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

// TODO: check out its scale attr in stuff like m104, ain't that strange?

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

// Variables
private alias object.value0 : object.centerInit
private alias object.value1 : object.spinCount
private alias object.value2 : object.spinTimer
private alias object.value3 : object.activePlayers
private alias object.value4 : object.allPlayersFinished
private alias object.value5 : object.lastPlayerID
private alias object.value6 : object.centerOffset	 // x center offset
private alias object.value7 : object.enableExitRight // determines if the exit stage right sequence should occur

// States
private alias 0 : SIGNPOST2_IDLE
private alias 1 : SIGNPOST2_SPUN
private alias 2 : SIGNPOST2_EXITPLAYER
private alias 3 : SIGNPOST2_IDLE_VS
private alias 4 : SIGNPOST2_SPUN_VS
private alias 5 : SIGNPOST2_UNUSED
private alias 6 : SIGNPOST2_FINISHED

// Player Aliases
private alias object.type 			: player.type
private alias object.propertyValue 	: player.character
private alias object.xpos 			: player.xpos
private alias object.ypos 			: player.ypos
private alias object.ixpos			: player.ixpos
private alias object.speed 			: player.speed
private alias object.xvel 			: player.xvel
private alias object.controlMode 	: player.controlMode
private alias object.scrollTracking : player.scrollTracking
private alias object.interaction 	: player.interaction
private alias object.jumpPress 		: player.jumpPress
private alias object.jumpHold 		: player.jumpHold
private alias object.up 			: player.up
private alias object.down 			: player.down
private alias object.left 			: player.left
private alias object.right 			: player.right
private alias object.value7 		: player.invincibleTimer
private alias object.value21 		: player.acceleration

private alias 1 : SUPERSTATE_SUPER
private alias 2 : SUPERSTATE_FADEOUT

// VSGame aliases
private alias object.value0 : vsGame.timer
private alias object.value5 : vsGame.countdownPlayer

// VSGame States
private alias 0 : VSGAME_DISPLAYTAGS
private alias 2 : VSGAME_FADEOUT
private alias 3 : VSGAME_FINISH_COUNTDOWN
private alias 4 : VSGAME_GOTOVSRESULTS

// Game Modes
private alias 2 : MODE_TIMEATTACK

// Tracks
private alias 1 : TRACK_ACTFINISH

// Achievement Aliases
private alias  0 : ACHIEVEMENT_QUICKRUN
private alias  3 : ACHIEVEMENT_SUPERSTAR
private alias 10 : ACHIEVEMENT_SCRAMBLEDEGG

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

reserve function SignPost2_DebugDraw
reserve function SignPost2_DebugSpawn


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

private function SignPost2_DebugDraw
	DrawSprite(0)
	DrawSprite(1)
end function


private function SignPost2_DebugSpawn
	CreateTempObject(TypeName[Sign Post2], 0, object.xpos, object.ypos)
	object[tempObjectPos].frame = 1
	object[tempObjectPos].spinCount = 16
	if options.vsMode == true
		object[tempObjectPos].state = SIGNPOST2_IDLE_VS
	end if
end function


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

event ObjectUpdate
	switch object.state
	case SIGNPOST2_IDLE
		temp0 = object.ypos
		temp0 += 0x400000
		if player[0].ypos < temp0
			if object.centerOffset > 0
				temp0 = object.ixpos
				temp0 -= player[0].ixpos
				CheckGreater(temp0, 0)
				temp1 = checkResult
				CheckLower(temp0, object.centerOffset)
				checkResult &= temp1
				if checkResult == true
					stage.newXBoundary1 = object.ixpos
					stage.newXBoundary1 -= object.centerOffset
					stage.newXBoundary2 = object.xpos
					stage.newXBoundary2 >>= 16
					stage.newXBoundary2 += screen.xcenter
				end if
			else
				stage.newXBoundary1 = object.xpos
				stage.newXBoundary1 >>= 16
				stage.newXBoundary1 -= screen.xcenter
				stage.newXBoundary1 -= screen.xcenter
				stage.newXBoundary2 = object.xpos
				stage.newXBoundary2 >>= 16
				stage.newXBoundary2 += screen.xcenter
			end if

			if player[0].xpos > object.xpos
				stage.newXBoundary1 = object.xpos
				stage.newXBoundary1 >>= 16
				stage.newXBoundary1 -= screen.xcenter
				
				switch player[0].character
				case PLAYER_SONIC_ALONE
					EditFrame(5, -24, -16, 48, 32, 34, 1)
					break

				case PLAYER_TAILS_ALONE
					EditFrame(5, -24, -16, 48, 32, 34, 34)
					break

				case PLAYER_KNUX_ALONE
					EditFrame(5, -24, -16, 48, 32, 34, 67)
					break

				end switch

				// No achievements in debug mode!
				if stage.debugMode == false
					if stage.activeList == BONUS_STAGE
						// Boss Attack is on the Bonus Stage list, check for the Boss Attack achievement
						// (In Origins all the Missions are on the Bonus stage list too, so this check can reward the achievement for them as well lol)
						if stage.minutes < 7
							CallNativeFunction2(SetAchievement, ACHIEVEMENT_SCRAMBLEDEGG, 100)
						end if
					else
						if stage.listPos == 0
							if stage.minutes == 0
								if stage.seconds < 35
									CallNativeFunction2(SetAchievement, ACHIEVEMENT_QUICKRUN, 100)
								end if
							end if
						end if
					end if
				end if

				CallNativeFunction2(NotifyCallback, NOTIFY_TOUCH_SIGNPOST, 0)

				stage.timeEnabled = false
				object.state = SIGNPOST2_SPUN
				PlaySfx(SfxName[Sign Post], false)
				
				if Player_superState == SUPERSTATE_SUPER
					Player_superState = SUPERSTATE_FADEOUT
					if stage.debugMode == false
						CallNativeFunction2(SetAchievement, ACHIEVEMENT_SUPERSTAR, 100)
					end if
				end if
			end if
		end if
		break
		
	case SIGNPOST2_SPUN
		music.volume--

		object.spinTimer++
		if object.spinTimer == 2
			object.spinTimer = 0
			object.frame++
			if object.frame == 5
				object.frame = 1
				Rand(temp0, 48)
				temp0 <<= 16
				temp0 += object.xpos
				temp0 -= 0x180000
				Rand(temp1, 32)
				temp1 <<= 16
				temp1 += object.ypos
				temp1 -= 0x140000
				CreateTempObject(TypeName[Ring Sparkle], 0, temp0, temp1)

				object.spinCount--
				if object.spinCount == 0
					if object.enableExitRight != false
						SetBit(object.activePlayers, 0, true)
						if stage.player2Enabled == true
							SetBit(object.activePlayers, 1, true)
						end if
					else
						player[0].interaction = false
						player[0].controlMode = CONTROLMODE_NONE
						player[0].up = false
						player[0].down = false
						player[0].left = false
						player[0].right = false
						player[0].jumpPress = false
						player[0].jumpHold = false
					end if
					object.state = SIGNPOST2_EXITPLAYER
				end if
			end if
		end if
		break

	case SIGNPOST2_EXITPLAYER
		temp0 = screen.xcenter
		temp0 <<= 16
		temp0 += object.xpos
		CheckGreater(player[0].xpos, temp0)
		temp1 = checkResult
		CheckEqual(object.enableExitRight, false)
		checkResult |= temp1
		if checkResult == true
			PlayMusic(TRACK_ACTFINISH)
			object.state = SIGNPOST2_FINISHED
			object[30].type = TypeName[Act Finish]
			object[30].drawOrder = 6
			object[30].priority = PRIORITY_ACTIVE
		end if
		break

	case SIGNPOST2_IDLE_VS
		stage.newXBoundary2 = object.xpos
		stage.newXBoundary2 >>= 16
		stage.newXBoundary2 += screen.xcenter
		foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
			GetBit(temp1, object.activePlayers, currentPlayer)
			if temp1 == false
				if player[currentPlayer].xpos > object.xpos
					object.priority = PRIORITY_ACTIVE
					
					SetBit(object.activePlayers, currentPlayer, true)
					
					if currentPlayer == 0
						if Player_superState == SUPERSTATE_SUPER
							Player_superState = SUPERSTATE_FADEOUT
						end if

						if vs.playerID == 0
							temp2 = 0
						else
							temp2 = 1
						end if
					else
						if vs.playerID == 0
							temp2 = 1
						else
							temp2 = 0
						end if
					end if

					if temp2 == 0
						vs.time1P = stage.milliSeconds
						vs.time1P = stage.seconds
						vs.time1P *= 100
						temp2 = stage.minutes
						temp2 *= 6000
						vs.time1P += temp2
						vs.time1P += stage.milliSeconds
					else
						vs.time2P = stage.milliSeconds
						vs.time2P = stage.seconds
						vs.time2P *= 100
						temp2 = stage.minutes
						temp2 *= 6000
						vs.time2P += temp2
						vs.time2P += stage.milliSeconds
					end if

					object.lastPlayerID = currentPlayer
					object.spinCount = 16
					object.state = SIGNPOST2_SPUN_VS
					PlaySfx(SfxName[Sign Post], false)

					if object.allPlayersFinished == false
						PlaySfx(SfxName[Sign Post 2P], false)
						object[30].state = VSGAME_FINISH_COUNTDOWN
						vsGame[30].countdownPlayer = currentPlayer
						vsGame[30].countdownPlayer ^= 1
						
						switch player[currentPlayer].character
						case PLAYER_SONIC_ALONE
							EditFrame(5, -24, -16, 48, 32, 34, 1)
							break

						case PLAYER_TAILS_ALONE
							EditFrame(5, -24, -16, 48, 32, 34, 34)
							break

						case PLAYER_KNUX_ALONE
							EditFrame(5, -24, -16, 48, 32, 34, 67)
							break

						end switch
					else
						object[30].state = VSGAME_DISPLAYTAGS
					end if

					if object.activePlayers == 3
						object.allPlayersFinished	= true
						object[30].state 			= VSGAME_DISPLAYTAGS
					end if
				end if
			end if
		next
		break

	case SIGNPOST2_SPUN_VS
		if object.allPlayersFinished == true
			music.volume--
		else
			foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
				GetBit(temp1, object.activePlayers, currentPlayer)
				if temp1 == false
					if player[currentPlayer].xpos > object.xpos
						object.spinTimer	= 1
						object.frame 	 	= 4
						object.spinCount 	= 1
					end if
				end if
			next
		end if

		object.spinTimer++
		if object.spinTimer == 2
			object.spinTimer = 0
			object.frame++
			if object.frame == 5
				object.frame = 1
				Rand(temp0, 48)
				temp0 <<= 16
				temp0 += object.xpos
				temp0 -= 0x180000
				Rand(temp1, 32)
				temp1 <<= 16
				temp1 += object.ypos
				temp1 -= 0x140000
				CreateTempObject(TypeName[Ring Sparkle], 0, temp0, temp1)
				
				object.spinCount--
				if object.spinCount == 0
					if object.allPlayersFinished == false
						object.allPlayersFinished = true
						object.state = SIGNPOST2_IDLE_VS
					else
						object.state = SIGNPOST2_FINISHED
						object[30].state = VSGAME_GOTOVSRESULTS
						vsGame[30].timer = -768
					end if
				end if
			end if
		end if
		break

	case SIGNPOST2_FINISHED
		break

	default
	case SIGNPOST2_UNUSED
		break
		
	end switch
	
	// Invisible off-screen barrier
	temp0 = 40
	temp0 += 212
	temp0 <<= 16
	temp0 += object.xpos
	currentPlayer = 0
	while currentPlayer < playerCount
		GetBit(temp1, object.activePlayers, currentPlayer)
		if temp1 == true
			player[currentPlayer].interaction 	= false
			player[currentPlayer].controlMode 	= CONTROLMODE_NONE
			player[currentPlayer].up 			= false
			player[currentPlayer].down 			= false
			player[currentPlayer].left 			= false
			player[currentPlayer].right 		= true
			player[currentPlayer].jumpPress 	= false
			player[currentPlayer].jumpHold 		= false
		end if

		if player[currentPlayer].xpos > temp0
			player[currentPlayer].xpos 	= temp0
			player[currentPlayer].speed = 0
			player[currentPlayer].xvel 	= 0
		end if

		if player[currentPlayer].type == TypeName[Debug Mode]
			SetBit(object.activePlayers, currentPlayer, false)
		end if
		currentPlayer++
	loop
	
	if object.state > SIGNPOST2_IDLE
		player[0].invincibleTimer = 80
	end if
end event


event ObjectDraw
	DrawSprite(0)
	if object.spinCount > 8
		DrawSprite(object.frame)
	else
		temp0 = object.frame
		temp0 += 4
		DrawSprite(temp0)
	end if
end event


event ObjectStartup
	LoadSpriteSheet("Global/Items2.gif")
	
	SpriteFrame(-24, 16, 48, 16, 34, 132)
	SpriteFrame(-24, -16, 48, 32, 34, 100)
	SpriteFrame(-16, -16, 32, 32, 149, 99)
	SpriteFrame(-4, -16, 8, 32, 247, 2)
	SpriteFrame(-16, -16, 32, 32, 116, 99)
	SpriteFrame(-24, -16, 48, 32, 34, 1)
	SpriteFrame(-16, -16, 32, 32, 149, 99)
	SpriteFrame(-4, -16, 8, 32, 247, 2)
	SpriteFrame(-16, -16, 32, 32, 116, 99)

	foreach (TypeName[Sign Post2], arrayPos0, ALL_ENTITIES)
		CheckGreater(object[arrayPos0].propertyValue, 0)
		temp0 = checkResult
		CheckEqual(options.vsMode, false)
		temp0 &= checkResult
		if temp0 == true
			object[arrayPos0].type = TypeName[Blank Object]
		else
			// Editors can only set object values 0-3, so set value6 to value0 and then reset value0
			// ...they could've just used value0 for the actual offset value though, it's not used for anything else in this object
			object[arrayPos0].centerOffset = object[arrayPos0].centerInit
			object[arrayPos0].centerOffset <<= 4
			object[arrayPos0].centerInit = 0
			
			// Same thing here, set value7 to value1 and reset value1
			object[arrayPos0].enableExitRight = object[arrayPos0].spinCount
			object[arrayPos0].spinCount = 0
			
			object[arrayPos0].frame = 1
			object[arrayPos0].spinCount = 16
			if object[arrayPos0].propertyValue != 2
				object[arrayPos0].priority = PRIORITY_XBOUNDS
			end if
		end if

		if options.vsMode == true
			object[arrayPos0].state = SIGNPOST2_IDLE_VS
		end if
	next

	SetTableValue(TypeName[Sign Post2], DebugMode_ObjCount, DebugMode_TypesTable)
	SetTableValue(SignPost2_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
	SetTableValue(SignPost2_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
	DebugMode_ObjCount++
end event


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

event RSDKEdit
	if editor.returnVariable == true
		switch editor.variableID
		case EDIT_VAR_PROPVAL // property value
			checkResult = object.propertyValue
			break
			
		case 0 // type
			checkResult = object.propertyValue
			break
			
		end switch
	else
		switch editor.variableID
		case EDIT_VAR_PROPVAL // property value
			object.propertyValue = editor.variableValue
			break
			
		case 0 // type
			object.propertyValue = editor.variableValue
			break
			
		end switch
	end if
end event


event RSDKDraw
	DrawSprite(0)
	DrawSprite(1)
end event


event RSDKLoad
	LoadSpriteSheet("Global/Items2.gif")
	SpriteFrame(-24, 16, 48, 16, 34, 132)
	SpriteFrame(-24, -16, 48, 32, 34, 100)

	AddEditorVariable("type")
	SetActiveVariable("type")
	AddEnumVariable("Normal", 0)
	AddEnumVariable("VS Only (No Y Bounds)", 1)
	AddEnumVariable("VS Only (Use Y Bounds)", 2)
	
	SetVariableAlias(ALIAS_VAR_VAL0, "centerOffset")
	SetVariableAlias(ALIAS_VAR_VAL1, "enableExitRight")
end event
