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

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

private alias object.value1  : object.activePlayers
private alias object.value2  : object.player1.angle
private alias object.value3  : object.player2.angle
private alias object.value4  : object.player3.angle
private alias object.value5  : object.player4.angle
private alias object.value6  : object.player1.direction
private alias object.value7  : object.player2.direction
private alias object.value8  : object.player3.direction
private alias object.value9  : object.player4.direction
private alias object.value10 : object.hitbox.left
private alias object.value11 : object.hitbox.right
private alias object.value12 : object.size

// Player Aliases
private alias object.state : player.state
private alias object.xpos : player.xpos
private alias object.ypos : player.ypos
private alias object.xvel : player.xvel
private alias object.yvel : player.yvel
private alias object.rotation : player.rotation
private alias object.angle : player.angle
private alias object.direction : player.direction
private alias object.gravity : player.gravity
private alias object.frame : player.frame
private alias object.prevAnimation : player.prevAnimation
private alias object.animationSpeed : player.animationSpeed
private alias object.animation : player.animation
private alias object.collisionTop : player.collisionTop
private alias object.collisionBottom : player.collisionBottom


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

private table Cylinder_playerFrameTable
	6, 5, 4, 3, 2, 1, 0, 11, 10, 9, 8, 7, 6
end table


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

event ObjectUpdate
	object.priority = PRIORITY_ACTIVE

	temp2 = 0
	foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
		GetBit(temp3, object.activePlayers, temp2)
		if temp3 == false
			BoxCollisionTest(C_TOUCH, object.entityPos, object.hitbox.left, 60, object.hitbox.right, 76, currentPlayer, C_BOX, 1, C_BOX, C_BOX)
			if player[currentPlayer].yvel < 0
				checkResult = false
			end if

			if checkResult == true
				SetBit(object.activePlayers, temp2, true)
				player[currentPlayer].yvel = 0

				// Very strange that it explicitly supports up to 4 players here, there's only 3 playable characters to begin with so not sure how that would've worked
				// It should be noted that if 4 players were loaded at once, there'd be no object slot clashes either (that would happen if 5 or more were loaded though)
				switch temp2
				case 0
					object.player1.angle = 0
					object.player1.direction = player[currentPlayer].direction
					break
					
				case 1
					object.player2.angle = 0
					object.player2.direction = player[currentPlayer].direction
					break
					
				case 2
					object.player3.angle = 0
					object.player3.direction = player[currentPlayer].direction
					break
					
				case 3
					object.player4.angle = 0
					object.player4.direction = player[currentPlayer].direction
					break
					
				end switch
			else
				temp0 = player[currentPlayer].collisionTop
				temp0 <<= 16
				temp0 += player[currentPlayer].ypos
				temp0 -= object.ypos
				if temp0 < -0x300000
					BoxCollisionTest(C_SOLID, object.entityPos, object.hitbox.left, -64, object.hitbox.right, -48, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
				else
					temp0 = player[currentPlayer].collisionBottom
					temp0 <<= 16
					temp0 += player[currentPlayer].ypos
					temp0 -= object.ypos
					if temp0 > 0x400000
						BoxCollisionTest(C_SOLID, object.entityPos, object.hitbox.left, 48, object.hitbox.right, 64, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
					end if
				end if
			end if
		else
			temp3 = 0
			temp0 = player[currentPlayer].xpos
			temp0 -= object.xpos
			Abs(temp0)

			CheckLower(player[currentPlayer].yvel, -0x40000)
			temp3 |= checkResult
			CheckGreater(temp0, object.size)
			temp3 |= checkResult
			if temp3 == true
				SetBit(object.activePlayers, temp2, false)
				if player[currentPlayer].gravity == 1
					if player[currentPlayer].yvel >= 0
						if player[currentPlayer].state != Player_State_Carried
							if player[currentPlayer].animation != ANI_SKIDDING
								if player[currentPlayer].xvel < 0
									player[currentPlayer].direction = FACING_LEFT
								end if

								player[currentPlayer].animation = ANI_TWIRL
								player[currentPlayer].angle = 0
								player[currentPlayer].rotation = 0
							end if
						end if
					end if
				end if

				switch temp2
				case 0
					temp6 = object.player1.angle
					break
					
				case 1
					temp6 = object.player2.angle
					break
					
				case 2
					temp6 = object.player3.angle
					break
					
				case 3
					temp6 = object.player4.angle
					break
					
				end switch

				temp6 += 0x20
				temp6 &= 0xFF
				if temp6 >= 64
					player[currentPlayer].yvel = 0
				else
					player[currentPlayer].yvel >>= 1
				end if
			else
				player[currentPlayer].yvel = 0
				temp0 >>= 16
				switch temp2
				case 0
					temp6 = object.player1.angle
					temp7 = object.player1.direction
					break
					
				case 1
					temp6 = object.player2.angle
					temp7 = object.player2.direction
					break
					
				case 2
					temp6 = object.player3.angle
					temp7 = object.player3.direction
					break
					
				case 3
					temp6 = object.player4.angle
					temp7 = object.player4.direction
					break
					
				end switch

				temp6 += 4
				temp6 &= 0xFF
				Cos256(player[currentPlayer].ypos, temp6)
				player[currentPlayer].ypos *= 42
				player[currentPlayer].ypos >>= 8
				player[currentPlayer].ypos -= player[currentPlayer].collisionBottom
				player[currentPlayer].ypos += 19
				player[currentPlayer].ypos <<= 16
				player[currentPlayer].ypos += object.ypos
				if player[currentPlayer].state == Player_State_Ground
					if player[currentPlayer].gravity == 1
						player[currentPlayer].prevAnimation 	= ANI_TWIRL
						player[currentPlayer].animation 		= ANI_TWIRL
						player[currentPlayer].animationSpeed 	= 0
						player[currentPlayer].direction 		= 0

						temp0 = temp6
						temp0 /= 21
						if player[currentPlayer].xvel != 0
							if player[currentPlayer].xvel > 0
								temp7 = FACING_RIGHT
							else
								temp7 = FACING_LEFT
							end if
						end if

						if temp7 == FACING_RIGHT
							player[currentPlayer].frame = temp0
							player[currentPlayer].rotation = 0x000
						else
							GetTableValue(player[currentPlayer].frame, temp0, Cylinder_playerFrameTable)
							player[currentPlayer].rotation = 0x100
						end if
					end if
				end if

				if player[currentPlayer].state == Player_State_Roll
					if player[currentPlayer].xvel != 0
						if player[currentPlayer].xvel > 0
							player[currentPlayer].direction = FACING_RIGHT
						else
							player[currentPlayer].direction = FACING_LEFT
						end if
					end if
				end if

				switch temp2
				case 0
					object.player1.angle 		= temp6
					object.player1.direction 	= temp7
					break
					
				case 1
					object.player2.angle 		= temp6
					object.player2.direction 	= temp7
					break
					
				case 2
					object.player3.angle 		= temp6
					object.player3.direction 	= temp7
					break
					
				case 3
					object.player4.angle 		= temp6
					object.player4.direction 	= temp7
					break
					
				end switch

				player[currentPlayer].gravity = GRAVITY_GROUND
			end if
		end if
		
		temp2++
	next

	if object.activePlayers != 0
		if object.propertyValue == 0
			if object.outOfBounds == true
				object.priority = PRIORITY_BOUNDS
			end if
		end if

		temp0 = false
		foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
			BoxCollisionTest(C_TOUCH, object.entityPos, object.hitbox.left, -64, object.hitbox.right, 64, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			temp0 |= checkResult
		next

		if temp0 == false
			object.activePlayers = 0
		end if
	end if
end event


event ObjectStartup
	foreach (TypeName[Cylinder], arrayPos0, ALL_ENTITIES)
		if object[arrayPos0].propertyValue == 0
			object[arrayPos0].hitbox.right 	= 192
			object[arrayPos0].priority 		= PRIORITY_BOUNDS
		else
			object[arrayPos0].hitbox.right 	= 384
			
			// The Cylinder is too large to run with traditional bounds, just make it always active
			object[arrayPos0].priority 		= PRIORITY_ACTIVE
		end if

		object[arrayPos0].size 			  = object[arrayPos0].hitbox.right
		object[arrayPos0].size 			<<= 16
		object[arrayPos0].hitbox.left 	  = object[arrayPos0].hitbox.right
		FlipSign(object[arrayPos0].hitbox.left)
	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 // 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)
	
	if editor.showGizmos == true
		editor.drawingOverlay = true
		
		// Draw the Cylinder's hitbox
		
		if object.propertyValue == 0
			temp0 = 192
		else
			temp0 = 384
		end if
		
		temp2 = temp0
		FlipSign(temp2)
		
		temp1 = 64; temp3 = 64;
		CallFunction(EditorHelpers_DrawHitbox)
		
		editor.drawingOverlay = false
	end if
end event


event RSDKLoad
	LoadSpriteSheet("Global/Display.gif")
	SpriteFrame(-8, -8, 16, 16, 168, 18) // "trigger" - #0
	
	AddEditorVariable("size")
	SetActiveVariable("size")
	AddEnumVariable("Small", 0)
	AddEnumVariable("Large", 1)
end event
