#東方弾幕風[Player]
#ScriptVersion[3]	//スクリプトバージョン3が必須です
#ID["Haiji Senri"]
#Title["Haiji Senri"]
#Text["Special Ability:[r]Energy Field[r]Flash bomb is replaced with an [r]energy field, which increases [r]your stats while inside.[r]Said increases include:[r]Increased Movement Speed[r]Decreased Shot Delay[r]Increased Shot Damage[r]Flash bomb takes longer to [r]charge."]
#Image["./img/cutin.png"]
#ReplayName["Haiji"]

let Player = GetPlayerObjectID();
let objSlowShot = ID_INVALID;
let current = GetCurrentScriptDirectory();
let prx;
let pry;
let flash = 0;
let PlayerType = 0;
let damageMultiplier = 1;
let shotDamage = 17/2.45;

let flashposition = "BPOHC";   //CHANGE THIS IF YOU WANT TO CHANGE FLASHBOMB POSITION, POSITIONS ARE LISTED IN THE "README" FILE

@Initialize
{
	let path = current ~ "Default_Player_RumiaShotData.txt";
	LoadPlayerShotData(path); //自弾画像ロード

	SetPlayerSpeed(4/1.42,2.5/1.42);
	ObjPlayer_AddIntersectionCircleA1(Player, 0, 0, 1, 20); //当たり判定登録
	SetPlayerRebirthFrame(30);
	SetPlayerDownStateFrame(2);

	SetPlayerSpell(3);
	TImage();//自機描画用タスク起動
	FocusImage();
	TShot();//弾発射用タスク起動
	TMagicCircle();//無敵時間魔法陣タスク起動
	FlashMeter();
}

function GetDistance(x, y, x2, y2)
{
	let d = ((x2-x)^2 + (y2-y)^2)^0.5;
	return d;
}

@MainLoop
{
	yield;
}

@Finalize
{
}

@Event
{
	alternative(GetEventType())
	case(EV_REQUEST_SPELL)
	{
		if(IsPermitPlayerSpell&&GetVirtualKeyState(VK_SLOWMOVE)!=KEY_FREE&&GetPlayerSpell >= 1)
		{
			TSpell();
			SetPlayerSpell(GetPlayerSpell-1);
			SetScriptResult(true);
		}
		else if(GetVirtualKeyState(VK_SLOWMOVE)==KEY_FREE && flash==100)
		{
			TPlay(GetCurrentScriptDirectory~"./../se/se_flash.wav");
			FlashBomb;
			flash=0;
			SetScriptResult(false);
		}
		else{SetScriptResult(false);}
	}
	case(EV_HIT)
	{
		TPlay(GetCurrentScriptDirectory~"./../se/se_hit.wav");
		SetForbidPlayerShot(true);
	}
	case(EV_PLAYER_SHOOTDOWN)
	{
		prx = GetPlayerX;
		pry = GetPlayerY;
		TPlay(GetCurrentScriptDirectory~"./../se/se_barrier.wav");
		TExplosion(0.1,[rand(0,255),rand(0,255),rand(0,255)]);
		SetForbidPlayerShot(false);
	}
	case(EV_PLAYER_REBIRTH)
	{
		//復帰
		SetPlayerSpell(3);
		SetPlayerInvincibilityFrame(180);
		ObjMove_SetPosition(Player,prx,pry);
		SetForbidPlayerShot(false);
		ForbidSpells;
	}
	case(EV_GRAZE)
	{
		TPlay(GetCurrentScriptDirectory~"./../se/se_thrill.wav");
	}
}

task ForbidSpells
{
	SetForbidPlayerSpell(true);
	wait(120);
	SetForbidPlayerSpell(false);
}

task FlashBomb
{
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj,GetCurrentScriptDirectory~"./../img/circle.png");
	Obj_SetRenderPriority(obj,0.6);
	ObjRender_SetBlendType(obj,BLEND_INV_DESTRGB);
	ObjSprite2D_SetSourceRect(obj,0,0,512,512);
	let r = 150;
	ObjSprite2D_SetDestRect(obj,-r,-r,r,r);
	let x = GetPlayerX;
	let y = GetPlayerY;
	ObjRender_SetPosition(obj,x,y,0);
	let objS = ObjSpell_Create;
	ObjSpell_SetDamage(objS,0);
	ObjSpell_SetEraseShot(objS,true);
	ObjSpell_Regist(objS);
	loop(300)
	{
		if(GetDistance(x,y,GetPlayerX,GetPlayerY)<r)
		{
			SetPlayerInvincibilityFrame(60); damageMultiplier = 1.75; SetPlayerSpeed((4/1.42)*1.75,(2.5/1.42)*1.75);
		}
		else
		{
			damageMultiplier = 1;
			SetPlayerSpeed(4/1.42,2.5/1.42);
		}
		ObjSpell_SetIntersectionCircle(objS,x,y,r);
		ObjSprite2D_SetDestRect(obj,-r,-r,r,r);
		r-=150/300;
		yield;
	}
	damageMultiplier = 1;
	SetPlayerSpeed(4/1.42,2.5/1.42);
	Obj_Delete(obj);
	Obj_Delete(objS);
}

function GetClipMaxX
{
	return GetStgFrameWidth;
}

function GetClipMaxY
{
	return GetStgFrameHeight;
}

function GetCenterX
{
	return GetStgFrameWidth/2;
}

function GetCenterY
{
	return GetStgFrameHeight/2;
}

task FlashMeter{
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj, GetCurrentScriptDirectory ~ "./../img/gauge_00.png");
	ObjSprite2D_SetSourceRect(obj, 0,0,260,15);
	ObjSprite2D_SetDestCenter(obj);
	ObjRender_SetAngleZ(obj,90);
	Obj_SetRenderPriority(obj, 0.9);
	let x = 537-10;
	let y = 462-130; //currently at BPOHC version
	if(flashposition=="REGULAR"){x=17-10; y=480-130;}
	ObjRender_SetPosition(obj, x,y,0); //x = 17-10 y = 480-130;

	let obj2 = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj2, GetCurrentScriptDirectory ~ "./../img/gauge_01.png");
	ObjSprite2D_SetSourceRect(obj2, 0,0,256,4);
	ObjSprite2D_SetDestCenter(obj2);
	ObjRender_SetAngleZ(obj2,90);
	Obj_SetRenderPriority(obj2, 0.9);
	ObjRender_SetPosition(obj2, x,y,0);
	ObjRender_SetScaleY(obj2,1.5);

	let t = 0;
	let grazusi = GetGraze;
	let flashAc = false;

	while(true){
		grazusi = GetGraze;

		ObjRender_SetY(obj2, y+256/2-256/2/100*flash);
		ObjRender_SetScaleX(obj2,1/100*flash);

		t++;

		yield;

		flash = min(100,flash+(GetGraze-grazusi));

		if(flash == 100){
			ObjRender_SetColor(obj2,255,200+55*cos(t*3),200+55*cos(t*3));
			if(!flashAc){flashAc = true; TPlay(GetCurrentScriptDirectory~"./../se/se_charge.wav");}
		}
		else{
			flashAc = false;
			ObjRender_SetColor(obj2,255,255,255);
		}
	}
}

task FocusImage
{
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj,GetCurrentScriptDirectory() ~ "./../img/focus.png");
	ObjSprite2D_SetSourceRect(obj,0,0,70,70);
	ObjSprite2D_SetDestCenter(obj);
	Obj_SetRenderPriority(obj,0.6);
	ObjRender_SetAlpha(obj,0);
	let a = 0;
	let sc = 2;
	loop
	{
		ObjRender_SetPosition(obj,GetPlayerX,GetPlayerY,0);
		ObjRender_SetScaleXYZ(obj,sc,sc,0);
		ObjRender_SetAlpha(obj,a);
		ObjRender_SetAngleZ(obj,ObjRender_GetAngleZ(obj)+2);
		if(GetVirtualKeyState(VK_SLOWMOVE)!=KEY_FREE)
		{
			if(sc>1){sc-=1/14; a+=255/14;}
		}
		else
		{
			if(sc<2){sc+=1/14; a-=255/14;}
		}
		yield;
	}
}

task TImage
{
	let path = GetCurrentScriptDirectory() ~ "./img/player.png";
	ObjPrim_SetTexture(Player, path);
	Obj_SetRenderPriority(Player,0.31);
	let x = 0;
	let xx = 28;
	let yy = 47;
	let t = 0;
	loop
	{
		if(GetVirtualKeyState(VK_LEFT) == KEY_PUSH || GetVirtualKeyState(VK_LEFT) == KEY_HOLD)
		{
			ObjSprite2D_SetSourceRect(Player, x, yy, x+xx, yy*2);
		}
		else if(GetVirtualKeyState(VK_RIGHT) == KEY_PUSH || GetVirtualKeyState(VK_RIGHT) == KEY_HOLD)
		{
			ObjSprite2D_SetSourceRect(Player, x, yy*2, x+xx, yy*3);
		}
		else
		{
			ObjSprite2D_SetSourceRect(Player, x, 0, x+xx, yy);
		}
		ObjSprite2D_SetDestCenter(Player);
		if(t%6==0){x+=xx;}
		t+=1;
		if(x==xx*8){x=0;}
		yield;
	}

}

task TShot
{
	ascent(i in 0..4)
	{
		CreateOption(i);
	}
	wait(5);
	loop
	{
		while(GetVirtualKeyState(VK_SHOT)==KEY_FREE)
		{
			yield;
		}
		let shotCount = 0;
		let angle = rand(0,360);
		let a = 0;
		let r = 45;
		while(GetVirtualKeyState(VK_SHOT)!=KEY_FREE&&GetCommonData("spellactive",false)==false)
		{
			if(shotCount%10==0)
			{
				ascent(i in 0..2)
				{
					if(IsForbidPlayerShot==false){TPlay(GetCurrentScriptDirectory~"./../se/se_plst00.wav"); CreatePlayerShotA1(GetPlayerX-5+i*10,GetPlayerY-16,15,270,6,1,1);}
				}
			}
			shotCount+=1;
			yield;
		}
		wait(10);
	}

	task CreateOption(type)
	{
		let obj = ObjPrim_Create(OBJ_SPRITE_2D);
		Obj_SetRenderPriority(obj,0.31);
		ObjPrim_SetTexture(obj,GetCurrentScriptDirectory~"./img/option.png");
		ObjSprite2D_SetSourceRect(obj,0,0,16,16);
		ObjSprite2D_SetDestCenter(obj);
		Shots(obj);
		let n = 30;
		let x = GetPlayerX;
		let y = GetPlayerY;
		let xx = [-n,n,-n,n][type]; //top left, top right, bottom left, bottom right
		let yy = [-n,-n,n,n][type];
		let xxx = xx;
		let yyy = yy;
		let destx = [-25,25,-12.5,12.5][type];
		let desty = [-15,-15,-30,-30][type];

		loop
		{
			ObjRender_SetPosition(obj,x+xx,y+yy,0);
			if(GetVirtualKeyState(VK_SLOWMOVE)!=KEY_FREE)
			{
				if(xx!=destx){xx-=(xxx-destx)/10; yy-=(yyy-desty)/10;}
			}
			else
			{
				if(xx!=xxx){xx+=(xxx-destx)/10; yy+=(yyy-desty)/10;}
			}
			x+=(GetPlayerX-x)/3;
			y+=(GetPlayerY-y)/3;
			yield;
		}
	}

	task Shots(obj)
	{
		wait(5);
		loop
		{
			while(GetVirtualKeyState(VK_SHOT)==KEY_FREE)
			{
				yield;
			}
			let shotCount = 0;
			let angle = rand(0,360);
			let a = 0;
			let r = 45;
			while(GetVirtualKeyState(VK_SHOT)!=KEY_FREE&&GetCommonData("spellactive",false)==false)
			{
				let ang = 270;
				let objID = GetIntersectionRegistedEnemyID;
				ascent(i in 0..length(objID))
				{
					if(!Obj_IsDeleted(objID[i])){ang = getDotAngle(GetX(objID[i]),GetY(objID[i]),GetPlayerX,GetPlayerY); if(ang>0&&ang<180){ang=270;}}
				}
				if(GetVirtualKeyState(VK_SLOWMOVE)==KEY_FREE)
				{
					if(shotCount%5==0)
					{
						if(IsForbidPlayerShot==false)
						{
							CreateHomingAmulet(GetRX(obj),GetRY(obj));
						}
					}
				}
				else
				{
					if(shotCount%5==0)
					{
						if(IsForbidPlayerShot==false){TPlay(GetCurrentScriptDirectory~"./../se/se_plst00.wav"); CreatePlayerShotA1(GetRX(obj),GetRY(obj),15,270,shotDamage*damageMultiplier,1,1);}
					}
				}
				shotCount+=1;
				yield;
			}
			wait(5);
		}
	}
}

task CreateHomingAmulet(x,y)
{
	let ang = 270;
	let objID = GetIntersectionRegistedEnemyID;
	ascent(i in 0..length(objID))
	{
		if(!Obj_IsDeleted(objID[i])){ang = getDotAngle(GetX(objID[i]),GetY(objID[i]),x,y); if(ang>0&&ang<180){ang=270;}}
	}
	TPlay(GetCurrentScriptDirectory~"./../se/se_plst00.wav");
	let objS = CreatePlayerShotA1(x,y,10,getDotAngle(x,y,GetPlayerX,GetPlayerY),shotDamage,1,1);
	while(!Obj_IsDeleted(objS))
	{
		ObjShot_SetDamage(objS,shotDamage*damageMultiplier);
		let ang = 270;
		let objID = GetIntersectionRegistedEnemyID;
		ascent(i in 0..length(objID))
		{
			if(!Obj_IsDeleted(objID[i])){ang = getDotAngle(GetX(objID[i]),GetY(objID[i]),GetX(objS),GetY(objS)); if(ang>0&&ang<180){ang=270;}}
		}
		ObjMove_SetAngle(objS,Horming(ang,ObjMove_GetAngle(objS),10));
		yield;
	}
}

function GetRX(obj)
{
	return ObjRender_GetX(obj);
}

function GetRY(obj)
{
	return ObjRender_GetY(obj);
}

function GetX(obj)
{
	return ObjMove_GetX(obj);
}

function GetY(obj)
{
	return ObjMove_GetY(obj);
}

function Horming(toAngle, angle, dAngle){
	toAngle %= 360;
	angle %= 360;

	let ret = toAngle-angle;
	if(ret >= 180){ret -= 360;}//180°以上なら-180～180内に補正
	if(ret < -180){ret += 360;}//-180°未満なら-180～180内に補正

	if((|ret|) < dAngle){
		angle = toAngle;
	}else{
		if(sin(ret) > 0){
			angle += dAngle;
		}else{
			angle -= dAngle;
		}
	}
	if(angle >= 360){angle -= 360;}
	if(angle < 0){angle += 360;}

	return angle;
}

function getDotAngle(x1,y1,x2,y2){
	let angle=atan2(y1-y2,x1-x2);
	return angle;
}

function IsForbidPlayerShot
{
	return !IsPermitPlayerShot;
}

function wait(t){loop(t){yield;}}

function AngleTo(obj1,obj2)
{
	let dir = atan2(ObjMove_GetY(obj1)-ObjMove_GetY(obj2),ObjMove_GetX(obj1)-ObjMove_GetX(obj2));
	return dir;
}

task TMagicCircle
{
	//無敵時間の魔法陣
	//頂点奇数：偶数：円の外側、円の内側
	let countVertex = 64;
	let listRadius = [];
	loop(countVertex)
	{
		listRadius = listRadius ~ [0];
	}

	let path = current ~ "./../img/Default_Player_MagicCircle.png";
	let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D);
	ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLESTRIP);
	ObjPrim_SetVertexCount(obj, countVertex);
	ObjRender_SetBlendType(obj, BLEND_ADD_RGB);
	Obj_SetRenderPriority(obj, 0.60);
	ObjPrim_SetTexture(obj, path);
	ascent(iVert in 0..countVertex / 2)
	{
		let left = iVert * 128;
		let indexVert = iVert * 2;
		ObjPrim_SetVertexUVT(obj, indexVert + 0, left, 0);
		ObjPrim_SetVertexUVT(obj, indexVert + 1, left, 64);		
	}

	let cx = 0;
	let cy = 0;
	let maxRadius = 128;
	let alpha = 0;
	let frame = 0;
	let angleRender = 0;
	let frameInvOld = 0;

	while(true)
	{
		let frameInv = GetPlayerInvincibilityFrame();

		if(frameInv <= 0)
		{
			Obj_SetVisible(obj, false);
			frameInvOld = 0;
		}
		else
		{
			if(frameInvOld == 0)
			{
				//初期化
				ascent(iVert in 0..countVertex)
				{
					listRadius[iVert] = 0;
				}
				alpha = 0;
				frame = 0;
			}
			frameInvOld = frameInv;

			let px = GetPlayerX();
			let py = GetPlayerY();

			alpha += 1 / 120;
			alpha = min(alpha, 1);
			angleRender += 360 / countVertex / 2;
			Obj_SetVisible(obj, true);

			frameInv = min(100, frameInv);
			let rRate = frameInv / 100;

			ascent(iVert in 0..countVertex / 2)
			{
				let indexVert = iVert * 2;
				let angle = 360 / (countVertex / 2 - 1) * iVert;

				let vx1 = listRadius[indexVert] * cos(angle);
				let vy1 = listRadius[indexVert] * sin(angle);
				ObjPrim_SetVertexPosition(obj, indexVert + 0, vx1, vy1, 0);

				let vx2 = listRadius[indexVert+1] * cos(angle);
				let vy2 = listRadius[indexVert+1] * sin(angle);
				ObjPrim_SetVertexPosition(obj, indexVert + 1, vx2, vy2, 0);

				//魔方陣拡大
				if(frame >= 0)
				{//外側
					let dr = (maxRadius * rRate - listRadius[indexVert]) / 8;
					listRadius[indexVert] = listRadius[indexVert] + dr;
				}
				if(frame > 10)
				{//内側
					let rRateIn = rRate - 0.12;
					if(rRateIn < 0){rRateIn=0;}
					let dr= (maxRadius * rRateIn - listRadius[indexVert + 1]) / 16;
					listRadius[indexVert + 1] = listRadius[indexVert + 1] + dr;
				}

			}

			ObjRender_SetColor(obj, 192 * alpha, 192 * alpha, 255 * alpha);
			ObjRender_SetPosition(obj, px, py, 0);
			ObjRender_SetAngleZ(obj, angleRender);

			frame++;
		}

		yield;
	}
}

task TPlay(path)
{
	let obj = ObjSound_Create();
	ObjSound_Load(obj, path);
	ObjSound_SetSoundDivision(obj,SOUND_SE);
	ObjSound_SetVolumeRate(obj,75);
	ObjSound_Play(obj);
}

task TExplosion(sc,col)
{
	let path = GetCurrentScriptDirectory() ~ "./../img/explosion.png";
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjRender_SetBlendType(obj, BLEND_ADD_ARGB);
	Obj_SetRenderPriority(obj, 0.60);
	ObjPrim_SetTexture(obj, path);
	ObjSprite2D_SetSourceRect(obj, 0, 0, 128, 128);
	ObjSprite2D_SetDestCenter(obj);
	ObjRender_SetColor(obj,col[0],col[1],col[2]);

	let alpha = 255;
	let scale = 0;
	loop(30)
	{
		scale += sc;
		alpha -= 8;
		ObjRender_SetAlpha(obj,alpha);
		ObjRender_SetPosition(obj, GetPlayerX, GetPlayerY, 0);
		ObjRender_SetScaleXYZ(obj, scale, scale, 1);
		yield;
	}
	Obj_Delete(obj);
}

task TSpell
{
	SetForbidPlayerShot(false);
	SetCommonData("spellactive",true);
	TPlay(GetCurrentScriptDirectory~"./../se/se_spell.wav");
	SetPlayerInvincibilityFrame(300);
	let objManage = GetSpellManageObject();
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj,GetCurrentScriptDirectory~"./img/eye.png");
	Obj_SetRenderPriority(obj,0.7);
	ObjSprite2D_SetSourceRect(obj,0,0,512,512);
	ObjSprite2D_SetDestCenter(obj);
	let x = GetCenterX;
	let y = GetCenterY;
	let objID = GetIntersectionRegistedEnemyID;
	ascent(i in 0..length(objID))
	{
		if(!Obj_IsDeleted(objID[i])){x=GetX(objID[i]);
		y=GetY(objID[i]);}
	}
	ObjRender_SetPosition(obj,x,y,0);
	let sc = 0.65;
	ObjRender_SetScaleXYZ(obj,sc,sc,sc);
	let objI = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(objI,GetCurrentScriptDirectory~"./../img/circle.png");
	Obj_SetRenderPriority(objI,0.7);
	ObjSprite2D_SetSourceRect(objI,0,0,512,512);
	ObjSprite2D_SetDestCenter(objI);
	ObjRender_SetPosition(objI,GetCenterX,GetCenterY,0);
	ObjRender_SetScaleXYZ(objI,5,5,5);
	ObjRender_SetAlpha(objI,0);
	ObjRender_SetColor(objI,0,0,0);

	ascent(i in 0..15)
	{
		ObjRender_SetAngleX(obj,-90+i*90/14);
		yield;
	}
	let objS = ObjSpell_Create;
	ObjSpell_SetEraseShot(objS,true);
	ObjSpell_Regist(objS);
	ascent(i in 0..210)
	{
		ObjSpell_SetIntersectionCircle(objS,x,y,150);
		ObjRender_SetAlpha(objI,255*i/209);
		ObjSpell_SetDamage(objS,40*i/209);
		Set2DCameraFocusX(GetCenterX+rand(-i*(10/210),i*(10/210)));
		Set2DCameraFocusY(GetCenterY+rand(-i*(10/210),i*(10/210)));
		ObjRender_SetAngleZ(obj,ObjRender_GetAngleZ(obj)+i*0.2);
		yield;
	}
	Set2DCameraFocusX(GetCenterX);
	Set2DCameraFocusY(GetCenterY);
	TPlay(GetCurrentScriptDirectory~"./../se/se_barrier.wav");
	ObjRender_SetAngleZ(obj,0);
	Obj_Delete(objS);
	descent(i in 0..15)
	{
		ObjRender_SetAngleX(obj,-90+i*90/14);
		ObjRender_SetAlpha(objI,255*i/14);
		yield;
	}
	Obj_Delete(obj);
	Obj_Delete(objI);
	wait(60);
	Obj_Delete(objManage);
	SetCommonData("spellactive",false);
}