/*
	This script file is part of the Sonic 3 A.I.R. script software distribution.
	Copyright (C) 2017-2024 by Eukaryot

	Published under the GNU GPLv3 open source software license, see license.txt
	or https://www.gnu.org/licenses/gpl-3.0.en.html
*/



//-------------------------------------------------------//
// Hollow tree in AIZ 1                                  //
//-------------------------------------------------------//

//# address-hook(0x01f746) end(0x01f7b2)
function void fn01f746()
{
	objA0.box_size.x = 0xd0
	objA0.update_address = 0x01f752
	fn01f752()
}


//# address-hook(0x01f752)
function void fn01f752()
{
	fn01f7b8()

	if ((objA0.flags2a & (object.flag.P1_ON_OBJECT | object.flag.P2_ON_OBJECT)) == 0 && u16[A0 + 0x38] != 0)
	{
		--u16[A0 + 0x38]
		if (u16[A0 + 0x38] == 0)
		{
			move_area.left = 0x1300
			move_area.right = 0x4000
		}
		else
		{
			if (move_area.left != 0x1300)
			{
				if (u16[0xffffb000 + 0x10] >= 0x2d00)
				{
					move_area.left = 0x1300
				}
				else
				{
					move_area.left -= 4
				}
			}
			if (move_area.right != 0x4000)
			{
				if (u16[0xffffb000 + 0x10] < 0x2d00)
				{
					move_area.right = 0x4000
				}
				else
				{
					move_area.right += 4
				}
			}
		}
	}
#if STANDALONE
	else
	{
		if (camera.position.x.u16 < 0x2c00 && camera.position.y.u16 >= 0x0360)
		{
			move_area.right = 0x2c54 + getScreenExtend()
		}
		else if (camera.position.y.u16 < 0x0320)
		{
			move_area.right = 0x4000
		}
	}

	// Dirty hack to refresh parts of the screen and avoid visual glitches
	fillPlaneA_Default(0x2d80, 0x02e0, 512, 512)
#endif

	CheckForUnloadObject()
}


//# address-hook(0x01f7b8) end(0x01f90e)
function void fn01f7b8()
{
	A1 = 0xffffb000
	A2 = A0 + 0x30
	D6 = 3		// object.flag.P1_ON_OBJECT
	fn01f7ce()

	A1 = 0xffffb04a
	A2 = A0 + 0x34
	D6 = 4		// object.flag.P2_ON_OBJECT
	fn01f7ce()
}


function void fn01f7ce()
{
#if STANDALONE
	if (debug_mode.state)
		return
#endif

	u8 bit = (1 << D6.u8)
	if ((objA0.flags2a & bit) == 0)
	{
		if ((u8[A1 + 0x2a] & char.flag.IN_AIR) == 0)
		{
			s16 dx = objA1.position.x.u16 - objA0.position.x.u16 + 0x10
			s16 dy = objA1.position.y.u16 - objA0.position.y.u16
			if (dx >= 0 && dx < 0x40 && dy >= -0x5a && dy <= 0xa0)
			{
				if (objA1.velocity.x >= 0x600 && u8[A1 + 0x2e] == 0)
				{
					LetSonicClimbOnObject()

					u32[A2] = 0
					objA1.state = char.state.RUNNING
					u8[A1 + 0x2e] |= 0x42
					if (A1 == 0xffffb000)
					{
						if (allocDynamicObjectAfterA0())
						{
							objA1.update_address = 0x04fa0c
						}

						move_area.left = 0x2c60 - getScreenExtend()
						move_area.right = 0x2c60 + getScreenExtend()
						u16[A0 + 0x38] = 0x3c
					}
				}
			}
		}
	}
	else
	{
		D0.u16 = abs(objA1.groundspeed)
		if (D0.u16 >= 0x600)
		{
			if ((u8[A1 + 0x2a] & char.flag.IN_AIR) == 0)
			{
				D0.u16 = objA1.position.y.u16 - objA0.position.y.u16 + 0x90
				s16 minDiff = 0
			#if STANDALONE
				minDiff = 12		// For a slightly faster exit at the top
			#endif
				if (D0.s16 >= minDiff && D0.u16 <= 0x130)
				{
					fn01f914()
					return
				}
			}
			else
			{
				if (objA1.position.x.u16 < 0x2c99)
				{
					objA1.position.x.u16 = 0x2c99
					objA1.velocity.x = 0x400
				}
				if (objA1.position.x.u16 >= 0x2d66)
				{
					objA1.position.x.u16 = 0x2d66
					objA1.velocity.x = -0x400
				}
			}
		}
		else
		{
			if (u16[A2] < 0x400)
			{
				u32 backupA1 = A1
				u32 backupD6 = D6
				fn01f914()
				A1 = backupA1
				D6 = backupD6
			}
		}

		fn01f8b4()
	}
}

//# address-hook(0x01f8b4)
function void fn01f8b4()
{
	u8 bit = (1 << D6.u8)
	objA1.velocity.x >>= 1
	objA1.velocity.y >>= 1
	objA1.hitbox_extends.y = char.hitbox.y.UPRIGHT
	objA1.hitbox_extends.x = char.hitbox.x.UPRIGHT
	u16[A1 + 0x20] = 1
	objA1.flags2a |= char.flag.IN_AIR
	objA1.flags2a &= ~(char.flag.ROLLING | char.flag.ON_OBJECT)
	u8[A1 + 0x2e] &= ~(control_flag.DISABLE_WALLS | control_flag.DISABLE_ANIMATION)
	u8[A1 + 0x30] = 0		// "char.rotation.x.count"
	u8[A1 + 0x31] = 4		// "char.rotation.x.speed"
	objA0.flags2a &= ~bit
}


//# address-hook(0x01f914) end(0x01f994)
function void fn01f914()
{
	if ((u8[A1 + 0x2a] & char.flag.ON_OBJECT) == 0)
		return

	D0 = s32(objA1.groundspeed) << 8
	u32[A2] += D0
	if (s32[A2] < 0)
	{
		fn01f8b4()
		return
	}

	if (u16[A2] >= 0x400)
	{
		move_area.left = 0x1300
		move_area.right = 0x4000
	}

	D0.u16 = u16[A2] >> 1
	s16 dx = (s32(lookupSin(D0.u8)) * 0x7000) >> 16
	u16 newPosX = objA0.position.x.u16 + dx
	objA1.velocity.x = s16(newPosX - objA1.position.x.u16) << 8
	objA1.position.x.u16 = newPosX

	u16 newPosY = objA0.position.y.u16 + 0x90 - (u16[A2] >> 2)
	objA1.velocity.y = s16(newPosY - objA1.position.y.u16) << 8
	objA1.position.y.u16 = newPosY

	D0 = (u16[A2] >> 1) / 11
	objA1.animation.sprite = u8[0x01f99a + D0.u16]		// Player characters' corkscrew vertical running sprites
	D0 = objA1.animation.sprite
	SetCharacterSpritePatterns()
}
