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

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

private alias object.value0 : object.timer
private alias object.value1 : object.crusherType
private alias object.value2 : object.useButton
private alias object.value3 : object.startPos.y
private alias object.value4 : object.endPos.y
private alias object.value5 : object.collisionOffset.y
private alias object.value6 : object.currentPos.y
private alias object.value7 : object.dontPlaySfx

private alias 0 : CHAINCRUSHER_DROPPING
private alias 1 : CHAINCRUSHER_DROPPED
private alias 2 : CHAINCRUSHER_RISING
private alias 3 : CHAINCRUSHER_RISEN
private alias 4 : CHAINCRUSHER_DROPWHENACTIVE

private alias 0 : CHAINCRUSHER_TYPE_LARGE
private alias 1 : CHAINCRUSHER_TYPE_MED
private alias 2 : CHAINCRUSHER_TYPE_SMALL
private alias 3 : CHAINCRUSHER_TYPE_SMALL_ACTIVE

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

// Debug Mode Aliases
private alias object.value17 : debugMode.currentSelection

// PushButton aliases
private alias object.propertyValue : pushButton.stood


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

reserve function ChainedCrusher_DebugDraw
reserve function ChainedCrusher_DebugSpawn
reserve function ChainedCrusher_CheckOnScreen


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

private value ChainedCrusher_startDebugID = 0


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

private function ChainedCrusher_DebugDraw
	temp7 = debugMode[0].currentSelection
	temp7 -= ChainedCrusher_startDebugID
	temp6 = temp7
	temp6 /= 7
	temp7 %= 7
	temp5 = object.ypos
	switch temp7
	case 0
		temp5 += 0x700000
		break
		
	case 1
		temp5 += 0xA00000
		break
		
	case 2
		temp5 += 0x500000
		break
		
	case 3
		temp5 += 0x780000
		break
		
	case 4
		temp5 += 0x380000
		break
		
	case 5
		temp5 += 0x580000
		break
		
	case 6
		temp5 += 0xB80000
		break
	end switch

	temp0 = temp5
	temp0 -= object.ypos
	temp0 >>= 16
	temp0 += 4
	temp1 = 257
	temp1 -= temp0
	temp2 = temp0
	temp2 += 18
	FlipSign(temp2)
	EditFrame(5, -4, temp2, 8, temp0, 308, temp1)
	DrawSpriteXY(5, object.xpos, temp5)
	DrawSpriteXY(0, object.xpos, object.ypos)
	switch temp6
	case 0
		DrawSpriteXY(1, object.xpos, temp5)
		DrawSpriteXY(4, object.xpos, temp5)
		break
			
	case 1
		DrawSpriteXY(2, object.xpos, temp5)
		DrawSpriteXY(4, object.xpos, temp5)
		break
			
	case 2
	case 3
		DrawSpriteXY(3, object.xpos, temp5)
		break
	end switch
end function


private function ChainedCrusher_DebugSpawn
	temp7 = debugMode[0].currentSelection
	temp7 -= ChainedCrusher_startDebugID

	temp6 = temp7
	temp6 /= 7
	temp7 %= 7
	CreateTempObject(TypeName[Chained Crusher], 0, object.xpos, object.ypos)
	object[tempObjectPos].useButton = false
	object[tempObjectPos].crusherType = temp6
	if object[tempObjectPos].crusherType == CHAINCRUSHER_TYPE_SMALL
		object[tempObjectPos].state = CHAINCRUSHER_DROPWHENACTIVE
	end if

	object[tempObjectPos].startPos.y = object.ypos
	object[tempObjectPos].endPos.y = object[tempObjectPos].startPos.y
	switch temp7
	case 0
		object[tempObjectPos].endPos.y += 0x700000
		break

	case 1
		object[tempObjectPos].endPos.y += 0xA00000
		break

	case 2
		object[tempObjectPos].endPos.y += 0x500000
		break

	case 3
		object[tempObjectPos].endPos.y += 0x780000
		break

	case 4
		object[tempObjectPos].endPos.y += 0x380000
		break

	case 5
		object[tempObjectPos].endPos.y += 0x580000
		break

	case 6
		object[tempObjectPos].endPos.y += 0xB80000
		break
		
	end switch
end function


private function ChainedCrusher_CheckOnScreen
	checkResult = false
	temp0 = object.xpos
	temp0 >>= 16
	temp0 -= camera[0].xpos
	Abs(temp0)
	switch object.crusherType
	case CHAINCRUSHER_TYPE_LARGE
		temp0 -= 64
		break
			
	case CHAINCRUSHER_TYPE_MED
		temp0 -= 56
		break
			
	case CHAINCRUSHER_TYPE_SMALL
		temp0 -= 0
		break
			
	case CHAINCRUSHER_TYPE_SMALL_ACTIVE
		temp0 -= 24
		break
	end switch

	if temp0 <= screen.xcenter
		temp1 = object.endPos.y
		temp1 -= object.startPos.y
		temp1 >>= 16
		temp1 += 8
		temp1 >>= 1
		temp0 = object.startPos.y
		temp0 += object.endPos.y
		temp0 >>= 17
		temp0 -= 12
		temp0 -= camera[0].ypos
		Abs(temp0)
		temp0 -= temp1
		temp0 -= 40
		if temp0 <= screen.ycenter
			checkResult = true
		end if
	end if
end function


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

event ObjectUpdate
	object.priority = PRIORITY_ACTIVE
	if object.useButton == true
		if pushButton[+1].stood == false
			object.dontPlaySfx = false
			object.yvel += 0x7000
			object.ypos += object.yvel
			if object.ypos >= object.endPos.y
				if object.yvel > 0x7000
					CallFunction(ChainedCrusher_CheckOnScreen)
					if checkResult == true
						PlaySfx(SfxName[Crusher], false)
					end if
				end if
				object.ypos = object.endPos.y
				object.yvel = 0
			end if
		else
			object.yvel = -0x8000
			object.ypos += object.yvel
			if object.ypos <= object.startPos.y
				object.ypos = object.startPos.y
				object.yvel = 0
			else
				if object.dontPlaySfx == false
					temp0 = oscillation
					temp0 &= 15
					if temp0 == 0
						CallFunction(ChainedCrusher_CheckOnScreen)
						if checkResult == true
							PlaySfx(SfxName[Chain Pull], false)
						end if
					end if
				end if
			end if
		end if
	else
		switch object.state
		case CHAINCRUSHER_DROPPING
			object.dontPlaySfx = false
			object.yvel += 0x7000
			object.ypos += object.yvel
			if object.ypos >= object.endPos.y
				if object.yvel > 0x7000
					CallFunction(ChainedCrusher_CheckOnScreen)
					if checkResult == true
						PlaySfx(SfxName[Crusher], false)
					end if
				end if
				object.ypos = object.endPos.y
				object.yvel = 0
				object.state++
			end if
			break

		case CHAINCRUSHER_DROPPED
			object.timer++
			if object.timer == 60
				object.timer = 0
				object.yvel = -0x8000
				object.state++
			end if
			break
			
		case CHAINCRUSHER_RISING
			object.ypos += object.yvel
			if object.ypos <= object.startPos.y
				object.ypos = object.startPos.y
				object.yvel = 0
				object.state++
			else
				if object.dontPlaySfx == false
					temp0 = oscillation
					temp0 &= 15
					if temp0 == 0
						CallFunction(ChainedCrusher_CheckOnScreen)
						if checkResult == true
							PlaySfx(SfxName[Chain Pull], false)
						end if
					end if
				end if
			end if
			break

		case CHAINCRUSHER_RISEN
			object.timer++
			if object.timer == 4
				object.timer = 0
				object.state = CHAINCRUSHER_DROPPING
			end if
			break
			
		case CHAINCRUSHER_DROPWHENACTIVE
			CallFunction(ChainedCrusher_CheckOnScreen)
			if checkResult == true
				object.state = CHAINCRUSHER_DROPPING
				object.crusherType++
			end if
			break	
		end switch
	end if

	object.collisionOffset.y = object.ypos
	object.collisionOffset.y &= 0xFFFF0000
	object.collisionOffset.y -= object.currentPos.y

	temp0 = object.ypos
	object.ypos = object.currentPos.y
	foreach (GROUP_PLAYERS, currentPlayer, ACTIVE_ENTITIES)
		switch object.crusherType
		case CHAINCRUSHER_TYPE_LARGE
			BoxCollisionTest(C_SOLID, object.entityPos, -56, -12, 56, 10, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			switch checkResult
			case COL_NONE
				BoxCollisionTest(C_TOUCH, object.entityPos, -48, 12, 48, 36, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
				if checkResult == true
					CallFunction(Player_Hit)
				end if
				break

			case COL_TOP
				player[currentPlayer].ypos += object.collisionOffset.y
				break

			case COL_BOTTOM
				if player[currentPlayer].gravity == GRAVITY_GROUND
					if object.collisionOffset.y >= 0
						CallFunction(Player_Kill)
					end if
				end if
				break
			end switch
			break

		case CHAINCRUSHER_TYPE_MED
			BoxCollisionTest(C_SOLID, object.entityPos, -48, -12, 48, 10, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			switch checkResult
			case COL_NONE
				BoxCollisionTest(C_TOUCH, object.entityPos, -47, 12, 47, 36, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
				if checkResult == true
					CallFunction(Player_Hit)
				end if
				break

			case COL_TOP
				player[currentPlayer].ypos += object.collisionOffset.y
				break

			case COL_BOTTOM
				if player[currentPlayer].gravity == GRAVITY_GROUND
					if object.collisionOffset.y >= 0
						CallFunction(Player_Kill)
					end if
				end if
				break
			end switch
			break

		case CHAINCRUSHER_TYPE_SMALL_ACTIVE
			BoxCollisionTest(C_SOLID, object.entityPos, -16, -12, 16, 12, currentPlayer, C_BOX, C_BOX, C_BOX, C_BOX)
			switch checkResult
			case COL_TOP
				player[currentPlayer].ypos += object.collisionOffset.y
				break

			case COL_BOTTOM
				if player[currentPlayer].gravity == GRAVITY_GROUND
					if object.collisionOffset.y >= 0
						CallFunction(Player_Kill)
					end if
				end if
				break
			end switch
			break
		end switch
	next

	object.ypos = temp0
	object.currentPos.y = object.ypos
	object.currentPos.y &= 0xFFFF0000

	temp0 = object.xpos
	temp0 >>= 16
	temp0 -= camera[0].xpos
	Abs(temp0)
	temp0 -= 128
	if temp0 > screen.xcenter
		if object.useButton == true
			object.ypos = object.endPos.y
		else
			object.ypos = object.startPos.y
		end if
		object.timer = 0

		if object.crusherType >= CHAINCRUSHER_TYPE_SMALL
			object.state = CHAINCRUSHER_DROPWHENACTIVE
			object.crusherType = CHAINCRUSHER_TYPE_SMALL
		else
			object.state = CHAINCRUSHER_DROPPING
		end if
		object.priority = PRIORITY_BOUNDS
	end if
end event


event ObjectDraw
	temp0 = object.ypos
	temp0 -= object.startPos.y
	temp0 >>= 16
	temp0 += 4
	temp1 = 257
	temp1 -= temp0
	temp2 = temp0
	temp2 += 18
	FlipSign(temp2)
	EditFrame(5, -4, temp2, 8, temp0, 308, temp1)
	DrawSpriteXY(5, object.xpos, object.currentPos.y)
	DrawSpriteXY(0, object.xpos, object.startPos.y)
	switch object.crusherType
	case CHAINCRUSHER_TYPE_LARGE
		DrawSpriteXY(1, object.xpos, object.currentPos.y)
		DrawSpriteXY(4, object.xpos, object.currentPos.y)
		break

	case CHAINCRUSHER_TYPE_MED
		DrawSpriteXY(2, object.xpos, object.currentPos.y)
		DrawSpriteXY(4, object.xpos, object.currentPos.y)
		break

	case CHAINCRUSHER_TYPE_SMALL
	case CHAINCRUSHER_TYPE_SMALL_ACTIVE
		DrawSpriteXY(3, object.xpos, object.currentPos.y)
		break
	end switch
end event


event ObjectStartup
	LoadSpriteSheet("MZ/Objects.gif")
	SpriteFrame(-16, -52, 32, 32, 256, 76)
	SpriteFrame(-56, -20, 112, 32, 143, 180)
	SpriteFrame(-48, -20, 96, 32, 159, 147)
	SpriteFrame(-16, -20, 32, 32, 256, 109)
	SpriteFrame(-44, 12, 87, 32, 199, 256)
	SpriteFrame(-4, -206, 8, 188, 308, 69)

	foreach (TypeName[Chained Crusher], arrayPos0, ALL_ENTITIES)
		object[arrayPos0].useButton = object[arrayPos0].propertyValue
		object[arrayPos0].useButton >>= 7

		object[arrayPos0].crusherType = object[arrayPos0].propertyValue
		object[arrayPos0].crusherType &= 0x7F
		object[arrayPos0].crusherType >>= 4
		object[arrayPos0].crusherType %= 3

		if object[arrayPos0].crusherType == CHAINCRUSHER_TYPE_SMALL
			object[arrayPos0].state = CHAINCRUSHER_DROPWHENACTIVE
		end if

		temp0 = object[arrayPos0].propertyValue
		temp0 &= 7
		if temp0 > 6
			temp0 = 0
		end if

		object[arrayPos0].startPos.y = object[arrayPos0].ypos
		object[arrayPos0].endPos.y = object[arrayPos0].startPos.y
		switch temp0
		case 0
			object[arrayPos0].endPos.y += 0x700000
			break

		case 1
			object[arrayPos0].endPos.y += 0xA00000
			break

		case 2
			object[arrayPos0].endPos.y += 0x500000
			break

		case 3
			object[arrayPos0].endPos.y += 0x780000
			break

		case 4
			object[arrayPos0].endPos.y += 0x380000
			break

		case 5
			object[arrayPos0].endPos.y += 0x580000
			break

		case 6
			object[arrayPos0].endPos.y += 0xB80000
			break
		end switch

		if object[arrayPos0].useButton == true
			object[arrayPos0].ypos = object[arrayPos0].endPos.y
		end if
	next

	temp0 = 0
	ChainedCrusher_startDebugID = DebugMode_ObjCount
	while temp0 < 21
		SetTableValue(TypeName[Chained Crusher], DebugMode_ObjCount, DebugMode_TypesTable)
		SetTableValue(ChainedCrusher_DebugDraw, DebugMode_ObjCount, DebugMode_DrawTable)
		SetTableValue(ChainedCrusher_DebugSpawn, DebugMode_ObjCount, DebugMode_SpawnTable)
		DebugMode_ObjCount++
		temp0++
	loop
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 // useButton
			checkResult = object.propertyValue
			checkResult >>= 7
			checkResult &= 1
			break
			
		case 1 // type
			checkResult = object.propertyValue
			checkResult &= 127
			checkResult >>= 4
			checkResult %= 3
			break
			
		case 2 // length
			checkResult = object.propertyValue
			checkResult &= 7
			if checkResult > 6
				checkResult = 0
			end if
			break
			
		end switch
	else
		switch editor.variableID
		case EDIT_VAR_PROPVAL // property value
			object.propertyValue = editor.variableValue
			break
			
		case 0 // useButton
			CheckNotEqual(editor.variableValue, false)
			SetBit(object.propertyValue, 7, checkResult)
			break
			
		case 1 // type
			temp1 = 0x70
			Not(temp1)
			object.propertyValue &= temp1

			editor.variableValue &= 3
			editor.variableValue <<= 4
			object.propertyValue |= editor.variableValue
			break
			
		case 2 // length
			temp1 = 7
			Not(temp1)
			object.propertyValue &= temp1

			temp0 = editor.variableValue
			temp0 &= 7
			object.propertyValue |= temp0
			break
			
		end switch
	end if
end event


event RSDKDraw
	temp7 = object.ypos
	// Get Values		
	object.useButton = object.propertyValue
	object.useButton >>= 7
	object.crusherType = object.propertyValue
	object.crusherType &= 127
	object.crusherType >>= 4
	object.crusherType %= 3

	temp0 = object.propertyValue
	temp0 &= 7
	if temp0 > 6
		temp0 = 0
	end if

	object.startPos.y = object.ypos
	object.endPos.y = object.startPos.y
	switch temp0
	case 0
		object.endPos.y += 0x700000
		break

	case 1
		object.endPos.y += 0xA00000
		break

	case 2
		object.endPos.y += 0x500000
		break

	case 3
		object.endPos.y += 0x780000
		break

	case 4
		object.endPos.y += 0x380000
		break

	case 5
		object.endPos.y += 0x580000
		break

	case 6
		object.endPos.y += 0xB80000
		break
		
	end switch

	object.ypos = object.startPos.y
	if object.useButton == true
		object.ypos = object.endPos.y
	end if
	object.inkEffect = INK_BLEND

	// Drawww (Actual)
	object.currentPos.y = object.ypos
	object.currentPos.y &= 0xFFFF0000
	temp0 = object.ypos
	temp0 -= object.startPos.y
	temp0 >>= 16
	temp0 += 4
	temp1 = 257
	temp1 -= temp0
	temp2 = temp0
	temp2 += 18
	FlipSign(temp2)
	EditFrame(5, -4, temp2, 8, temp0, 308, temp1)
	DrawSpriteXY(5, object.xpos, object.currentPos.y)
	DrawSpriteXY(0, object.xpos, object.startPos.y)
	switch object.crusherType
	case CHAINCRUSHER_TYPE_LARGE
		DrawSpriteXY(1, object.xpos, object.currentPos.y)
		DrawSpriteXY(4, object.xpos, object.currentPos.y)
		break

	case CHAINCRUSHER_TYPE_MED
		DrawSpriteXY(2, object.xpos, object.currentPos.y)
		DrawSpriteXY(4, object.xpos, object.currentPos.y)
		break

	case CHAINCRUSHER_TYPE_SMALL
		DrawSpriteXY(3, object.xpos, object.currentPos.y)
		break
		
	end switch

	// Drawww (Preview)
	object.ypos = object.endPos.y
	if object.useButton == true
		object.ypos = object.startPos.y
	end if
	object.currentPos.y = object.ypos
	object.currentPos.y &= 0xFFFF0000
	temp0 = object.ypos
	temp0 -= object.startPos.y
	temp0 >>= 16
	temp0 += 4
	temp1 = 257
	temp1 -= temp0
	temp2 = temp0
	temp2 += 18
	FlipSign(temp2)
	EditFrame(5, -4, temp2, 8, temp0, 308, temp1)
	DrawSpriteFX(5, FX_INK, object.xpos, object.currentPos.y)
	DrawSpriteFX(0, FX_INK, object.xpos, object.startPos.y)
	switch object.crusherType
	case CHAINCRUSHER_TYPE_LARGE
		DrawSpriteFX(1, FX_INK, object.xpos, object.currentPos.y)
		DrawSpriteFX(4, FX_INK, object.xpos, object.currentPos.y)
		break

	case CHAINCRUSHER_TYPE_MED
		DrawSpriteFX(2, FX_INK, object.xpos, object.currentPos.y)
		DrawSpriteFX(4, FX_INK, object.xpos, object.currentPos.y)
		break

	case CHAINCRUSHER_TYPE_SMALL
		DrawSpriteFX(3, FX_INK, object.xpos, object.currentPos.y)
		break
		
	end switch

	object.ypos = temp7
end event


event RSDKLoad
	LoadSpriteSheet("MZ/Objects.gif")
	SpriteFrame(-16, -52, 32, 32, 256, 76)
	SpriteFrame(-56, -20, 112, 32, 143, 180)
	SpriteFrame(-48, -20, 96, 32, 159, 147)
	SpriteFrame(-16, -20, 32, 32, 256, 109)
	SpriteFrame(-44, 12, 87, 32, 199, 256)
	SpriteFrame(-4, -206, 8, 188, 308, 69)

	AddEditorVariable("useButton")
	SetActiveVariable("useButton")
	AddEnumVariable("false", false)
	AddEnumVariable("true", true)

	AddEditorVariable("type")
	SetActiveVariable("type")
	AddEnumVariable("Large", CHAINCRUSHER_TYPE_LARGE)
	AddEnumVariable("Medium", CHAINCRUSHER_TYPE_MED)
	AddEnumVariable("Small (Drop On Interval)", CHAINCRUSHER_TYPE_SMALL)
	AddEnumVariable("Small (Wait For Visible)", CHAINCRUSHER_TYPE_SMALL_ACTIVE)

	AddEditorVariable("length")
	SetActiveVariable("length")
	AddEnumVariable("112 Pixels", 0)
	AddEnumVariable("160 Pixels", 1)
	AddEnumVariable("80 Pixels", 2)
	AddEnumVariable("120 Pixels", 3)
	AddEnumVariable("56 Pixels", 4)
	AddEnumVariable("88 Pixels", 5)
	AddEnumVariable("184 Pixels", 6)
end event
