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

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

private alias object.value0  : object.oscillation
private alias object.value1  : object.drawIndex
private alias object.value2  : object.stoodPlayers
private alias object.value3  : object.gear1Offset.x
private alias object.value4  : object.gear2Offset.x
private alias object.value5  : object.gear3Offset.x
private alias object.value6  : object.gear4Offset.x
private alias object.value7  : object.gear5Offset.x
private alias object.value8  : object.gear6Offset.x
private alias object.value9  : object.gear7Offset.x
private alias object.value10 : object.gear8Offset.x

// Player Aliases
private alias object.xpos : player.xpos
private alias object.ypos : player.ypos
private alias object.gravity : player.gravity
private alias object.collisionLeft : player.collisionLeft
private alias object.collisionRight : player.collisionRight
private alias object.collisionBottom : player.collisionBottom

// Path ID Aliases
private alias 0 : PATH_A


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

reserve function LargeGear_DebugDraw
reserve function LargeGear_DebugSpawn


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

private table LargeGear_gearXTable[8]

private table LargeGear_gearYTable[8]


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

private function LargeGear_DebugDraw
	temp0 = 0
	temp1 = object.rotation

	object.rotation = 0
	while temp0 < 8
		DrawSpriteFX(0, FX_ROTATE, object.xpos, object.ypos)
		object.rotation += 0x40
		temp0++
	loop

	temp0 = 0
	while temp0 < 8
		DrawSpriteFX(2, FX_ROTATE, object.xpos, object.ypos)
		object.rotation += 0x40
		temp0++
	loop

	object.rotation = temp1

	Cos(temp0, 0)
	temp0 *= -28
	temp0 <<= 7
	temp0 += object.xpos

	Sin(temp1, 0)
	temp1 *= -28
	temp1 <<= 7
	temp1 += object.ypos

	DrawSpriteXY(1, temp0, temp1)
end function


private function LargeGear_DebugSpawn
	CreateTempObject(TypeName[Large Gear], object.direction, object.xpos, object.ypos)
	object[tempObjectPos].drawOrder = 2
end function


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

event ObjectUpdate
	object.rotation = oscillation
	object.rotation &= 0x3F

	object.oscillation = oscillation
	if object.propertyValue == 1
		FlipSign(object.rotation)
		object.rotation += 0x68
		object.rotation &= 0x3F
		FlipSign(object.oscillation)
		object.oscillation += 0x228
		object.oscillation &= 0x1FF
	end if

	temp0 = 0
	temp1 = object.oscillation

	while temp0 < 8
		Cos(temp2, temp1)
		temp2 *= -75
		temp2 >>= 9
		SetTableValue(temp2, temp0, LargeGear_gearXTable)

		Sin(temp2, temp1)
		temp2 *= -75
		temp2 >>= 9
		SetTableValue(temp2, temp0, LargeGear_gearYTable)

		temp0++
		temp1 += 0x40
	loop

	temp7 = 0
	foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
		GetBit(temp6, object.stoodPlayers, temp7)
		if temp6 == true
			player[currentPlayer].ypos += 0x40000
		end if

		SetBit(object.stoodPlayers, temp7, false)
		temp0 = 0
		temp5 = 9
		while temp0 < 8
			GetTableValue(temp1, temp0, LargeGear_gearXTable)
			GetTableValue(temp2, temp0, LargeGear_gearYTable)
			temp3 = temp1
			temp4 = temp2
			temp1 -= 10
			temp2 -= 10
			temp3 += 10
			temp4 += 10
			if temp6 == true
				BoxCollisionTest(C_PLATFORM, object.entityPos, temp1, temp2, temp3, temp4, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			else
				BoxCollisionTest(C_SOLID, object.entityPos, temp1, temp2, temp3, temp4, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			end if

			if checkResult == COL_TOP
				// Bug Details:
				// -> yeah uhhhh... that's not a proper gravity value...
				//    Because of this, the player might still be registered as in the air even when they're on the ground, and they'll look all weird 'n stuff
				// -> The intended value is GRAVITY_GROUND
				
				player[currentPlayer].gravity = object.entityPos
				
				SetBit(object.stoodPlayers, temp7, true)
				temp5 = temp0
			end if

			temp0++
		loop

		if temp5 < 8
			GetTableValue(temp0, temp5, LargeGear_gearXTable)
			switch temp5
			case 0
				temp0 -= object.gear1Offset.x
				break

			case 1
				temp0 -= object.gear2Offset.x
				break

			case 2
				temp0 -= object.gear3Offset.x
				break

			case 3
				temp0 -= object.gear4Offset.x
				break

			case 4
				temp0 -= object.gear5Offset.x
				break

			case 5
				temp0 -= object.gear6Offset.x
				break

			case 6
				temp0 -= object.gear7Offset.x
				break

			case 7
				temp0 -= object.gear8Offset.x
				break
				
			end switch

			temp0 <<= 16
			temp1 = temp0
			temp1 >>= 2
			temp0 += temp1
			player[currentPlayer].xpos += temp0
		else
			if temp6 == true
				player[currentPlayer].ypos -= 0x40000
			end if
		end if

		// We're gonna do some quick object slot shenanigans where we run code from slot[currentPlayer], since ObjectTileCollision doesn't have an entityPos input value and assumes the current entity

		// First, back up the slot that this Large Gear is running from
		arrayPos0 = stage.entityPos

		// Now, move focus to the player we're currently looking at
		stage.entityPos = currentPlayer

		// player.xpos is the position of, well, the player, and object[arrayPos0].xpos is the position of the Large Gear
		if player.xpos > object[arrayPos0].xpos
			ObjectTileCollision(CSIDE_RWALL, player.collisionLeft, 0, PATH_A)
		else
			ObjectTileCollision(CSIDE_LWALL, player.collisionRight, 0, PATH_A)
		end if

		ObjectTileCollision(CSIDE_FLOOR, 0, player.collisionBottom, PATH_A)

		// We're done with all the weird player stuff, now we can move focus back to the Large Gear's slot
		stage.entityPos = arrayPos0

		BoxCollisionTest(C_SOLID, object.entityPos, -64, -8, 64, 8, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)

		temp7++
	next

	GetTableValue(object.gear1Offset.x, 0, LargeGear_gearXTable)
	GetTableValue(object.gear2Offset.x, 1, LargeGear_gearXTable)
	GetTableValue(object.gear3Offset.x, 2, LargeGear_gearXTable)
	GetTableValue(object.gear4Offset.x, 3, LargeGear_gearXTable)
	GetTableValue(object.gear5Offset.x, 4, LargeGear_gearXTable)
	GetTableValue(object.gear6Offset.x, 5, LargeGear_gearXTable)
	GetTableValue(object.gear7Offset.x, 6, LargeGear_gearXTable)
	GetTableValue(object.gear8Offset.x, 7, LargeGear_gearXTable)
end event


event ObjectDraw
	if object.drawIndex == 0
		// Drawing on Draw Order 2

		temp0 = 0
		temp1 = object.rotation
		while temp0 < 8
			DrawSpriteFX(0, FX_ROTATE, object.xpos, object.ypos)
			object.rotation += 64
			temp0++
		loop
		object.rotation = temp1
		AddDrawListEntityRef(4, object.entityPos)
	else
		// Drawing on Draw Order 4

		temp0 = 0
		temp1 = object.rotation
		while temp0 < 8
			DrawSpriteFX(2, FX_ROTATE, object.xpos, object.ypos)
			object.rotation += 64
			temp0++
		loop
		object.rotation = temp1

		Cos(temp0, object.oscillation)
		temp0 *= -28
		temp0 <<= 7
		temp0 += object.xpos

		Sin(temp1, object.oscillation)
		temp1 *= -28
		temp1 <<= 7
		temp1 += object.ypos

		DrawSpriteXY(1, temp0, temp1)
	end if

	object.drawIndex ^= 1
end event


event ObjectStartup
	LoadSpriteSheet("MPZ/Objects.gif")
	SpriteFrame(-14, -88, 28, 32, 256, 1)
	SpriteFrame(-12, -12, 24, 24, 487, 157)
	SpriteFrame(-2, -14, 4, 4, 40, 34)

	foreach (TypeName[Large Gear], arrayPos0, ALL_ENTITIES)
		object[arrayPos0].drawOrder = 2
	next

	SetTableValue(TypeName[Large Gear], DebugMode_ObjCount, DebugMode_TypesTable)
	SetTableValue(LargeGear_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
	SetTableValue(LargeGear_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 // direction
			checkResult = object.propertyValue
			break
			
		end switch
	else
		switch editor.variableID
		case EDIT_VAR_PROPVAL // property value
			object.propertyValue = editor.variableValue
			break
			
		case 0 // direction
			object.propertyValue = editor.variableValue
			break
			
		end switch
	end if
end event


event RSDKDraw
	temp0 = 0
	temp1 = object.rotation

	object.rotation = 0
	while temp0 < 8
		DrawSpriteFX(0, FX_ROTATE, object.xpos, object.ypos)
		object.rotation += 0x40
		temp0++
	loop

	temp0 = 0
	while temp0 < 8
		DrawSpriteFX(2, FX_ROTATE, object.xpos, object.ypos)
		object.rotation += 0x40
		temp0++
	loop

	object.rotation = temp1

	Cos(temp0, 0)
	temp0 *= -28
	temp0 <<= 7
	temp0 += object.xpos

	Sin(temp1, 0)
	temp1 *= -28
	temp1 <<= 7
	temp1 += object.ypos

	DrawSpriteXY(1, temp0, temp1)
end event


event RSDKLoad
	LoadSpriteSheet("MPZ/Objects.gif")
	SpriteFrame(14, -60, 28, 32, 256, 67)
	SpriteFrame(-12, -12, 24, 24, 487, 157)
	SpriteFrame(-2, -14, 4, 4, 40, 34)

	AddEditorVariable("direction")
	SetActiveVariable("direction")
	AddEnumVariable("Clockwise", 0)
	AddEnumVariable("Anti-Clockwise", 1)
end event
