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

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

private alias object.value0 : object.distTimer // Movement distance, represented as a timer for how long the object should go for
private alias object.value1 : object.collisionOffset.y
private alias object.value2 : object.originPos.x
private alias object.value3 : object.originPos.y

private alias 0 : LIFT_WAITING
private alias 1 : LIFT_MOVING
private alias 2 : LIFT_FALLING
private alias 3 : LIFT_FALLEN

// Player Aliases
private alias object.xpos : player.xpos
private alias object.ypos : player.ypos


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

reserve function Lift_DebugDraw
reserve function Lift_DebugSpawn


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

private function Lift_DebugDraw
	DrawSpriteFX(0, FX_FLIP, object.xpos, object.ypos)
	DrawSpriteFX(2, FX_FLIP, object.xpos, object.ypos)
end function


private function Lift_DebugSpawn
	CreateTempObject(TypeName[Lift], 0, object.xpos, object.ypos)
	object[tempObjectPos].drawOrder = 5
	object[tempObjectPos].direction = object.direction
end function


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

event ObjectUpdate
	// Flag, for if this Lift should check for OOB after
	temp7 = false
	
	switch object.state
	case LIFT_WAITING
		foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
			BoxCollisionTest(C_PLATFORM, object.entityPos, -32, 41, 32, 57, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			if checkResult == true
				object.state = LIFT_MOVING
				object.priority = PRIORITY_ACTIVE
			end if
		next
		break

	case LIFT_MOVING
		foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
			BoxCollisionTest(C_PLATFORM, object.entityPos, -32, 41, 32, 57, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			if checkResult == true
				if object.direction == FLIP_X
					player[currentPlayer].xpos -= 0x20000
				else
					player[currentPlayer].xpos += 0x20000
				end if
				player[currentPlayer].ypos += 0x10000
			end if
		next

		if object.direction == FLIP_X
			object.xpos -= 0x20000
		else
			object.xpos += 0x20000
		end if

		object.ypos += 0x10000
		temp0 = oscillation
		temp0 &= 15
		if temp0 == 0
			PlaySfx(SfxName[Lift Tick], false)
		end if

		object.distTimer--
		if object.distTimer == 0
			object.collisionOffset.y = object.ypos
			object.priority = PRIORITY_ACTIVE
			object.state = LIFT_FALLING
		end if
		break

	case LIFT_FALLING
		// Backup the object's ypos, since it'll need to be changed soon
		temp0 = object.ypos

		// Setup object values for collision checks
		object.ypos = object.collisionOffset.y
		temp1 = object.collisionOffset.y
		temp1 &= 0xFFFF0000
		object.collisionOffset.y += object.yvel
		object.yvel += 0x3800
		temp2 = object.collisionOffset.y
		temp2 &= 0xFFFF0000
		temp2 -= temp1
		foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
			BoxCollisionTest(C_PLATFORM, object.entityPos, -32, 41, 32, 57, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			if checkResult == true
				player[currentPlayer].ypos += temp2
			end if
		next

		if object.outOfBounds == true
			object.state = LIFT_FALLEN
		else
			// Set this flag to exlcude this object from OOB checks
			temp7 = true
		end if

		// And now it's safe to restore the object's ypos
		object.ypos = temp0
		break

	case LIFT_FALLEN
		// Interesting note - in most cases whenever an object has an empty state, there's simply no case jump destination for it
		// In this case, however, it looks like something may have been here after all...
		break
		
	end switch

	if temp7 == false // Don't do this if the lift is still moving
		if object.outOfBounds == true
			temp0 = object.xpos
			temp1 = object.ypos
			object.xpos = object.originPos.x
			object.ypos = object.originPos.y
			if object.outOfBounds == true
				object.yvel = 0
				object.distTimer = object.propertyValue
				object.distTimer <<= 3
				object.priority = PRIORITY_BOUNDS
				object.state = LIFT_WAITING
			else
				object.xpos = temp0
				object.ypos = temp1
			end if
		end if
	end if
end event


event ObjectDraw
	switch object.state
	case LIFT_WAITING
	case LIFT_MOVING
		DrawSpriteFX(0, FX_FLIP, object.xpos, object.ypos)
		DrawSpriteFX(2, FX_FLIP, object.xpos, object.ypos)
		break

	case LIFT_FALLING
		DrawSpriteFX(0, FX_FLIP, object.xpos, object.ypos)
		DrawSpriteFX(1, FX_FLIP, object.xpos, object.ypos)
		DrawSpriteFX(3, FX_FLIP, object.xpos, object.collisionOffset.y)
		break

	case LIFT_FALLEN
		DrawSpriteFX(0, FX_FLIP, object.xpos, object.ypos)
		DrawSpriteFX(1, FX_FLIP, object.xpos, object.ypos)
		break
		
	end switch
end event


event ObjectStartup
	CheckCurrentStageFolder("Zone05")

	if checkResult == true
		LoadSpriteSheet("HTZ/Objects.gif")
		SpriteFrame(-28, -63, 56, 90, 102, 1)  // 0 - Holding vines frame
		SpriteFrame(-28, 27, 56, 13, 109, 198) // 1 - Loose Vines Frame
		SpriteFrame(-32, 27, 64, 21, 109, 212) // 2 - Platform frame, attached to vines
		SpriteFrame(-32, 27, 64, 21, 109, 234) // 3 - Loose Platform Frame
	else
		LoadSpriteSheet("MBZ/Objects.gif")
		SpriteFrame(-28, -63, 56, 90, 73, 848)
		SpriteFrame(-28, 27, 56, 13, 73, 939)
		SpriteFrame(-32, 27, 64, 21, 1, 953)
		SpriteFrame(-32, 27, 64, 21, 65, 953)
	end if

	foreach (TypeName[Lift], arrayPos0, ALL_ENTITIES)
		object[arrayPos0].originPos.x = object[arrayPos0].xpos
		object[arrayPos0].originPos.y = object[arrayPos0].ypos
		object[arrayPos0].drawOrder = 5
		object[arrayPos0].distTimer = object[arrayPos0].propertyValue
		object[arrayPos0].distTimer <<= 3
	next

	SetTableValue(TypeName[Lift], DebugMode_ObjCount, DebugMode_TypesTable)
	SetTableValue(Lift_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
	SetTableValue(Lift_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
	DebugMode_ObjCount++
end event


// ========================
// Editor Events
// ========================

event RSDKDraw
	DrawSpriteFX(0, FX_FLIP, object.xpos, object.ypos)
	DrawSpriteFX(1, FX_FLIP, object.xpos, object.ypos)

	if editor.showGizmos == true
		editor.drawingOverlay = true

		// Show a ghost of the lift's destination

		object.inkEffect = INK_BLEND

		temp0 = object.propertyValue
		temp0 <<= 3
		temp1 = object.xpos
		temp2 = object.ypos
		temp3 = 0x20000

		if object.direction == FLIP_X
			FlipSign(temp3)
		end if

		while temp0 > 0
			temp1 += temp3
			temp2 += 0x10000
			temp0--
		loop

		DrawSpriteFX(0, FX_INK, temp1, temp2)
		DrawSpriteFX(1, FX_INK, temp1, temp2)

		object.inkEffect = INK_NONE

		// Here -> dest
		DrawArrow(object.xpos, object.ypos, temp1, temp2, 0xFF, 0xFF, 0x00)
		
		editor.drawingOverlay = false
	end if
end event


event RSDKLoad
	CheckCurrentStageFolder("Zone05")
	if checkResult == true
		LoadSpriteSheet("HTZ/Objects.gif")
		SpriteFrame(-28, -63, 56, 90, 102, 1)  // Vines
		SpriteFrame(-32, 27, 64, 21, 109, 212) // Platform
	else
		LoadSpriteSheet("MBZ/Objects.gif")
		SpriteFrame(-28, -63, 56, 90, 73, 848) // Vines
		SpriteFrame(-32, 27, 64, 21, 1, 953)   // Platform
	end if

	SetVariableAlias(ALIAS_VAR_PROPVAL, "distance")
end event
