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

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

private alias object.value1  : object.bgWaterPaletteTimer
private alias object.value4  : object.deformTimer

private alias object.value5  : object.bgLightDuration
private alias object.value6  : object.bgLightFrame

private alias object.value7  : object.pinkFlowerDuration
private alias object.value8  : object.pinkFlowerFrame

private alias object.value9  : object.redFlowerDuration
private alias object.value10 : object.redFlowerFrame

private alias object.value11 : object.rectFlowerDuration
private alias object.value12 : object.rectFlowerFrame

private alias object.value13 : object.pointyFlowerDuration
private alias object.value14 : object.pointyFlowerFrame

// Game Modes
private alias 0 : MODE_NOSAVE
private alias 1 : MODE_SAVEGAME
private alias 2 : MODE_TIMEATTACK

// Tracks
private alias 0 : TRACK_STAGE
private alias 1 : TRACK_ACTFINISH
private alias 2 : TRACK_INVINCIBLE
private alias 3 : TRACK_CONTINUE
private alias 4 : TRACK_BOSS
private alias 5 : TRACK_GAMEOVER
private alias 6 : TRACK_DROWNING
private alias 7 : TRACK_SUPER

// Reserved object slots
private alias 10 : SLOT_ZONESETUP
private alias 25 : SLOT_MUSICEVENT_CHANGE
private alias 26 : SLOT_MUSICEVENT_BOSS

// Music Events
private alias 2 : MUSICEVENT_TRANSITION

private alias 0 : MUSICEVENT_FLAG_NOCHANGE
private alias 1 : MUSICEVENT_FLAG_SPEEDUP
private alias 2 : MUSICEVENT_FLAG_SLOWDOWN

// Music Loops
private alias 152750 : MUSIC_LOOP_EHZ_1P
private alias 122240 : MUSIC_LOOP_EHZ_1P_F

private alias 99572  : MUSIC_LOOP_EHZ_2P
private alias 79604  : MUSIC_LOOP_EHZ_2P_F

private alias 38679  : MUSIC_LOOP_INV
private alias 30897  : MUSIC_LOOP_INV_F

// Achievement Aliases
private alias 2 : ACHIEVEMENT_EARLYBIRDSPECIAL


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

reserve function EHZSetup_SpeedUpMusic1P
reserve function EHZSetup_SlowDownMusic1P
reserve function EHZSetup_SpeedUpMusic2P
reserve function EHZSetup_SlowDownMusic2P


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

private value EHZSetup_hasAchievement = 0


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

private table EHZSetup_bgLightFrameTable
	508, 24
	509, 10
	510, 12
	511, 24
	510, 12
	509, 10
end table

private table EHZSetup_pinkFlowerFrameTable
	512, 128
	513, 20
	512, 8
	513, 8
	512, 8
	513, 8
end table

private table EHZSetup_redFlowerFrameTable
	514, 128
	515, 12
	514, 12
	515, 12
	514, 6
	515, 6
	514, 6
	515, 6
end table

private table EHZSetup_rectFlowerFrameTable
	516, 8
	517, 8
end table

private table EHZSetup_pointyFlowerFrameTable
	518, 128
	519, 8
	518, 8
	519, 8
	518, 8
	519, 12
	518, 12
	519, 12
end table

private table EHZSetup_deformationTable
	1, 2, 1, 3, 1, 2, 2, 1, 2, 3, 1, 2, 1, 2, 0, 0
	2, 0, 3, 2, 2, 3, 2, 2, 1, 3, 0, 0, 1, 0, 1, 3
	1, 2, 1, 3, 1, 2, 2, 1, 2, 3, 1, 2, 1, 2, 0, 0
	2, 0, 3, 2, 2, 3, 2, 2, 1, 3, 0, 0, 1, 0, 1, 3
end table

private table EHZSetup_replay_attract_S
	0x440000, 0x2910000
	0x20, 1
	0x28, 27
	0x08, 39
	0x38, 1
	0x28, 9
	0x08, 40
	0x38, 1
	0x28, 6
	0x08, 8
	0x38, 1
	0x28, 6
	0x08, 175
	0x38, 1
	0x28, 7
	0x08, 111
	0x00, 2
	0x04, 35
	0x34, 1
	0x24, 7
	0x04, 73
	0x00, 4
	0x08, 4
	0x38, 1
	0x28, 7
	0x08, 68
	0x00, 5
	0x04, 30
	0x00, 8
	0x02, 4
	0x32, 1
	0x22, 1
	0x32, 1
	0x20, 4
	0x00, 15
	0x08, 56
	0x00, 1
	0x02, 32
	0x32, 1
	0x22, 1
	0x2A, 1
	0x28, 3
	0x08, 255
	0x08, 97
	0x00, 12
	0x04, 5
	0x00, 26
	0x08, 21
	0x38, 1
	0x28, 9
	0x08, 255
	0x08, 4
	0x0A, 3
	0x02, 7
	0x0A, 2
end table

private table EHZSetup_replay_attract_T
	0x440000, 0x2950000
	0x20, 13
	0x28, 38
	0x08, 47
	0x38, 1
	0x28, 12
	0x08, 224
	0x38, 1
	0x28, 5
	0x08, 69
	0x38, 1
	0x28, 8
	0x20, 2
	0x00, 2
	0x08, 12
	0x00, 28
	0x08, 16
	0x00, 1
	0x08, 255
	0x08, 5
	0x38, 1
	0x28, 24
	0x08, 218
	0x38, 1
	0x28, 9
	0x08, 50
	0x00, 1
	0x04, 7
	0x00, 16
	0x08, 174
	0x38, 1
	0x28, 12
	0x08, 7
	0x38, 1
	0x28, 8
	0x08, 4
	0x38, 1
	0x28, 5
	0x08, 3
	0x04, 2
	0x34, 1
	0x24, 5
	0x04, 4
	0x34, 1
	0x20, 5
	0x00, 4
	0x04, 1
	0x34, 1
	0x24, 3
	0x04, 4
	0x34, 1
	0x24, 4
	0x04, 5
	0x34, 1
	0x24, 3
	0x04, 1
	0x00, 2
	0x08, 2
	0x38, 1
	0x28, 3
	0x20, 2
	0x00, 1
	0x08, 5
	0x00, 5
	0x08, 3
	0x38, 1
	0x28, 2
	0x08, 1
	0x00, 9
	0x08, 5
	0x00, 15
	0x08, 22
	0x00, 3
	0x04, 2
	0x34, 1
	0x24, 9
	0x20, 2
	0x28, 8
	0x08, 4
	0x38, 1
	0x28, 4
	0x20, 1
	0x00, 3
	0x30, 1
	0x20, 6
	0x00, 4
	0x30, 1
	0x20, 5
	0x00, 1
	0x08, 3
	0x00, 1
	0x30, 1
	0x20, 5
	0x00, 3
	0x30, 1
	0x20, 3
	0x28, 3
	0x08, 2
	0x00, 1
	0x30, 1
	0x20, 5
	0x00, 5
	0x30, 1
	0x20, 4
	0x00, 4
	0x30, 1
	0x20, 4
	0x00, 5
	0x30, 1
	0x20, 4
	0x00, 4
	0x30, 1
	0x20, 5
	0x00, 4
	0x30, 1
	0x20, 4
	0x00, 5
	0x30, 1
	0x20, 4
	0x00, 5
	0x30, 1
	0x20, 4
	0x00, 5
	0x30, 1
	0x20, 5
	0x00, 3
	0x30, 1
	0x20, 4
	0x00, 4
	0x30, 1
	0x20, 5
	0x00, 3
	0x30, 1
	0x20, 5
	0x00, 3
	0x30, 1
	0x20, 6
	0x00, 3
	0x30, 1
	0x20, 4
	0x00, 4
	0x30, 1
	0x20, 4
	0x00, 4
	0x30, 1
	0x20, 4
	0x00, 4
	0x30, 1
	0x20, 4
	0x28, 2
	0x08, 39
	0x38, 1
	0x28, 12
	0x08, 13
	0x00, 17
	0x08, 4
	0x00, 12
	0x04, 11
	0x08, 8
end table

private table EHZSetup_replay_attract_K
	0x440000, 0x2910000
	0x00, 18
	0x08, 77
	0x38, 1
	0x28, 13
	0x08, 70
	0x38, 1
	0x28, 14
	0x08, 3
	0x00, 22
	0x04, 4
	0x00, 3
	0x30, 1
	0x20, 16
	0x28, 3
	0x08, 1
	0x00, 30
	0x30, 1
	0x20, 38
	0x28, 149
	0x08, 11
	0x00, 3
	0x04, 6
	0x00, 4
	0x04, 5
	0x00, 5
	0x08, 13
	0x00, 14
	0x04, 89
	0x00, 6
	0x08, 44
	0x0A, 1
	0x02, 13
	0x00, 52
	0x08, 59
	0x38, 1
	0x28, 17
	0x08, 18
	0x00, 4
	0x04, 33
	0x00, 1
	0x08, 105
	0x38, 1
	0x28, 30
	0x08, 45
	0x04, 6
	0x00, 52
	0x08, 6
	0x38, 1
	0x28, 19
	0x08, 54
	0x0A, 6
	0x02, 17
	0x0A, 2
	0x08, 58
	0x38, 1
	0x28, 4
	0x08, 197
	0x38, 1
	0x29, 10
	0x09, 14
	0x39, 1
	0x29, 40
	0x21, 4
	0x01, 126
	0x09, 12
	0x08, 6
	0x38, 1
	0x28, 12
end table


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

private function EHZSetup_SpeedUpMusic1P
	CheckEqual(object[SLOT_MUSICEVENT_CHANGE].type, TypeName[Music Event])
	temp0 = checkResult
	CheckEqual(object[SLOT_MUSICEVENT_CHANGE].propertyValue, MUSICEVENT_TRANSITION)
	temp0 &= checkResult
	CheckEqual(stage.musicFlag, MUSICEVENT_FLAG_NOCHANGE)
	temp0 &= checkResult
	if temp0 == false
		switch music.currentTrack
		case TRACK_STAGE
			SetMusicTrack("Invincibility_F.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV_F)
			SwapMusicTrack("EmeraldHill_F.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_1P_F, 8000)
			break

		case TRACK_INVINCIBLE
			SetMusicTrack("EmeraldHill_F.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_1P_F)
			SwapMusicTrack("Invincibility_F.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV_F, 8000)
			break

		case TRACK_BOSS
		case TRACK_DROWNING
		case TRACK_SUPER
			SetMusicTrack("EmeraldHill_F.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_1P_F)
			SetMusicTrack("Invincibility_F.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV_F)
			break
			
		end switch
	else
		stage.musicFlag = MUSICEVENT_FLAG_SPEEDUP
	end if
end function


private function EHZSetup_SlowDownMusic1P
	CheckEqual(object[SLOT_MUSICEVENT_CHANGE].type, TypeName[Music Event])
	temp0 = checkResult
	CheckEqual(object[SLOT_MUSICEVENT_CHANGE].propertyValue, MUSICEVENT_TRANSITION)
	temp0 &= checkResult
	CheckEqual(stage.musicFlag, MUSICEVENT_FLAG_NOCHANGE)
	temp0 &= checkResult
	if temp0 == false
		switch music.currentTrack
		case TRACK_STAGE
			SetMusicTrack("Invincibility.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV)
			SwapMusicTrack("EmeraldHill.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_1P, 12500)
			break

		case TRACK_INVINCIBLE
			SetMusicTrack("EmeraldHill.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_1P)
			SwapMusicTrack("Invincibility.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV, 12500)
			break

		case TRACK_BOSS
		case TRACK_DROWNING
		case TRACK_SUPER
			SetMusicTrack("EmeraldHill.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_1P)
			SetMusicTrack("Invincibility.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV)
			break
			
		end switch
	else
		stage.musicFlag = MUSICEVENT_FLAG_SLOWDOWN
	end if
end function


private function EHZSetup_SpeedUpMusic2P
	CheckEqual(object[SLOT_MUSICEVENT_CHANGE].type, TypeName[Music Event])
	temp0 = checkResult
	CheckEqual(object[SLOT_MUSICEVENT_CHANGE].propertyValue, MUSICEVENT_TRANSITION)
	temp0 &= checkResult
	CheckEqual(stage.musicFlag, MUSICEVENT_FLAG_NOCHANGE)
	temp0 &= checkResult
	if temp0 == false
		switch music.currentTrack
		case TRACK_STAGE
			SetMusicTrack("Invincibility_F.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV_F)
			SwapMusicTrack("EmeraldHill2_F.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_2P_F, 8000)
			break

		case TRACK_INVINCIBLE
			SetMusicTrack("EmeraldHill2_F.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_2P_F)
			SwapMusicTrack("Invincibility_F.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV_F, 8000)
			break

		case TRACK_BOSS
		case TRACK_DROWNING
		case TRACK_SUPER
			SetMusicTrack("EmeraldHill2_F.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_2P_F)
			SetMusicTrack("Invincibility_F.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV_F)
			break
			
		end switch
	else
		stage.musicFlag = MUSICEVENT_FLAG_SPEEDUP
	end if
end function


private function EHZSetup_SlowDownMusic2P
	CheckEqual(object[SLOT_MUSICEVENT_CHANGE].type, TypeName[Music Event])
	temp0 = checkResult
	CheckEqual(object[SLOT_MUSICEVENT_CHANGE].propertyValue, MUSICEVENT_TRANSITION)
	temp0 &= checkResult
	CheckEqual(stage.musicFlag, MUSICEVENT_FLAG_NOCHANGE)
	temp0 &= checkResult
	if temp0 == false
		switch music.currentTrack
		case TRACK_STAGE
			SetMusicTrack("Invincibility.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV)
			SwapMusicTrack("EmeraldHill2.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_2P, 12500)
			break

		case TRACK_INVINCIBLE
			SetMusicTrack("EmeraldHill2.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_2P)
			SwapMusicTrack("Invincibility.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV, 12500)
			break

		case TRACK_BOSS
		case TRACK_DROWNING
		case TRACK_SUPER
			SetMusicTrack("EmeraldHill2.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_2P)
			SetMusicTrack("Invincibility.ogg", TRACK_INVINCIBLE, MUSIC_LOOP_INV)
			break
			
		end switch
	else
		stage.musicFlag = MUSICEVENT_FLAG_SLOWDOWN
	end if
end function


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

event ObjectUpdate
	// What's this check supposed to be?
	// This object's state always seems to be 0, and 5 is such a strange number...
	// (S1's GHZ Setup had this same state check too and it made just as little sense there, as well...)
	if object.state < 5
		object.bgWaterPaletteTimer++
		if object.bgWaterPaletteTimer == 8
			object.bgWaterPaletteTimer = 0
			GetPaletteEntry(0, 159, temp1)

			GetPaletteEntry(0, 158, temp0)
			SetPaletteEntry(0, 159, temp0)

			GetPaletteEntry(0, 148, temp0)
			SetPaletteEntry(0, 158, temp0)

			GetPaletteEntry(0, 147, temp0)
			SetPaletteEntry(0, 148, temp0)

			SetPaletteEntry(0, 147, temp1)
		end if
	end if
	
	// Update the shimmering water in the background
	object.deformTimer++
	if object.deformTimer > 7
		tileLayer[1].deformationOffset++
		object.deformTimer = 0
	end if

	if object.bgLightDuration < 2
		GetTableValue(temp0, object.bgLightFrame, EHZSetup_bgLightFrameTable)

		Copy16x16Tile(502, temp0)
		temp0 += 12

		Copy16x16Tile(503, temp0)
		temp0 += 4

		Copy16x16Tile(504, temp0)
		object.bgLightFrame++
		
		GetTableValue(object.bgLightDuration, object.bgLightFrame, EHZSetup_bgLightFrameTable)
		object.bgLightFrame++

		object.bgLightFrame %= 12
	else
		object.bgLightDuration--
	end if

	if object.pinkFlowerDuration < 2
		GetTableValue(temp0, object.pinkFlowerFrame, EHZSetup_pinkFlowerFrameTable)

		Copy16x16Tile(764, temp0)
		object.pinkFlowerFrame++

		GetTableValue(object.pinkFlowerDuration, object.pinkFlowerFrame, EHZSetup_pinkFlowerFrameTable)
		object.pinkFlowerFrame++

		object.pinkFlowerFrame %= 12
	else
		object.pinkFlowerDuration--
	end if

	if object.redFlowerDuration < 2
		GetTableValue(temp0, object.redFlowerFrame, EHZSetup_redFlowerFrameTable)

		Copy16x16Tile(765, temp0)
		object.redFlowerFrame++

		GetTableValue(object.redFlowerDuration, object.redFlowerFrame, EHZSetup_redFlowerFrameTable)
		object.redFlowerFrame++

		object.redFlowerFrame &= 15
	else
		object.redFlowerDuration--
	end if

	if object.rectFlowerDuration < 2
		GetTableValue(temp0, object.rectFlowerFrame, EHZSetup_rectFlowerFrameTable)

		Copy16x16Tile(766, temp0)
		object.rectFlowerFrame++

		GetTableValue(object.rectFlowerDuration, object.rectFlowerFrame, EHZSetup_rectFlowerFrameTable)
		object.rectFlowerFrame++

		object.rectFlowerFrame &= 3
	else
		object.rectFlowerDuration--
	end if

	if object.pointyFlowerDuration < 2
		GetTableValue(temp0, object.pointyFlowerFrame, EHZSetup_pointyFlowerFrameTable)

		Copy16x16Tile(767, temp0)
		object.pointyFlowerFrame++

		GetTableValue(object.pointyFlowerDuration, object.pointyFlowerFrame, EHZSetup_pointyFlowerFrameTable)
		object.pointyFlowerFrame++

		object.pointyFlowerFrame &= 15
	else
		object.pointyFlowerDuration--
	end if

	if EHZSetup_hasAchievement == false
		if stage.debugMode == false
			if specialStage.emeralds >= 0x7F
				// Grant the "Early Bird Special" Achievement, if applicable
				
				if options.gameMode == MODE_NOSAVE
					EHZSetup_hasAchievement = true
					CallNativeFunction2(SetAchievement, ACHIEVEMENT_EARLYBIRDSPECIAL, 100)
				end if

				if options.gameMode == MODE_SAVEGAME
					arrayPos1 = options.saveSlot
					arrayPos1 <<= 3
					arrayPos1 += 4
					if saveRAM[arrayPos1] < 20 // Make sure our save file hasn't been completed yet, you have to play by the rules and do it on the first go!
						EHZSetup_hasAchievement = true
						CallNativeFunction2(SetAchievement, ACHIEVEMENT_EARLYBIRDSPECIAL, 100)
					end if
				end if
			end if
		end if
	end if
end event


event ObjectStartup
	if stage.activeList != BONUS_STAGE
		// Different music based on the current mode
		// To accommodate the different music, there are also separate speedup and slowdown functions for each track

		if options.vsMode == false
			SetMusicTrack("EmeraldHill.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_1P)
			SpeedUpMusic = EHZSetup_SpeedUpMusic1P
			SlowDownMusic = EHZSetup_SlowDownMusic1P
		else
			SetMusicTrack("EmeraldHill2.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_2P)
			SpeedUpMusic = EHZSetup_SpeedUpMusic2P
			SlowDownMusic = EHZSetup_SlowDownMusic2P
		end if
	else
		// In the Boss Attack version of the state, play the DEZ track instead
		SetMusicTrack("DeathEgg.ogg", TRACK_STAGE, true)
		
		// (Nothing for speed up or slow down here since a speed up version of DEZ's music doesn't exist, and it's not needed anyways)
	end if

#platform: USE_ORIGINS
	// In Mission Mode, disregard the previous code and always play EHZ 1P
	// (The Mission stages are all on the Bonus stage list, which triggers the DEZ music code)
	if game.playMode == BOOT_PLAYMODE_MISSION
		SetMusicTrack("EmeraldHill.ogg", TRACK_STAGE, MUSIC_LOOP_EHZ_1P)
		SpeedUpMusic = EHZSetup_SpeedUpMusic1P
		SlowDownMusic = EHZSetup_SlowDownMusic1P
	end if
#endplatform

	animalType1 = TypeName[Flicky]
	animalType2 = TypeName[Ricky]
	
	tileLayer[1].scrollPos = -0x80000

	arrayPos0 = 0
	while arrayPos0 < 576
		temp0 = arrayPos0
		temp0 &= 0x3F
		GetTableValue(stage.deformationData2[arrayPos0], temp0, EHZSetup_deformationTable)
		arrayPos0++
	loop

	object[SLOT_ZONESETUP].type = TypeName[EHZ Setup]
	object[SLOT_ZONESETUP].priority = PRIORITY_ACTIVE

	// Reset the boss flash colour
	SetPaletteEntry(0, 192, 0x000000)

	if options.attractMode == true
		switch stage.playerListPos
		case PLAYER_SONIC_ALONE
			Player_attractTable = EHZSetup_replay_attract_S
			Player_attractTableSize = 110
			Player_attractDuration = 1620
			break
			
		case PLAYER_TAILS_ALONE
			Player_attractTable = EHZSetup_replay_attract_T
			Player_attractTableSize = 318
			Player_attractDuration = 1800
			break
			
		case PLAYER_KNUX_ALONE
			Player_attractTable = EHZSetup_replay_attract_K
			Player_attractTableSize = 138
			Player_attractDuration = 1800
			break
			
		end switch
		
		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
