#include"./lib/lib_shot/shot_const.txt"
#include"./lib/lib_sound/_PathSound.txt"
#include"./lib/lib_img/_PathImage.txt"
#include"./function.txt"

let BossObj;
let BossObjX = 0;
let BossObjY = 0;

let BossAlpha = 255;
let hitbox = [48,54];
let imgBossObj 	= bossSprite;

let bossHitbox = true;
let damage = 0;
let life = 4000;
let alive = true;

let objScene = GetEnemyBossSceneObjectID();

@Initialize 
{
	SetAutoDeleteObject	(true);
	BossObj = ObjEnemy_Create	(OBJ_ENEMY_BOSS);
	ObjEnemy_Regist				(BossObj);
	ObjRender_SetPosition		(BossObj,320,120,0);
	mainTask;
} 

@Event
{
	alternative(GetEventType())
	case(EV_REQUEST_LIFE)
	{
		SetScriptResult(life);
	}
}

@MainLoop 
{
	ObjEnemy_SetDamageRate	(BossObj,damage,damage);
	ObjRender_SetAlpha		(BossObj,BossAlpha);
	BossObjX = ObjMove_GetX	(BossObj);
	BossObjY = ObjMove_GetY	(BossObj);
	if(bossHitbox == true)
	{
		ObjEnemy_SetIntersectionCircleToShot(BossObj,BossObjX,BossObjY,hitbox[0]/2);
		ObjEnemy_SetIntersectionCircleToPlayer(BossObj,BossObjX,BossObjY,hitbox[1]/2);
	}
	if(ObjEnemy_GetInfo(BossObj, INFO_LIFE) > 0){alive = true;}
	if(ObjEnemy_GetInfo(BossObj, INFO_LIFE) <= 0){alive = false;}
	yield;
} 

@Finalize 
{ 
} 

task mainTask
{
	if(GetCommonData("bgMode",0) != 2){SetCommonData("bgMode",2);}
	spriteIdle(BossObj,210,imgBossObj,1);
	disperseFormation;
	loop(210){yield;}
	playSE(seSpell0,90);
	ObjEnemyBossScene_StartSpell(objScene);
	spellName(BossObj,"Autumn Crowd \"Procession of Hundred Demons\"");
	loop(180){yield;}
	mainShooter;
	ObjEnemyBossScene_SetSpellTimer(objScene,3600);
	TEnd;
}

task TEnd
{
	while(alive == true){yield;}
	SetCommonData("autoSnap",true);
	gatherFormation;
	bossHitbox = false;
	damage = 0;
	spriteIdle(BossObj,180,imgBossObj,1);
	let c = 0;
	loop(180)
	{
		if(c >= 1/6 && BossAlpha < 255){BossAlpha += 255/30;}
		c += 1/180;
		DeleteShotInCircle(TYPE_SHOT,TYPE_FADE,BossObjX,BossObjY,1280 * c);
		yield;
	}
	Obj_Delete(BossObj);
	CloseScript(GetOwnScriptID());
}

task gatherFormation
{
	let ang = rand(0,360);
	loop(10)
	{
		spectre0(BossObjX+60*sin(ang+18),BossObjY+60*cos(ang+18),5*5,ang+60,30);
		spectre0(BossObjX+60*sin(ang),BossObjY+60*cos(ang),5*3,ang,30);
		ang += 36;
	}
}

task spectre0(x,y,rr,a,time)
{
	let obj = ObjEnemy_Create	(OBJ_ENEMY);
	ObjEnemy_Regist				(obj);
	ObjRender_SetPosition		(obj,x,y,0);
	ObjRender_SetColor			(obj,180,180,180);
	moveS(BossObjX+rr*sin(a),BossObjY+rr*cos(a),time);
	let alpha = 0;
	loop(time)
	{	
		alpha += 255/time;
		ObjRender_SetAlpha	(obj,alpha);
		yield;
	}
	task moveS(x,y,time)
	{
		let pos = [ObjMove_GetX(obj),ObjMove_GetY(obj)];
		let ang = -(atan2(pos[1]-y,pos[0]-x))-90;
		let spd = GetDistance(x,y,pos[0],pos[1])/(time/2);
		let sp = spd;
		let r = sp * time;
		if(pos[0] + r * sin(ang) < pos[0])	{spriteHold(obj,time,imgBossObj,0,0.5);} // Going Left
		if(pos[0] + r * sin(ang) >= pos[0])	{spriteHold(obj,time,imgBossObj,1,0.5);} // Going Right
		loop(time)
		{
			ObjMove_SetDestAtSpeed(obj,pos[0]+r*sin(ang),pos[1]+r*cos(ang),sp);
			sp -= spd/time;
			yield;
		}
		ObjMove_SetSpeed(obj,0);
	}
	spriteIdle(obj,30,imgBossObj,0.5);
	while(alpha > 0)
	{	
		alpha -= 255/30;
		ObjRender_SetAlpha	(obj,alpha);
		yield;
	}
	Obj_Delete(obj);
}

task disperseFormation
{
	let a = rand(0,360);
	let y = 30;
	let c = 0;
	loop(12)
	{
		let aa = 0;
		loop(5)
		{
			c += 1/60;
			spectre1(320+30*sin(a+aa),120+y,320+320*c*sin(a+aa),-30,120);
			aa += 72;
			y -= 1;
			a += 3;
			yield;
		}
	}
	bossHitbox = false;
	loop(15)
	{
		BossAlpha -= 255/15;
		yield;
	}
}

task spectre1(x,y,xx,yy,time)
{
	let a = atan2(yy-y,xx-x);
	let obj = ObjEnemy_Create	(OBJ_ENEMY);
	ObjEnemy_Regist				(obj);
	ObjRender_SetPosition		(obj,x,y,0);
	spriteIdle(obj,time,imgBossObj,0.5);
	let pos = [0,0,0];
	let alpha = 0;
	existence;
	while(alpha < 255 && alive == true)
	{
		alpha += 255/30;
		ObjRender_SetAlpha		(obj,alpha);
		yield;
	}
	loop(30){yield;}
	if(xx <= x)	{spriteHold(obj,time,imgBossObj,0,0.5);}
	else		{spriteHold(obj,time,imgBossObj,1,0.5);}
	task existence
	{
		while(alive == true && time > 30){yield;}
		while(alpha > 0)
		{
			alpha -= 255/30;
			ObjRender_SetAlpha(obj,alpha);
			yield;
		}
		Obj_Delete(obj);
	}
	ObjMove_SetDestAtFrame(obj,xx,yy,time);
	loop(time){time--;yield;}
}

task mainShooter
{
	let wave = 1;
	while(alive == true)
	{
		loop(5)
		{
			circleFormation(1);
			if(wave > 1 && alive == true){spiralFormation(500);}
			loop(120){yield;}
			if(alive == true){playSE(seShot0,40);}
			circleFormation(-1);
			if(wave > 1 && alive == true){spiralFormation(140);}
			loop(120){yield;}
			if(alive == true){playSE(seShot0,40);}
			if(damage <= 0){damage = 40;}
		}
		wave ++;
	}
}

task circleFormation(m)
{
	let x = 320-180*m;
	let y = -120;
	let maxy = 480+120;
	let a = 0;
	let time = 600;
	let lp = 6;
	let mm = 1;
	spawnSpectre;
	loop(lp)
	{
		loop(time/lp)
		{
			x += 120/(time/lp)*m*mm;
			y += (maxy+150)/time;
			a += 90/time*m;
			yield;
		}
		mm *= -1;
	}
	task spawnSpectre
	{
		let ag = rand(0,360);
		loop(4)
		{
			ag -= 45*m;
			let aa = 0;
			loop(5)
			{
				spectre2(180,60,ag+aa);
				aa += 72*m;
				yield;
			}
		}
	}
	task spectre2(rx,ry,aa)
	{
		let obj = ObjEnemy_Create	(OBJ_ENEMY);
		ObjEnemy_Regist				(obj);
		ObjRender_SetPosition		(obj,x,y,0);
		ObjEnemy_SetLife			(obj,50);
		spriteIdle(obj,time,imgBossObj,0.5);
		let pos = [0,0,0];
		let alpha = 0;
		existence;
		hitbox;
		while(alpha < 255 && alive == true)
		{
			alpha += 255/30;
			ObjRender_SetAlpha		(obj,alpha);
			yield;
		}
		loop(30){yield;}
		task existence
		{
			while(ObjEnemy_GetInfo(obj,INFO_LIFE) > 0){if(alive == false){ObjEnemy_SetLife(obj,0);}yield;}
			if(ObjMove_GetX(obj) > 0 && ObjMove_GetX(obj) < 640 && ObjMove_GetY(obj) > 0 && ObjMove_GetY(obj) < 480)
			{
				charge(sfxGlow,BLEND_ADD_ARGB,180,120,60,128,ObjMove_GetX(obj),ObjMove_GetY(obj),60,180,0,rand(0,360));
				if(alive == true)
				{
					playSE(seEnemyDeath0,35);
					createShotA2(ObjMove_GetX(obj),ObjMove_GetY(obj),0,90+rand(15,-15),0.02,1.2,FIRE_ORANGE,60,BLEND_ADD_ARGB);
				}
			}
			while(alpha > 0)
			{
				alpha -= 255/15;
				ObjRender_SetAlpha(obj,alpha);
				yield;
			}
			Obj_Delete(obj);
		}
		while(alive == true && y < maxy && !Obj_IsDeleted(obj))
		{
			let pos = [x+rx*sin(a+aa),y+ry*cos(a+aa)];
			if(pos[0] < ObjMove_GetX(obj))	{spriteHold(obj,60,imgBossObj,0,0.5);}
			if(pos[0] >= ObjMove_GetX(obj))	{spriteHold(obj,60,imgBossObj,1,0.5);}
			moveS(pos[0],pos[1],60);
			loop(60){yield;}
			spriteIdle(obj,60,imgBossObj,0.5);
			if(!Obj_IsDeleted(obj) && ObjEnemy_GetInfo(obj,INFO_LIFE) > 0 && alive == true)
			{
				if(ObjMove_GetX(obj) > 0 && ObjMove_GetX(obj) < 640 && ObjMove_GetY(obj) > 0 && ObjMove_GetY(obj) < 420)
				{
					let ag = atan2(ObjMove_GetY(obj)+120,ObjMove_GetX(obj)-x);
					let spd = 1.8;
					let pos = [ObjMove_GetX(obj),ObjMove_GetY(obj)];
					let aa = ag-195*m;
					createShotB2(pos[0],pos[1],spd*cos(aa),spd*sin(aa),0,-spd*2*sin(aa)/120,spd*cos(aa),-spd*sin(aa),DOT_YELLOW,30,BLEND_ALPHA);
					spd = 1.5;
					aa = ag-205*m;
					createShotB2(pos[0],pos[1],spd*cos(aa),spd*sin(aa),0,-spd*2*sin(aa)/120,spd*cos(aa),-spd*sin(aa),DOT_YELLOW,30,BLEND_ALPHA);
					aa = ag-185*m;
					createShotB2(pos[0],pos[1],spd*cos(aa),spd*sin(aa),0,-spd*2*sin(aa)/120,spd*cos(aa),-spd*sin(aa),DOT_YELLOW,30,BLEND_ALPHA);
				}
			}
			loop(60){yield;}
		}
		task hitbox
		{
			while(!Obj_IsDeleted(obj) && ObjEnemy_GetInfo(obj,INFO_LIFE) > 0)
			{
				let dis = GetDistance(pos[0],pos[1],GetPlayerX,GetPlayerY);
				if(dis <= 16)
				{
					ObjEnemy_SetIntersectionCircleToPlayer	(obj,pos[0],pos[1],8);
					ObjEnemy_SetIntersectionCircleToPlayer	(BossObj,pos[0],pos[1],8);
				}
				ObjEnemy_SetIntersectionCircleToShot	(obj,ObjMove_GetX(obj),ObjMove_GetY(obj),8);
				ObjEnemy_SetIntersectionCircleToShot	(BossObj,ObjMove_GetX(obj),ObjMove_GetY(obj),8);
				ObjRender_SetPosition					(obj,ObjMove_GetX(obj),ObjMove_GetY(obj),0);
				yield;
			}
		}
		task moveS(x,y,time)
		{
			let pos = [ObjMove_GetX(obj),ObjMove_GetY(obj)];
			let ang = -(atan2(pos[1]-y,pos[0]-x))-90;
			let spd = GetDistance(x,y,pos[0],pos[1])/(time/2);
			let sp = spd;
			let r = sp * time;
			if(pos[0] + r * sin(ang) < pos[0])	{spriteHold(obj,time,imgBossObj,0,0.5);} // Going Left
			if(pos[0] + r * sin(ang) >= pos[0])	{spriteHold(obj,time,imgBossObj,1,0.5);} // Going Right
			loop(time)
			{
				ObjMove_SetDestAtSpeed(obj,pos[0]+r*sin(ang),pos[1]+r*cos(ang),sp);
				sp -= spd/time;
				yield;
			}
			ObjMove_SetSpeed(obj,0);
		}
	}
}

task spiralFormation(x)
{
	if(alive == true)
	{
		charge(sfxGlow,BLEND_ADD_ARGB,150,150,60,512,x,480,240,180,0,rand(0,360));
		charge(sfxGlow,BLEND_ADD_ARGB,150,150,60,512,x,480,240,180,0,rand(0,360));
	}
	loop(120){yield;}
	if(alive == true){playSE(seShot2,40);}
	let y = 480;
	let a = 0;
	let xyz = 64;
	let r = 60;
	loop(120)
	{
		a += 6;
		y -= 4;
		xyz -= 64/120;
		r -= 0.5;
		if(alive == true)
		{
			charge(sfxGlow,BLEND_ADD_ARGB,150,150,60,xyz,x+r*sin(a),y,30,60,0,rand(0,360));
			charge(sfxGlow,BLEND_ADD_ARGB,150,150,60,xyz,x+r*sin(-a),y,30,60,0,rand(0,360));
		}
		yield;
	}
	if(alive == true)
	{
		playSE(seShiny0,80);
		let lp = 10;
		let ang = rand(0,360);
		let spd = 1.2;
		loop(lp)
		{
			createShotA2(x,0,spd+0.6,ang,-0.01,spd,ORB_ORANGE,30,BLEND_ADD_ARGB);
			createShotA2(x,0,spd+1.5,ang+180/lp,-0.025,spd,ORB_ORANGE,30,BLEND_ADD_ARGB);
			createShotA2(x,0,spd+2.7,ang,-0.045,spd,ORB_YELLOW,30,BLEND_ADD_ARGB);
			createShotA2(x,0,spd+4.2,ang+180/lp,-0.07,spd,ORB_YELLOW,30,BLEND_ADD_ARGB);
			ang += 360/lp;
		}
	}
}

task createShotA2(x,y,s,ang,acc,maxs,st,d,blend)
{
	let obj = CreateShotA2(x,y,s,ang,acc,maxs,st,0);
	ObjRender_SetBlendType			(obj,blend);
	ObjRender_SetAlpha				(obj,0);
	ObjShot_SetIntersectionEnable	(obj,false);
	let alpha = 0;
	while (alpha < 255 && !Obj_IsDeleted(obj))
	{
		alpha += 255/d;
		ObjRender_SetAlpha(obj,alpha);
		yield;
	}
	ObjShot_SetIntersectionEnable	(obj,true);
}

task createShotB2(x,y,sx,sy,xspd,yspd,xspdmax,yspdmax,st,d,blend)
{
	let obj = CreateShotB2(x,y,sx,sy,xspd,yspd,xspdmax,yspdmax,st,0);
	ObjRender_SetAlpha				(obj,0);
	ObjShot_SetIntersectionEnable	(obj,false);
	ObjRender_SetBlendType			(obj,blend);
	let alpha = 0;
	while (alpha < 255 && !Obj_IsDeleted(obj))
	{
		alpha += 255/d;
		ObjRender_SetAlpha	(obj,alpha);
		yield;
	}
	ObjShot_SetIntersectionEnable	(obj,true);
}