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

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

private alias object.value0  : object.contentsPos.y
private alias object.value1  : object.timer
private alias object.value3  : object.rewardPlayer
private alias object.value31 : object.altContents

// Monitor type aliases
private alias 0  : MONITOR_BLANK
private alias 1  : MONITOR_RINGS
private alias 2  : MONITOR_SHIELD_BLUE
private alias 3  : MONITOR_INVINCIBILITY
private alias 4  : MONITOR_SPEEDSHOES
private alias 5  : MONITOR_1UP_SONIC
private alias 6  : MONITOR_1UP_TAILS
private alias 7  : MONITOR_1UP_KNUX
private alias 8  : MONITOR_SUPER
private alias 9  : MONITOR_SHIELD_BUBBLE
private alias 10 : MONITOR_SHIELD_FIRE
private alias 11 : MONITOR_SHIELD_LIGHTNING
private alias 12 : MONITOR_EGGMAN
private alias 13 : MONITOR_TELEPORT
private alias 14 : MONITOR_RANDOM
private alias 15 : MONITOR_DEBUG_SHIELD
private alias 16 : MONITOR_COUNT

// Monitor states
private alias 0 : MONITOR_STATE_IDLE
private alias 1 : MONITOR_STATE_FALL

// Broken monitor states
private alias 0 : MONITOR_STATE_RISE

// Player Aliases
private alias object.state : player.state
private alias object.controlMode : player.controlMode
private alias object.propertyValue : player.character
private alias object.yvel : player.yvel
private alias object.gravity : player.gravity
private alias object.animation : player.animation
private alias object.value16 : player.isSidekick
private alias object.value17 : debugMode.currentSelection
private alias object.value25 : player.gravityStrength
private alias object.value40 : player.hitboxLeft
private alias object.value38 : player.hitboxTop
private alias object.value41 : player.hitboxRight
private alias object.value39 : player.hitboxBottom

// Game Modes
private alias 2 : MODE_TIMEATTACK

// Shield Types Aliases
private alias 0 : SHIELDTYPE_S2
private alias 1 : SHIELDTYPE_S3
private alias 2 : SHIELDTYPE_RAND_S2
private alias 3 : SHIELDTYPE_RAND_S3

// Path ID Aliases
private alias 0 : PATH_A


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

reserve function Monitor_DebugDraw
reserve function Monitor_DebugSpawn


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

private value Monitor_startDebugID = 0


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

// This variant uses S2 shields only
private table Monitor_randTypesTable_S2
	1  // MONITOR_RINGS
	2  // MONITOR_SHIELD_BLUE
	3  // MONITOR_INVINCIBILITY
	4  // MONITOR_SPEEDSHOES
	5  // MONITOR_1UP_SONIC
	6  // MONITOR_EGGMAN
	13 // MONITOR_TELEPORT
	1  // MONITOR_RINGS
	2  // MONITOR_SHIELD_BLUE
	1  // MONITOR_RINGS
end table

// This table uses S3 shields as well!
private table Monitor_randTypesTable_S3
	1  // MONITOR_RINGS
	2  // MONITOR_SHIELD_BLUE
	3  // MONITOR_INVINCIBILITY
	4  // MONITOR_SPEEDSHOES
	5  // MONITOR_1UP_SONIC
	9  // MONITOR_SHIELD_BUBBLE
	10 // MONITOR_SHIELD_FIRE
	11 // MONITOR_SHIELD_LIGHTNING
	6  // MONITOR_EGGMAN
	13 // MONITOR_TELEPORT
end table


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

private function Monitor_DebugDraw
	DrawSprite(0)
	
	temp0 = debugMode[0].currentSelection
	temp0 -= Monitor_startDebugID
	if temp0 == MONITOR_1UP_SONIC
		temp0 += stage.playerListPos
	else
		if temp0 > MONITOR_1UP_SONIC
			temp0 += 2
		end if
	end if

	temp0 += 2
	DrawSprite(temp0)
end function


private function Monitor_DebugSpawn
	temp0 = debugMode[0].currentSelection
	temp0 -= Monitor_startDebugID
	if temp0 == MONITOR_1UP_SONIC
		temp0 += stage.playerListPos
	else
		if temp0 > MONITOR_1UP_SONIC
			temp0 += 2
		end if
	end if

	CreateTempObject(TypeName[Monitor], temp0, object.xpos, object.ypos)
	object[tempObjectPos].frame = object[tempObjectPos].propertyValue
	object[tempObjectPos].frame += 2
end function


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

event ObjectUpdate
	if object.state == MONITOR_STATE_FALL
		object.yvel += 0x3800
		object.ypos += object.yvel
		if object.yvel >= 0
			ObjectTileCollision(CSIDE_FLOOR, 0, 16, PATH_A)
			if checkResult == true
				object.yvel = 0
				object.state = MONITOR_STATE_IDLE
			end if
		end if
	end if

	foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
		CheckGreater(player[currentPlayer].yvel, -1)
		temp0 = checkResult
		CheckEqual(player[currentPlayer].gravity, GRAVITY_GROUND)
		temp0 |= checkResult
		if temp0 == true
			CheckEqual(player[currentPlayer].animation, ANI_JUMPING)
			temp0 = checkResult
			CheckEqual(player[currentPlayer].animation, ANI_GLIDING)
			temp0 |= checkResult
			CheckEqual(player[currentPlayer].animation, ANI_GLIDING_STOP)
			temp0 |= checkResult
			if temp0 == true
				if player[currentPlayer].isSidekick == false
					BoxCollisionTest(C_TOUCH, object.entityPos, -16, -14, 16, 16, currentPlayer, player[currentPlayer].hitboxLeft, player[currentPlayer].hitboxTop, player[currentPlayer].hitboxRight, player[currentPlayer].hitboxBottom)
					if checkResult == true
						object.state = MONITOR_STATE_RISE
						CreateTempObject(TypeName[Smoke Puff], 0, object.xpos, object.ypos)
						object[tempObjectPos].drawOrder = 4
						player[currentPlayer].yvel += player[currentPlayer].gravityStrength
						player[currentPlayer].yvel += player[currentPlayer].gravityStrength
						FlipSign(player[currentPlayer].yvel)

						object.type = TypeName[Broken Monitor]
						object.rewardPlayer = currentPlayer
						if object.priority != PRIORITY_XBOUNDS_DESTROY
							object.priority = PRIORITY_ACTIVE
						end if

						object.alpha = 0xFF
						object.contentsPos.y = object.ypos
						object.timer = -0x30000
						if object.propertyValue == MONITOR_RANDOM
							vs.randomValue *= 1103515245
							vs.randomValue += 12345
							vs.randomValue &= 0x7FFFFFFF
							temp0 = vs.randomValue
							temp0 >>= 16
							temp0 %= 10

							if options.vsMode == true
								if player[currentPlayer].character == PLAYER_SONIC_ALONE // only let Sonic have access to the elemental shields, they're useless to all other chars anyways
									GetTableValue(object.propertyValue, temp0, Monitor_randTypesTable_S3)
								else
									GetTableValue(object.propertyValue, temp0, Monitor_randTypesTable_S2)
								end if

								if object.propertyValue == MONITOR_TELEPORT
									// If we have a Teleport monitor but either of the characters aren't ready to be teleported at the moment, then
									// just transform the monitor into a more generic reward instead
									
									if player[0].controlMode == CONTROLMODE_NONE
										object.propertyValue = MONITOR_SHIELD_BLUE
									end if

									if player[1].controlMode == CONTROLMODE_NONE
										object.propertyValue = MONITOR_SHIELD_BLUE
									end if

									if player[0].state == Player_State_Static
										object.propertyValue = MONITOR_RINGS
									end if

									if player[1].state == Player_State_Static
										object.propertyValue = MONITOR_RINGS
									end if
								end if
							else
								if options.shieldType == SHIELDTYPE_RAND_S3
									GetTableValue(object.propertyValue, temp0, Monitor_randTypesTable_S3)
								else
									GetTableValue(object.propertyValue, temp0, Monitor_randTypesTable_S2)
								end if

								if object.propertyValue == MONITOR_TELEPORT
									object.propertyValue = MONITOR_RINGS
								end if
							end if
						end if

						if options.vsMode == true
							if vs.playerID == 0
								if currentPlayer == 0
									vs.items1P++
								else
									vs.items2P++
								end if
							else
								if currentPlayer == 1
									vs.items1P++
								else
									vs.items2P++
								end if
							end if
						end if

						PlaySfx(SfxName[Destroy], false)
					end if
				else
					BoxCollisionTest(C_SOLID, object.entityPos, -15, -14, 15, 16, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
				end if
			else
				BoxCollisionTest(C_SOLID, object.entityPos, -15, -14, 15, 16, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			end if
		else
			BoxCollisionTest(C_SOLID, object.entityPos, -15, -16, 15, 16, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			if checkResult == COL_BOTTOM
				object.state = MONITOR_STATE_FALL
				object.yvel = -0x20000
				player[currentPlayer].yvel = 0x20000
			end if
		end if
	next
end event


event ObjectDraw
	DrawSprite(0)
	
	switch StageSetup_monitorOverlayFrame
	case 0
	case 1
		break

	case 6
	case 7
		DrawSprite(1)
		break

	case 12
	case 13
		DrawSprite(2)
		break

	default
		DrawSprite(object.frame)
		break

	end switch
end event


event ObjectStartup
	LoadSpriteSheet("Global/Items.gif")
	
	// 0 - Base monitor sprite
	SpriteFrame(-16, -16, 32, 32, 18, 1)
	
	// Icons
	SpriteFrame(-8, -9, 16, 14, 18, 51) // 1 - Static 1
	SpriteFrame(-8, -9, 16, 14, 35, 51) // 2 - Static 2
	SpriteFrame(-8, -9, 16, 14, 18, 66) // 3 - MONITOR_RINGS - Rings
	SpriteFrame(-8, -9, 16, 14, 35, 66) // 4 - MONITOR_RINGS - Blue Shield
	SpriteFrame(-8, -9, 16, 14, 18, 81) // 5 - MONITOR_INVINCIBILITY - Invincibility
	SpriteFrame(-8, -9, 16, 14, 35, 81) // 6 - MONITOR_SPEEDSHOES - Speed Shoes
#platform: USE_ORIGINS
	if game.coinMode == false
#endplatform
		SpriteFrame(-8, -9, 16, 14, 18, 96)  // 7 - MONITOR_1UP_SONIC - Sonic
		SpriteFrame(-8, -9, 16, 14, 35, 96)  // 8 - MONITOR_1UP_TAILS - Tails
		SpriteFrame(-8, -9, 16, 14, 18, 111) // 9 - MONITOR_1UP_KNUX  - Knuckles
#platform: USE_ORIGINS
	else
		SpriteFrame(-8, -9, 16, 14, 35, 186) // 7 - MONITOR_1UP_SONIC - Coin
		SpriteFrame(-8, -9, 16, 14, 35, 186) // 8 - MONITOR_1UP_TAILS - Coin (again)
		SpriteFrame(-8, -9, 16, 14, 35, 186) // 9 - MONITOR_1UP_KNUX  - Coin (woah)
	end if
#endplatform
	SpriteFrame(-8, -9, 16, 14, 35, 111) // 10 - MONITOR_SUPER - Super
	SpriteFrame(-8, -9, 16, 14, 18, 141) // 11 - MONITOR_SHIELD_BUBBLE - Bubble
	SpriteFrame(-8, -9, 16, 14, 35, 126) // 12 - MONITOR_SHIELD_FIRE - Flame
	SpriteFrame(-8, -9, 16, 14, 18, 126) // 13 - MONITOR_SHIELD_LIGHTNING - Lightning
	SpriteFrame(-8, -9, 16, 14, 35, 141) // 14 - MONITOR_EGGMAN - Eggman
	SpriteFrame(-8, -9, 16, 14, 18, 156) // 15 - MONITOR_TELEPORT - Teleport
	SpriteFrame(-8, -9, 16, 14, 35, 156) // 16 - MONITOR_RANDOM - Random
	SpriteFrame(-8, -9, 16, 14, 18, 171) // 17 - MONITOR_DEBUG_SHIELD - Debug Shields
	SpriteFrame(-8, -9, 16, 14, 35, 171) // 18 - Debug Emeralds
	
	// (The Mania monitor introduced in Origins is unused btw)
	
	Monitor_startDebugID = DebugMode_ObjCount
	Monitor_startDebugID--
	temp0 = MONITOR_BLANK
	while temp0 < MONITOR_COUNT
		temp2 = true
		if temp0 >= MONITOR_1UP_SONIC
			if temp0 <= MONITOR_1UP_KNUX
				temp1 = temp0
				temp1 -= MONITOR_1UP_SONIC
				if stage.playerListPos != temp1
					temp2 = false
				end if
			end if
		end if

		if temp2 == true
			SetTableValue(TypeName[Monitor], DebugMode_ObjCount, DebugMode_TypesTable)
			SetTableValue(Monitor_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
			SetTableValue(Monitor_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
			DebugMode_ObjCount++
		end if
		temp0++
	loop
	
	foreach (TypeName[Monitor], arrayPos0, ALL_ENTITIES)
		object[arrayPos0].altContents = object[arrayPos0].propertyValue
		object[arrayPos0].altContents >>= 4
		object[arrayPos0].propertyValue &= 15
	next

	// Turn all 1UP monitors into the icons of the appropriate character
	if stage.playerListPos == PLAYER_TAILS_ALONE
		foreach (TypeName[Monitor], arrayPos0, ALL_ENTITIES)
			if object[arrayPos0].propertyValue == MONITOR_1UP_SONIC
				object[arrayPos0].propertyValue = MONITOR_1UP_TAILS
			end if
		next
	end if
	
	if stage.playerListPos == PLAYER_KNUX_ALONE
		foreach (TypeName[Monitor], arrayPos0, ALL_ENTITIES)
			if object[arrayPos0].propertyValue == MONITOR_1UP_SONIC
				object[arrayPos0].propertyValue = MONITOR_1UP_KNUX
			end if
		next
	end if
	
	// Only 1 life in Time Attack, remove all 1UP monitors
	if options.gameMode == MODE_TIMEATTACK
		foreach (TypeName[Monitor], arrayPos0, ALL_ENTITIES)
			if object[arrayPos0].propertyValue == MONITOR_1UP_SONIC
				object[arrayPos0].type = TypeName[Blank Object]
			end if
		next
	end if
	
	if options.vsMode == true
		// Set up the monitors for VS mode
		switch vs.itemMode
		default
		case 0
			break
			
		case 1
			foreach (TypeName[Monitor], arrayPos0, ALL_ENTITIES)
				object[arrayPos0].propertyValue = MONITOR_RANDOM
			next
			break
			
		case 2
			foreach (TypeName[Monitor], arrayPos0, ALL_ENTITIES)
				object[arrayPos0].propertyValue = MONITOR_TELEPORT
			next
			break
			
		end switch
	else
		// Set up the shield monitors
		if options.shieldType > SHIELDTYPE_S3
			foreach (TypeName[Monitor], arrayPos0, ALL_ENTITIES)
				object[arrayPos0].propertyValue = MONITOR_RANDOM
			next
		else
			if options.shieldType == SHIELDTYPE_S2
				foreach (TypeName[Monitor], arrayPos0, ALL_ENTITIES)
					if object[arrayPos0].propertyValue >= MONITOR_SHIELD_BUBBLE
						if object[arrayPos0].propertyValue <= MONITOR_SHIELD_LIGHTNING
							if object[arrayPos0].altContents == MONITOR_BLANK
								object[arrayPos0].type = TypeName[Blank Object]
							else
								object[arrayPos0].propertyValue = object[arrayPos0].altContents
							end if
						end if
					end if
				next
			end if
		end if
	end if

	foreach (TypeName[Monitor], arrayPos0, ALL_ENTITIES)
		object[arrayPos0].frame = object[arrayPos0].propertyValue
		object[arrayPos0].frame += 2
	next
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 // contents
			checkResult = object.propertyValue
			checkResult &= 0xF
			break
			
		case 1 // altContents
			checkResult = object.propertyValue
			checkResult >>= 4
			checkResult &= 0xF
			break
			
		end switch
	else
		switch editor.variableID
		case EDIT_VAR_PROPVAL // property value
			object.propertyValue = editor.variableValue
			break
			
		case 0 // contents
			temp0 = editor.variableValue
			temp0 &= 0xF
			object.propertyValue &= 0xF0
			object.propertyValue |= temp0
			break
			
		case 1 // altContents
			temp0 = editor.variableValue
			temp0 &= 0xF
			temp0 <<= 4
			object.propertyValue &= 0xF
			object.propertyValue |= temp0
			break
			
		end switch
	end if
end event


event RSDKDraw
	object.frame = object.propertyValue
	object.frame &= 0xF

	DrawSprite(0)
	DrawSprite(object.frame)
end event


event RSDKLoad
	LoadSpriteSheet("Global/Items.gif")
	SpriteFrame(-16, -16, 32, 32, 18, 1)
	SpriteFrame(-8, -9, 16, 14, 18, 66)
	SpriteFrame(-8, -9, 16, 14, 35, 66)
	SpriteFrame(-8, -9, 16, 14, 18, 81)
	SpriteFrame(-8, -9, 16, 14, 35, 81)
	SpriteFrame(-8, -9, 16, 14, 18, 96)
	SpriteFrame(-8, -9, 16, 14, 35, 96)
	SpriteFrame(-8, -9, 16, 14, 18, 111)
	SpriteFrame(-8, -9, 16, 14, 35, 111)
	SpriteFrame(-8, -9, 16, 14, 18, 141)
	SpriteFrame(-8, -9, 16, 14, 35, 126)
	SpriteFrame(-8, -9, 16, 14, 18, 126)
	SpriteFrame(-8, -9, 16, 14, 35, 141)
	SpriteFrame(-8, -9, 16, 14, 18, 156)
	SpriteFrame(-8, -9, 16, 14, 35, 156)
	SpriteFrame(-8, -9, 16, 14, 18, 171)
	SpriteFrame(-8, -9, 16, 14, 35, 171)

	AddEditorVariable("contents")
	SetActiveVariable("contents")
	AddEnumVariable("None", 0)
	AddEnumVariable("10 Rings", 1)
	AddEnumVariable("Blue Shield", 2)
	AddEnumVariable("Invincibility", 3)
	AddEnumVariable("Speed Shoes", 4)
	AddEnumVariable("1UP (Sonic)", 5)
	AddEnumVariable("1UP (Tails)", 6)
	AddEnumVariable("1UP (Knux)", 7)
	AddEnumVariable("Super", 8)
	AddEnumVariable("Bubble Shield", 9)
	AddEnumVariable("Fire Shield", 10)
	AddEnumVariable("Lightning Shield", 11)
	AddEnumVariable("Eggman", 12)
	AddEnumVariable("Teleport", 13)
	AddEnumVariable("Random", 14)
	AddEnumVariable("Shields Toggle", 15)

	AddEditorVariable("altContents")
	SetActiveVariable("altContents")
	AddEnumVariable("None", 0)
	AddEnumVariable("10 Rings", 1)
	AddEnumVariable("Blue Shield", 2)
	AddEnumVariable("Invincibility", 3)
	AddEnumVariable("Speed Shoes", 4)
	AddEnumVariable("1UP (Sonic)", 5)
	AddEnumVariable("1UP (Tails)", 6)
	AddEnumVariable("1UP (Knux)", 7)
	AddEnumVariable("Super", 8)
	AddEnumVariable("Bubble Shield", 9)
	AddEnumVariable("Fire Shield", 10)
	AddEnumVariable("Lightning Shield", 11)
	AddEnumVariable("Eggman", 12)
	AddEnumVariable("Teleport", 13)
	AddEnumVariable("Random", 14)
	AddEnumVariable("Shields Toggle", 15)
end event
