// ----------------------------------
// RSDK Project: Sonic 2
// Script Description: Menu Control 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.scrollDelayUp
private alias object.value2 : object.scrollDelayDown
private alias object.value3 : object.currentSelection
private alias object.value4 : object.soundTestCooldown

private alias object.value0 : hexNo.number
private alias object.value1 : hexNo.highlighted

private alias 0 : MENUCONTROL_INIT
private alias 1 : MENUCONTROL_FADEIN
private alias 2 : MENUCONTROL_MAIN
private alias 3 : MENUCONTROL_LOADLEVEL
private alias 4 : MENUCONTROL_LOADSPECIAL

// The maximum number of selections available
// (Inclusive limit)
private alias 22 : MAX_SELECTION_COUNT

// Music Loops
private alias 152750 : MUSIC_LOOP_EHZ_1P
private alias 18671  : MUSIC_LOOP_MCZ_2P // This is 18672 in some other cases...
private alias 293572 : MUSIC_LOOP_OOZ
private alias 309378 : MUSIC_LOOP_MPZ
private alias 1      : MUSIC_LOOP_HTZ
private alias 1      : MUSIC_LOOP_ARZ
private alias 95868  : MUSIC_LOOP_CNZ_2P
private alias 62820  : MUSIC_LOOP_CNZ_1P
private alias 1      : MUSIC_LOOP_DEZ
private alias 99356  : MUSIC_LOOP_MCZ_1P
private alias 99572  : MUSIC_LOOP_EHZ_2P
private alias 198253 : MUSIC_LOOP_SCZ
private alias 684580 : MUSIC_LOOP_CPZ
private alias 99874  : MUSIC_LOOP_WFZ
private alias 59852  : MUSIC_LOOP_PPZ
private alias 496644 : MUSIC_LOOP_SPECIAL
private alias 38679  : MUSIC_LOOP_INV


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

reserve function MenuControl_HandleSecrets
reserve function MenuControl_SoundTestPlayer


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

public value MenuControl_optionsMenuOpen		= 0
private value MenuControl_optionsMenuCounter 	= 0
private value MenuControl_debugModeCounter 		= 0
private value MenuControl_emeraldCodeCounter 	= 0
private value MenuControl_continueCodeCounter 	= 0
private value MenuControl_PPZCodeCounter 		= 0


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

// Code to open the game config menu
private table MenuControl_OptionsMenu
	0, 0, 0
end table

// Code to enable debug mode
private table MenuControl_SecretDebugMode
	1, 9, 9, 2, 1, 1, 2, 4
end table

// Code to give all emeralds
private table MenuControl_SecretEmeralds
	4, 1, 2, 6
end table

// Code to give 14 continues
private table MenuControl_SecretContinues
	1, 1, 2, 4
end table

// Code to replace Hidden Palace Zone with Proto Palace Zone
private table MenuControl_SecretPPZ
	3, 3, 3, 11, 16, 16, 16, 4
end table


// This table holds data for every stage with six values for every stage, 
// -> First entry is menu table the stage option is on
// -> Second is what number this one is on the list, from top to bottom
// -> Third is the active stage list the stage is on
// -> Fourth is the stage's position in the stage list
// -> Fifth is the menu entry of what is on the opposite side of this selection, like how MTZ is to the right of EHZ and vice versa
// -> Sixth is the icon the entry uses

private table MenuControl_EntryTable
	0, 0,  1,  0, 14,  1	//  0 - Emerald Hill 1
	0, 1,  1,  1, 15,  1	//  1 - Emerald Hill 2
	0, 3,  1,  2, 17,  2	//  2 - Chemical Plant 1
	0, 4,  1,  3, 17,  2	//  3 - Chemical Plant 2
	0, 6,  1,  4, 18,  3	//  4 - Aquatic Ruin 1
	0, 7,  1,  5, 18,  3	//  5 - Aquatic Ruin 2
	0, 9,  1,  6, 19,  4	//  6 - Casino Night 1
	0, 10, 1,  7, 19,  4	//  7 - Casino Night 2
	0, 12, 1,  8, 20,  5	//  8 - Hill Top 1
	0, 13, 1,  9, 20,  5	//  9 - Hill Top 2
	0, 15, 1, 10, 21,  6	// 10 - Mystic Cave 1
	0, 16, 1, 11, 21,  6	// 11 - Mystic Cave 2
	0, 18, 1, 12, 22,  8	// 12 - Oil Ocean 1
	0, 19, 1, 13, 22,  8	// 13 - Oil Ocean 2
	1, 0,  1, 14,  0,  9	// 14 - Metropolis 1
	1, 1,  1, 15,  1,  9	// 15 - Metropolis 2
	1, 2,  1, 16,  2,  9	// 16 - Metropolis 3
	1, 3,  1, 17,  2, 10	// 17 - Sky Chase
	1, 6,  1, 18,  4, 11	// 18 - Wing Fortress
	1, 9,  1, 19,  6, 12	// 19 - Death Egg
	1, 12, 1, 20,  8,  7	// 20 - Hidden Palace (or Proto Palace)
	1, 15, 2,  0, 10, 13	// 21 - Special Stage
	1, 18, 0,  0, 67,  0 	// 22 - Sound Test
end table


// ========================
// Function Defintions
// ========================

private function MenuControl_HandleSecrets
	// Set the Special Stage act number, for acts 1-8
	if hexNo[+1].number < 8
		SetTableValue(hexNo[+1].number, 129, MenuControl_EntryTable)
	end if

	// Handle the options menu check
	GetTableValue(temp0, MenuControl_optionsMenuCounter, MenuControl_OptionsMenu)

	if temp0 == hexNo[+1].number
		MenuControl_optionsMenuCounter++
		if MenuControl_optionsMenuCounter == 3
			MenuControl_optionsMenuCounter = 0
	
			CreateTempObject(TypeName[Config Screen], 0, 0, 0)
			MenuControl_optionsMenuOpen = true
	
			PlaySfx(SfxName[Resume], false)
		end if
	else
		MenuControl_optionsMenuCounter = 0
	end if
	
	// Handle the debug mode code
	GetTableValue(temp0, MenuControl_debugModeCounter, MenuControl_SecretDebugMode)

	if temp0 == hexNo[+1].number
		MenuControl_debugModeCounter++
		if MenuControl_debugModeCounter == 8
			MenuControl_debugModeCounter = 0

			stage.debugMode = true

			PlaySfx(SfxName[Ring L], false)
		end if
	else
		MenuControl_debugModeCounter = 0
	end if

	// Handles the code for all emeralds
	GetTableValue(temp0, MenuControl_emeraldCodeCounter, MenuControl_SecretEmeralds)

	if temp0 == hexNo[+1].number
		MenuControl_emeraldCodeCounter++
		if MenuControl_emeraldCodeCounter == 4
			MenuControl_emeraldCodeCounter = 0

			// Give the player all 7 emeralds
			specialStage.emeralds = 127
			PlaySfx(SfxName[Emerald], false)
			StopMusic()
		end if
	else
		MenuControl_emeraldCodeCounter = 0
	end if

	if MenuControl_debugModeCounter < 2
		GetTableValue(temp0, MenuControl_continueCodeCounter, MenuControl_SecretContinues)
		if temp0 == hexNo[+1].number
			MenuControl_continueCodeCounter++
			if MenuControl_continueCodeCounter == 4
				MenuControl_continueCodeCounter = 0

				player.continues = 14
				PlaySfx(SfxName[Continue], false)
			end if
		else
			MenuControl_continueCodeCounter = 0
		end if
	else
		MenuControl_continueCodeCounter = 0
	end if
	
#platform: USE_ORIGINS
	// In place of unlocking PPZ, Origins added in some cool debug stuff instead
	CallNativeFunction4(NotifyCallback, NOTIFY_DEBUGPRINT, stage.debugMode, MenuControl_PPZCodeCounter, hexNo[+1].number)
#endplatform

	if stage.debugMode == true
		GetTableValue(temp0, MenuControl_PPZCodeCounter, MenuControl_SecretPPZ)
		if temp0 == hexNo[+1].number
			MenuControl_PPZCodeCounter++
			if MenuControl_PPZCodeCounter == 8
				MenuControl_PPZCodeCounter = 0

#platform: USE_STANDALONE
				// Change the Hidden Palace slot to use Proto Palace instead
				// (Origins removed this)
				SetTableValue(BONUS_STAGE, 122, MenuControl_EntryTable)
				SetTableValue(11, 123, MenuControl_EntryTable)
#endplatform

				PlaySfx(SfxName[Ring L], false)

				// Set the Hidden Palace unlock flag to true
				saveRAM[46] = true
			end if
		else
			MenuControl_PPZCodeCounter = 0
		end if
	end if
end function


private function MenuControl_SoundTestPlayer
	// Don't play songs in quick succession
	if object.soundTestCooldown == 0
		object.soundTestCooldown = 30

		switch hexNo[+1].number
		case 0
			break

		case 1
			SetMusicTrack("Results.ogg", 0, true)
			PlayMusic(0)
			break

		case 2
			SetMusicTrack("EmeraldHill.ogg", 0, MUSIC_LOOP_EHZ_1P)
			PlayMusic(0)
			break

		case 3
			SetMusicTrack("MysticCave2.ogg", 0, MUSIC_LOOP_MCZ_2P)
			PlayMusic(0)
			break

		case 4
			SetMusicTrack("OilOcean.ogg", 0, MUSIC_LOOP_OOZ)
			PlayMusic(0)
			break

		case 5
			SetMusicTrack("Metropolis.ogg", 0, MUSIC_LOOP_MPZ)
			PlayMusic(0)
			break

		case 6
			SetMusicTrack("HillTop.ogg", 0, MUSIC_LOOP_HTZ)
			PlayMusic(0)
			break

		case 7
			SetMusicTrack("AquaticRuin.ogg", 0, MUSIC_LOOP_ARZ)
			PlayMusic(0)
			break

		case 8
			SetMusicTrack("CasinoNight2.ogg", 0, MUSIC_LOOP_CNZ_2P)
			PlayMusic(0)
			break

		case 9
			SetMusicTrack("CasinoNight.ogg", 0, MUSIC_LOOP_CNZ_1P)
			PlayMusic(0)
			break

		case 10
			SetMusicTrack("DeathEgg.ogg", 0, MUSIC_LOOP_DEZ)
			PlayMusic(0)
			break

		case 11
			SetMusicTrack("MysticCave.ogg", 0, MUSIC_LOOP_MCZ_1P)
			PlayMusic(0)
			break

		case 12
			SetMusicTrack("EmeraldHill2.ogg", 0, MUSIC_LOOP_EHZ_2P)
			PlayMusic(0)
			break

		case 13
			SetMusicTrack("SkyChase.ogg", 0, MUSIC_LOOP_SCZ)
			PlayMusic(0)
			break

		case 14
			SetMusicTrack("ChemicalPlant.ogg", 0, MUSIC_LOOP_CPZ)
			PlayMusic(0)
			break

		case 15
			SetMusicTrack("WingFortress.ogg", 0, MUSIC_LOOP_WFZ)
			PlayMusic(0)
			break

		case 16
			SetMusicTrack("Extra.ogg", 0, MUSIC_LOOP_PPZ)
			PlayMusic(0)
			break

		case 17
			SetMusicTrack("Options.ogg", 0, true)
			PlayMusic(0)
			break

		case 18
			SetMusicTrack("SpecialStage.ogg", 0, MUSIC_LOOP_SPECIAL)
			PlayMusic(0)
			break

		case 19
			SetMusicTrack("Boss.ogg", 0, true)
			PlayMusic(0)
			break

		case 20
			SetMusicTrack("FinalBoss.ogg", 0, true)
			PlayMusic(0)
			break

		case 21
			SetMusicTrack("Ending.ogg", 0, false)
			PlayMusic(0)
			break

		case 22
			SetMusicTrack("Super.ogg", 0, true)
			PlayMusic(0)
			break

		case 23
			SetMusicTrack("Invincibility.ogg", 0, MUSIC_LOOP_INV)
			PlayMusic(0)
			break

		case 24
			PlaySfx(SfxName[Life], false)
			PauseMusic()
			ResetObjectEntity(26, TypeName[Music Event], 2, 0, 0)
			object[26].priority = PRIORITY_ACTIVE
			break

		case 25
			SetMusicTrack("TitleScreen.ogg", 0, false)
			PlayMusic(0)
			break

		case 26
			SetMusicTrack("ActComplete.ogg", 0, false)
			PlayMusic(0)
			break

		case 27
			SetMusicTrack("GameOver.ogg", 0, false)
			PlayMusic(0)
			break

		case 28
			SetMusicTrack("Continue.ogg", 0, false)
			PlayMusic(0)
			break

		case 29
			StopMusic()
			PlaySfx(SfxName[Emerald], false)
			break

		case 30
			SetMusicTrack("Credits.ogg", 0, false)
			PlayMusic(0)
			break

		case 31
			SetMusicTrack("Drowning.ogg", 0, false)
			PlayMusic(0)
			break
			
		end switch
	end if
end function


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

event ObjectUpdate
	// Setup the HexNo object
	object[+1].xpos = screen.xcenter
	object[+1].xpos += 118

	switch object.state
	case MENUCONTROL_INIT
		object.timer = 320
		SetScreenFade(0, 0, 0, object.timer)
		object[+1].ypos = 160
		object[+1].priority = PRIORITY_ACTIVE
		object.state++
		break

	case MENUCONTROL_FADEIN
		if object.timer > 0
			object.timer -= 16
		else
			PlayMusic(0)
			object.state++
		end if
		SetScreenFade(0, 0, 0, object.timer)
		break

	case MENUCONTROL_MAIN
		// Don't do any of this if the options menu is open
		if MenuControl_optionsMenuOpen == false
			if keyDown[0].down == true
				object.scrollDelayUp = 0
				object.scrollDelayDown++
				if object.scrollDelayDown == 1
					object.currentSelection++
				end if

				object.scrollDelayDown %= 12
			else
				if keyDown[0].up == true
					object.scrollDelayDown = 0
					object.scrollDelayUp++
					if object.scrollDelayUp == 1
						object.currentSelection--
					end if

					object.scrollDelayUp %= 12
				else
					object.scrollDelayUp = 0
					object.scrollDelayDown = 0
				end if
			end if

			if object.currentSelection > MAX_SELECTION_COUNT
				object.currentSelection = 0
			end if

			if object.currentSelection < 0
				object.currentSelection = MAX_SELECTION_COUNT
			end if

			temp0 = object.currentSelection
			temp0 *= 6
			temp0++
			GetTableValue(temp2, temp0, MenuControl_EntryTable)
			temp0 += 3
			GetTableValue(temp1, temp0, MenuControl_EntryTable)

			switch temp1
			default
				checkResult = keyPress[0].left
				checkResult |= keyPress[0].right

				if checkResult == true
					object.currentSelection = temp1
				end if

				hexNo[+1].highlighted = 0

				if keyPress[0].buttonA == true
					keyPress[0].start = true
				end if
				break

			case 67 // Sound test
				if object.soundTestCooldown > 0
					object.soundTestCooldown--
				end if

				hexNo[+1].highlighted = 16

				if keyPress[0].buttonA == true
					hexNo[+1].number += 16
				end if
				
				if keyPress[0].left == true
					hexNo[+1].number--
				end if
				
				if keyPress[0].right == true
					hexNo[+1].number++
				end if

				// Limit the number's maximum count
				hexNo[+1].number &= 31

				if keyPress[0].buttonB == true
					CallFunction(MenuControl_SoundTestPlayer)
					CallFunction(MenuControl_HandleSecrets)
				end if
				if keyPress[0].buttonC == true
					CallFunction(MenuControl_SoundTestPlayer)
					CallFunction(MenuControl_HandleSecrets)
				end if
				break
			end switch

			temp0 = object.currentSelection
			temp0 *= 6
			GetTableValue(temp1, temp0, MenuControl_EntryTable)
			temp0++

			if temp1 == MENU_1
				menu2.selection = -1
				GetTableValue(menu1.selection, temp0, MenuControl_EntryTable)
			else // MENU_2
				menu1.selection = -1
				GetTableValue(menu2.selection, temp0, MenuControl_EntryTable)
			end if

			// Set the preview image to what it should be
			temp0 += 4
			GetTableValue(BGAnimation_currentPreview, temp0, MenuControl_EntryTable)

			// Player selected the option?
			if keyPress[0].start == true

				// Special Stage
				if object.currentSelection == 21
					PlaySfx(SfxName[Warp], false)
					object.state = MENUCONTROL_LOADSPECIAL
					fadeColor = 208
					fadeColor <<= 16
					temp0 = 255
					temp0 <<= 8
					fadeColor += temp0
					fadeColor += 224
				else
					// Hidden Palace?
					if object.currentSelection == 20
						// See if the player has it unlocked
						if saveRAM[46] == true
							// Proceed and load the level like normal
							object.state = MENUCONTROL_LOADLEVEL
						else
							// Haven't played it legitimately yet, sorry...
							PlaySfx(SfxName[Fail], false)
						end if
					else
						// Normal stage - let the player proceed
						object.state = MENUCONTROL_LOADLEVEL
					end if
				end if
			end if
		end if
		break

	case MENUCONTROL_LOADLEVEL
		if object.timer < 256
			music.volume -= 10
			object.timer += 16
			SetScreenFade(0, 0, 0, object.timer)
		else
#platform: USE_ORIGINS
			CallNativeFunction2(NotifyCallback, NOTIFY_LEVEL_SELECT_MENU, 1)
			CallNativeFunction4(NotifyCallback, NOTIFY_PLAYER_SET, stage.playerListPos, stage.player2Enabled, 0)
#endplatform

			StopMusic()
			temp0 = object.currentSelection
			temp0 *= 6
			temp0 += 2
			GetTableValue(temp1, temp0, MenuControl_EntryTable)
			temp0++
			GetTableValue(temp2, temp0, MenuControl_EntryTable)
			stage.activeList = temp1
			stage.listPos = temp2
			LoadStage()
			SetScreenFade(0x00, 0x00, 0x00, 0xFF)
		end if
		break

	case MENUCONTROL_LOADSPECIAL
		if object.timer < 768
			music.volume -= 10
			object.timer += 8
			SetScreenFade(0xD0, 0xFF, 0xE0, object.timer)
		else
			StopMusic()
			temp0 = object.currentSelection
			temp0 *= 6
			temp0 += 2
			GetTableValue(temp1, temp0, MenuControl_EntryTable)
			temp0++
			GetTableValue(temp2, temp0, MenuControl_EntryTable)
			stage.activeList = temp1
			stage.listPos = temp2
			LoadStage()
			SetScreenFade(0xD0, 0xFF, 0xE0, 0xFF)
		end if
		break
		
	end switch
end event


event ObjectDraw
	// Two rows, two menus to be drawn
	
	temp0 = screen.xcenter
	temp0 -= 10
	DrawMenu(MENU_1, temp0, 16)

	temp0 = screen.xcenter
	temp0 += 142
	DrawMenu(MENU_2, temp0, 16)
end event


event ObjectStartup
	// Load the sprite sheet
	// No need to setup sprite frames since using the menu system will handle them automatically
	LoadSpriteSheet("LevelSelect/Text.gif")

	// All Menu Control objects should be active
	// -> Note that there should only ever be one of them in a scene, though
	foreach (TypeName[Menu Control], arrayPos0, ALL_ENTITIES)
		object[arrayPos0].priority = PRIORITY_ACTIVE
	next

#platform: USE_STANDALONE
	if stage.actNum < 3
		options.stageSelectFlag = true
	end if
#endplatform

	options.touchControls = false

	SetMusicTrack("Options.ogg", 0, true)

	// Setup menu 1 (left column)
	SetupMenu(MENU_1, 0, 3, 1)

	// Add the entries
	AddMenuEntry(MENU_1, "EMERALD HILL@@ 1", true)
	AddMenuEntry(MENU_1, "2", false)
	AddMenuEntry(MENU_1, " ", false)
	AddMenuEntry(MENU_1, "CHEMICAL PLANT 1", true)
	AddMenuEntry(MENU_1, "2", false)
	AddMenuEntry(MENU_1, " ", false)
	AddMenuEntry(MENU_1, "AQUATIC RUIN@@ 1", true)
	AddMenuEntry(MENU_1, "2", false)
	AddMenuEntry(MENU_1, " ", false)
	AddMenuEntry(MENU_1, "CASINO NIGHT@@ 1", true)
	AddMenuEntry(MENU_1, "2", false)
	AddMenuEntry(MENU_1, " ", false)
	AddMenuEntry(MENU_1, "HILL TOP@@@@@@ 1", true)
	AddMenuEntry(MENU_1, "2", false)
	AddMenuEntry(MENU_1, " ", false)
	AddMenuEntry(MENU_1, "MYSTIC CAVE@@@ 1", true)
	AddMenuEntry(MENU_1, "2", false)
	AddMenuEntry(MENU_1, " ", false)
	AddMenuEntry(MENU_1, "OIL OCEAN@@@@@ 1", true)
	AddMenuEntry(MENU_1, "2", false)
	AddMenuEntry(MENU_1, " ", false)

	// Setup menu 2 (right column)
	SetupMenu(MENU_2, 0, 3, 1)

	// Add its entries
	AddMenuEntry(MENU_2, "METROPOLIS@@@@ 1", true)
	AddMenuEntry(MENU_2, "2", false)
	AddMenuEntry(MENU_2, "3", false)
	AddMenuEntry(MENU_2, "SKY CHASE@@@@@@@", true)
	AddMenuEntry(MENU_2, " ", false)
	AddMenuEntry(MENU_2, " ", false)
	AddMenuEntry(MENU_2, "WING FORTRESS@@@", true)
	AddMenuEntry(MENU_2, " ", false)
	AddMenuEntry(MENU_2, " ", false)
	AddMenuEntry(MENU_2, "DEATH EGG@@@@@@@", true)
	AddMenuEntry(MENU_2, " ", false)
	AddMenuEntry(MENU_2, " ", false)
	AddMenuEntry(MENU_2, "HIDDEN PALACE@@@", true)
	AddMenuEntry(MENU_2, " ", 0)
	AddMenuEntry(MENU_2, " ", 0)
	AddMenuEntry(MENU_2, "SPECIAL STAGE@@@", true)
	AddMenuEntry(MENU_2, " ", false)
	AddMenuEntry(MENU_2, " ", false)
	AddMenuEntry(MENU_2, "SOUND TEST@ *@@*", true)

	menu1.selection = 0
	menu2.selection = -1
	
	// Not in the original, but origins compiler swaps the value of SPECIAL_STAGE to 2 (rather than 3 originally)
	temp0 = 21
	temp0 *= 6
	temp0 += 2
	SetTableValue(SPECIAL_STAGE, temp0, MenuControl_EntryTable)
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
