//--------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
//Functions to be included in in-game scripts, ie players, stages and bosses. Is automatically included in functions_stage.txt
//--------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------

#include "./functions_general.txt"

let objEnemy = ID_INVALID;
let objPlayer = GetPlayerObjectID;
let Dif = GetCommonData("DIFFICULTY",0);
let Rank = GetCommonData("RANK",0);

//Sets the player's flash bomb meter. Parameter must be a numerical value.
task SetPlayerFlash(val)
{
	Obj_SetValue(objPlayer,"PLAYER_FLASH",val);
}
//return: returns how full the player's flash bomb meter is. The flashbomb meter is considered full at 200.
function GetPlayerFlash
{
	return Obj_GetValueD(objPlayer,"PLAYER_FLASH",0);
}

//return: returns true if the player's flashbomb is currently active
function IsFlashActive
{
	return Obj_GetValueD(objPlayer,"IS_PLAYER_FLASH_ACTIVE",false);
}
//return: returns true if the player's spell is currently active
function IsSpellActive
{
	return Obj_GetValueD(objPlayer,"IS_PLAYER_SPELL_ACTIVE",false);
}
//Forbids or permits the player spell. Parameter must be true or false.
task SetForbidPlayerFlash(val)
{	
	Obj_SetValue(objPlayer,"IS_PERMIT_PLAYER_FLASH",val);
}
//return: returns false if flashbomb use is currently forbidden
function IsPermitPlayerFlash
{
	return Obj_GetValueD(objPlayer,"IS_PERMIT_PLAYER_FLASH",true);
}


//parameter 1: base x position
//parameter 2: base y position
//parameter 3: how far to the left or right it can target. If an enemy's X position is less than x-xD or greater than x+xD, that enemy can not be targetted.
//parameter 4: how far below it can target. If an enemy's Y position is greater than y+yD, that enemy can not be targetted.
//parameter 5: if set to true, it will choose the boss over any other enemy.
//return: returns an enemy ID
//Gets an enemy ID, useful for determining homing targets
//It'll target enemies with a postion less than y+yD and an x position between x-xD and x+xD.
//It always targets the enemy closest to the player.
function FHomingEnemy(x,y,xD,yD,boss)
{
	yD+=y;
	let array = GetAllEnemyID;
	let enemy = ID_INVALID;
	let dist = GetStgFrameHeight*1.5;
	if(boss == true)
		{
		let array = GetEnemyBossObjectID;
		ascent(i in 0..length(array))
			{
			enemy = array[0];
			}
		}
	if(enemy == ID_INVALID || Obj_IsDeleted(enemy))
		{
		ascent(i in 0..length(array))
			{
			let obj = array[i];
			if(!Obj_IsDeleted(obj) && GetDistance(x,y,ObjMove_GetX(obj),ObjMove_GetY(obj)) < dist && ObjMove_GetY(obj) < yD && GetDistance(x,0,ObjMove_GetX(obj),0) < xD)
				{
				enemy = obj;
				dist = GetDistance(x,y,ObjMove_GetX(obj),ObjMove_GetY(obj));
				}
			}	
		}	
	return enemy;	
}

//parameter 1: target enemy ID
//parameter 2: The x position of the object that is homing
//parameter 3: The y position of the object that is homing
//parameter 4: The angle of the object the is homing
//parameter 5: how quickly the angle changes
//return: returns an angle
//Gets the angle from a position to an enemy.
//rad changes how quickly you go from the base angle to the homing angle
//if rad is 0.1, it will turn very slowly. If rad is 30, it will turn very quickly.
//However, if rad is 0 it will automatically point the object at the enemy.
function FAngleToHomingEnemy(enemy,x,y,angle,rad)
{	
	if(enemy != ID_INVALID)
		{
		let angleA = atan2(ObjMove_GetY(enemy)-y,ObjMove_GetX(enemy)-x);
		if(rad != 0)
			{
			angle+=rad*sin(angleA-angle);
			}
		else
			{
			angle = angleA;
			}
		}
	return angle;
}

task ObjShot_Delete(shot)
	{
	Obj_Delete(shot);
	}
task ObjShot_DeleteInCircle(x,y,rad,target)
	{
	let array = GetShotIdInCircleA2(x,y,rad,target);
	ascent(i in 0..length(array))
		{
		let shot = array[i];
		ObjShot_Delete(shot);
		}
	}
task ObjShot_DeleteAll(target)
	{
	let array = GetShotIdInCircleA2(GetStgFrameHeight*0.5,GetStgFrameWidth*0.5,GetStgFrameHeight*2,target);
	ascent(i in 0..length(array))
		{
		let shot = array[i];
		ObjShot_Delete(shot);
		}
	}

task SetPlayerIntersectionEnable(value)
{
	Obj_SetValue(GetPlayerObjectID,"INTERSECTION_ENABLE",value);
}
function IsPlayerIntersectionEnable
{
	return Obj_GetValueD(GetPlayerObjectID,"INTERSECTION_ENABLE",true);
}
task SetPlayerSpellEnable(numb)
{
	Obj_SetValue(GetPlayerObjectID,"PLAYER_SPELL_ENABLE",numb);
}
function GetPlayerSpellEnable
{
	return Obj_GetValueD(GetPlayerObjectID,"PLAYER_SPELL_ENABLE",true);
}
task SetPlayerFlashEnable(val)
	{
	Obj_SetValue(objPlayer,"FLASH_PERMIT",val);
	}
function GetPlayerFlashEnable
	{
	return Obj_GetValueD(objPlayer,"FLASH_PERMIT",true);
	}
task SetPlayerHitbox(val)
	{
	Obj_SetValue(objPlayer,"PLAYER_HITBOX",val);
	}
function GetPlayerHitbox
	{
	return Obj_GetValueD(objPlayer,"PLAYER_HITBOX",0);
	}
task SetPlayerGrazebox(val)
	{
	Obj_SetValue(objPlayer,"PLAYER_GRAZEBOX",val);
	}
function GetPlayerGrazebox
	{
	return Obj_GetValueD(objPlayer,"PLAYER_GRAZEBOX",0);
	}


//These functions deal with the CreateBullet objects. They are included here because they are used in the player scripts.
//Since I use CreateBullet functions instead of CreateShot functions, ObjShot_SetIntersectionEnable no longer works. Use this function instead.
task ObjShot_SetIntersection(shot,value)
	{
	Obj_SetValue(shot,"INTERSECTION_ENABLED",value);
	}
function ObjShot_GetIntersection(shot)
	{
	return Obj_GetValueD(shot,"INTERSECTION_ENABLED",true);
	}
task ObjShot_SetScale(shot,scale)
	{
	if(shot == ID_INVALID || Obj_IsDeleted(shot)){return;}
	ObjRender_SetScaleXYZ(shot,scale,scale,0);
	Obj_SetValue(shot,"SHOT_HITBOX",GetShotDataInfoA1(ObjShot_GetImageID(shot),TARGET_ENEMY,INFO_COLLISION)*scale);
	}
//This returns the scale of the bullet
function ObjShot_GetScale(shot)
	{
	if(Obj_IsDeleted(shot)){return ID_INVALID;}
	let val = GetShotDataInfoA1(ObjShot_GetImageID(shot),TARGET_ENEMY,INFO_COLLISION);
	return Obj_GetValueD(shot,"SHOT_HITBOX",val)/val;
	}
//This returns the actual size of the bullet's hitbox
function ObjShot_GetHitbox(shot)
	{
	if(Obj_IsDeleted(shot)){return ID_INVALID;}
	return Obj_GetValueD(shot,"SHOT_HITBOX",GetShotDataInfoA1(ObjShot_GetImageID(shot),TARGET_ENEMY,INFO_COLLISION));
	}
task ObjShot_SetStrength(shot,damage)
	{
	Obj_SetValue(shot,"SHOT_DAMAGE",SHOT_DAMAGE[damage]);
	}
function ObjShot_GetStrength(shot)
	{
	if(Obj_IsDeleted(shot)){return ID_INVALID;}
	return Obj_GetValueD(shot,"SHOT_DAMAGE",100);
	}
//An additional function, similar to spell resist.
task ObjShot_ScaleDelete(shot,time)
	{
	let scaleM = 1.125*ObjShot_GetScale(shot)/GetShotDataInfoA1(ObjShot_GetImageID(shot),TARGET_ENEMY,INFO_COLLISION);
	let x = ObjMove_GetX(shot);
	let y = ObjMove_GetY(shot);
	descent(t in 0..time)
		{	
		let scale = t*scaleM/time;
		ObjMove_SetPosition(shot,x,y);
		ObjShot_SetScale(shot,scale);	
		yield;
		}
	Obj_Delete(shot);
	}
task ObjShot_AlphaDelete(shot,time)
	{
	let x = ObjMove_GetX(shot);
	let y = ObjMove_GetY(shot);
	descent(t in 0..time)
		{	
		let alpha = t*255/time;
		ObjMove_SetPosition(shot,x,y);
		ObjRender_SetAlpha(shot,alpha);	
		ObjShot_SetIntersection(shot,false);
		yield;
		}
	Obj_Delete(shot);
	}
task ObjShot_SetDeathResist(shot,val)
	{
	Obj_SetValue(shot,"IS_SHOT_DEATH_RESIST",val);
	}
function ObjShot_IsDeathResist(shot)
	{
	return Obj_GetValueD(shot,"IS_SHOT_DEATH_RESIST",false);
	}
task ObjShot_SetFlashResist(shot,val)
	{
	Obj_SetValue(shot,"IS_SHOT_FLASH_RESIST",val);
	}
function ObjShot_IsFlashResist(shot)
	{
	return Obj_GetValueD(shot,"IS_SHOT_FLASH_RESIST",false);
	}


function IsBeyondClip(obj,clip)
	{
	let value = false;
	if(ObjMove_GetX(obj) < -clip || ObjMove_GetX(obj) > GetStgFrameWidth+clip || ObjMove_GetY(obj) < -clip || ObjMove_GetY(obj) > GetStgFrameHeight+clip)
		{
		value = true;
		}
	return value;
	}	

task SetChapterGraze(val)
	{
	Obj_SetValue(objPlayer,"CHAPTER_GRAZE",val);
	}
task AddChapterGraze(val)
	{
	Obj_SetValue(objPlayer,"CHAPTER_GRAZE",GetChapterGraze+val);
	}
function GetChapterGraze
	{
	return Obj_GetValueD(objPlayer,"CHAPTER_GRAZE",0);
	}