#TouhouDanmakufu[Single]
#ScriptVersion[3]

#include "./functions.txt"

timer = 60;
let timerA = 10^10;

@Initialize
{
	Obj_SetValue(GetEnemyBossSceneObjectID,"INIT",false);
	objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS);
	ObjEnemy_Regist(objEnemy);
	bspell = true;

	TEnemyWork;
	ObjEnemy_Render;
	TBackground;
	TLife(0,0,32,0,0);
	TEnd(false);
}

@MainLoop
{
	timerA = ObjEnemyBossScene_GetInfo(objScene,INFO_TIMER);
	yield;
}

@Event
{
	alternative(GetEventType())
	case(EV_REQUEST_LIFE)
		{
		SetScriptResult(2200/spellLife);
		}
	case(EV_REQUEST_TIMER)
		{
		SetScriptResult(10^10);
		}
	case(EV_REQUEST_SPELL_SCORE)
		{
		SetScriptResult(30000);
		}
}
task TEnemyWork
{
	TXY;
	TSpellName("\"An Unwinnable Game, Repeated Forever\"");
	loop(45){yield;}
	ObjMove_SetDestAtFrame(objEnemy,enmx,-200,60);
	loop(45){yield;}
	let SSxP;
	let SSyP;
	let SStime;
	let SSShotDataEnm = [];
	let SSShotDataPla = [];
	let SSFocus;
	let SSPhase;

	let phase = 0;
	let IsLoadState = false;
	let IsSaveState = false;

	let spreadM = [6+Dif*2,10,8+Dif*4,6];

	TOrb;
	TFam;
	descent(t in 1..6)
		{
		SaveState;
		let time = 50;
		if(t == 4)
			{
			time = 38;
			}
		if(t == 3)
			{
			time = 23;
			}
		while(timerA > time)
			{
			if(timerA == time+1 && phase < 6-t)
				{
				phase = 6-t;
				if(t > 2)
					{
					PlaySound("se_Phantom2",75);
					PlaySound("se_Umi_Light1",75);
					}
				}
			yield;
			}
		}
	
	task TFam
		{
		let obj = ObjPrim_Create(OBJ_SPRITE_LIST_2D);
		ObjPrim_SetTexture(obj,GetCurrentScriptDirectory ~ "img/sprite_fam.png");
		ObjSpriteList2D_SetSourceRect(obj,3+384,3+128,122+384,122+128);
		Obj_SetRenderPriority(obj,0.45);

		let scl = [0,0,0];
		let c = 0;
		let counterM = [0,0,0];
		let counter = counterM;
		let xP = 1;
		let yP = 1;
		let xPMM = xP;
		let yPMM = yP;
		while(!Obj_IsDeleted(objEnemy))
			{
			c+=1;
			let xPM = 1;		
			let yPM = 1;
			xP += (xPM-xP)/6;
			yP += (yPM-yP)/6;
			if(IsSaveState == true)
				{
				xPMM = xP;
				yPMM = yP;
				}
			if(IsLoadState == true)
				{
				xP = xPMM;
				yP = yPMM;
				}
			ObjSpriteList2D_ClearVertexCount(obj);
			ObjSpriteList2D_SetDestRect(obj,0,0,1,1);
			ascent(t in 0..3)
				{
				if(phase >= t+1)
					{
					scl[t] = scl[t]+(1-scl[t])/20;
					counter[t] = counter[t]+1;
					ascent(n in 0..2-ceil(t/2))
						{
						let color = 0;
						let x = GetStgFrameWidth*(0.5+xP*0.45);
						let y = GetStgFrameHeight*(0.5+yP*0.45);
						if(t == 2 || (n == 0 && t == 0))							
							{
							x = GetStgFrameWidth-x;
							color+=120;
							}
						if(t == 2 || (n == 1 && t == 0))							
							{
							y = GetStgFrameHeight-y;
							color+=120;
							}
						if(counter[t] >= 60)
							{	
							alternative(t)
								case(0)
									{	
									let time = 28-Dif*6;
									let spread = spreadM[3];
									if(counter[t]%time == 0)
										{
										let c = floor(counter[t]/time);
										PlaySound("se_Shot1",70);
										ascent(i in 0..spread)
											{
											let shot = CreateBulletA1(x,y,1.5,i*360/spread+(n*2-1)*((c%2)*180/spread-c*0.5),AMULET,8,1.33,SHOT_GREEN);
											ObjShot_SetGraphic(shot,AMULET[SHOT_GREEN]-1);
											}
										}
									}
								case(1)
									{
									let spread = [spreadM[0],spreadM[1]];
									let time = 120;
									if(counter[t]%time == 0)
										{
										let angle = rand(0,360);
										PlaySound("se_Shot7",45);
										ascent(i0 in 0..spread[0])
											{
											ascent(i1 in 0..spread[1])
												{
												i1 = i1-spread[1]*0.5+0.5;
												CreateBulletA1(x,y,0.875,i0*360/spread[0]+i1*(180/8)/spread[1]+angle,SMALL,8,1.125,SHOT_PURPLE);
												}
											}
										}
									}
								case(2)
									{
									let spread = spreadM[2];
									if(counter[t]%40 == 15)
										{
										let angle = rand(0,360);
										PlaySound("se_Shot2",65);
										ascent(i in 0..spread)
											{
											CreateBulletA1(x,y,2.5,i*360/spread+angle,BL_SMALL,8,1,SHOT_BLUE);
											}
										}
									}
							}
						descent(dir in 0..2)
							{
							let scale = (2-scl[t])*(54+dir*10);
							ObjRender_SetScaleXYZ(obj,scale,scale,0);
							ObjRender_SetAlpha(obj,scl[t]*(255-dir*130));
	
							ObjRender_SetColorHSV(obj,color,(205+dir*50),255);
							ObjRender_SetPosition(obj,x,y,0);
							ObjRender_SetAngleZ(obj,color+(n*2-1)*(dir*2-1)*((t%2)*2-1)*(4+dir*3)*c);
							ObjSpriteList2D_AddVertex(obj);
							}
						}
					if(IsLoadState == true)
						{
						counter[t] = counterM[t];
						}
					}
				else
					{
					scl[t] = 0;
					counterM[t] = 0;
					counter[t] = 0;
					}
				if(IsSaveState == true)
					{
					counterM[t] = counter[t];
					}
				}
			yield;
			}
		Obj_Delete(obj);
		}

	task TOrb	
		{
		let obj = ObjPrim_Create(OBJ_SPRITE_2D);
		ObjPrim_SetTexture(obj,GetCurrentScriptDirectory ~ "img/sprite_fam.png");
		ObjSprite2D_SetSourceRect(obj,4,4,122,122);
		ObjSprite2D_SetDestRect(obj,0,0,1,1);
		Obj_SetRenderPriority(obj,0.3);
	
		let x = GetStgFrameWidth*0.5;
		let y = GetStgFrameHeight*0.5-50;
		if(GetDistance(GetPlayerX,GetPlayerY,x,y) <= 32)
			{
			if(GetPlayerY >= y)
				{
				y-=32;
				}
			else if(GetPlayerY < y)
				{
				y+=32;
				}
			}
		let xE = x;
		let yE = y;
		let xP = 0;
		let yP = 0;
		let scale = 0;
		let c = -1;

		let xM = x;
		let yM = y;
		let xEM = xE;
		let yEM = yE;
		let xPM = xP;
		let yPM = yP;
		let scaleM = scale;
		let cM = c;

		let time = 45;

		while(!Obj_IsDeleted(objEnemy))
			{
			c+=1;
			if(scale == 0)
				{
				PlaySound("se_Phantom2",75);
				PlaySound("se_Horror",75);
				}
			if(scale < 54)
				{
				scale += 54/30;
				}	
			if(c >= 60)
				{
				let count = (c-60)%(2*time+20);
				if(count == 0)
					{
					PlaySound("se_LaserDelay",120);
					xP = GetPlayerX;
					yP = GetPlayerY;
					xE = x;
					yE = y;
					}
				let angle = atan2(yP-yE,xP-xE);
				let dist = (150+0.33*max(0,GetDistance(xE,yE,xP,yP)-150))*0.5;
				if(count <= time)
					{		
					let n = (count^2)/(time^2);
					x = xE+n*dist*cos(angle);
					y = yE+n*dist*sin(angle);
					}
				else
					{
					let n = 1-((time*2-min(time*2,count))^2)/(time^2);
					x = xE+(1+n)*dist*cos(angle);
					y = yE+(1+n)*dist*sin(angle);
					}
				}
			if(IsLoadState == true)
				{
				x = xM;
				y = yM;
				xE = xEM;
				yE = yEM;
				xP = xPM;
				yP = yPM;
				scale = scaleM;
				c = cM;
				}
			if(IsSaveState == true)
				{
				xM = x;
				yM = y;
				xEM = xE;
				yEM = yE;
				xPM = xP;
				yPM = yP;
				scaleM = scale;
				cM = c;
				}
			if(GetDistance(GetPlayerX,GetPlayerY,x,y) <= scale && GetPlayerInvincibilityFrame <= 0)
				{
				LoadState;
				}
			ObjRender_SetScaleXYZ(obj,scale*2,scale*2,0);
			ObjRender_SetPosition(obj,x,y,0);
			yield;
			}
		Obj_Delete(obj);
		}
	
	task SaveState
		{
		SSxP = GetPlayerX;
		SSyP = GetPlayerY;
		SStime = ObjEnemyBossScene_GetInfo(objScene,INFO_TIMERF);
		SSShotDataEnm = [];
		SSShotDataPla = [];
		SSFocus = IsKeyState([VK_SLOWMOVE],[KEY_PUSH,KEY_HOLD]);
		SSPhase = phase;

		let shotDataEnm = GetShotIdInCircleA2(GetStgFrameWidth*0.5,GetStgFrameHeight*0.5,GetStgFrameHeight,TARGET_ENEMY);
		ascent(i in 0..length(shotDataEnm))
			{
			let shot = shotDataEnm[i];
			let array = [];
			array = array ~ [ObjMove_GetX(shot),ObjMove_GetY(shot),ObjMove_GetSpeed(shot),ObjMove_GetAngle(shot),ObjShot_GetImageID(shot),ObjShot_GetScale(shot)];
			SSShotDataEnm = SSShotDataEnm ~ [array];
			}

		let shotDataPla = GetShotIdInCircleA2(GetStgFrameWidth*0.5,GetStgFrameHeight*0.5,GetStgFrameHeight,TARGET_PLAYER);
		ascent(i in 0..length(shotDataPla))
			{
			let shot = shotDataPla[i];
			let array = [];
			array = array ~ [ObjMove_GetX(shot),ObjMove_GetY(shot),ObjMove_GetSpeed(shot),ObjMove_GetAngle(shot),ObjShot_GetImageID(shot),ObjShot_GetDamage(shot),ObjShot_GetPenetration(shot)];
			SSShotDataPla = SSShotDataPla ~ [array];
			}
		IsSaveState = true;
		yield;
		IsSaveState = false;
		}
	task LoadState
		{
		IsLoadState = true;
		SetForbidPlayerShot(true);
		SetForbidPlayerSpell(true);

		let obj = ObjPrim_Create(OBJ_SPRITE_2D);
		ObjPrim_SetTexture(obj,"");
		ObjSprite2D_SetSourceRect(obj,0,0,1,1);
		ObjSprite2D_SetDestRect(obj,-64,-64,GetStgFrameWidth+64,GetStgFrameHeight+64);
		Obj_SetRenderPriority(obj,0.7);

		descent(t in 0..5)
			{
			ObjEnemyBossScene_SetSpellTimer(objScene,SStime);

			ObjMove_SetX(objPlayer,SSxP);
			ObjMove_SetY(objPlayer,SSyP);
			if(SSFocus == true)
				{
				SetVirtualKeyState(VK_SLOWMOVE,KEY_HOLD);
				}
			else
				{
				SetVirtualKeyState(VK_SLOWMOVE,KEY_FREE);
				}
			phase = SSPhase;

			let array = GetShotIdInCircleA2(GetStgFrameWidth*0.5,GetStgFrameHeight*0.5,GetStgFrameHeight,TARGET_ALL);
			ascent(i in 0..length(array))
				{
				let shot = array[i];
				Obj_Delete(shot);
				}
			ObjRender_SetAlpha(obj,t*255/4);
			yield;
			ObjEnemyBossScene_SetSpellTimer(objScene,SStime);
			}

		ascent(i in 0..length(SSShotDataEnm))
			{
			let SD = SSShotDataEnm[i];
			let shot = CreateShotA1(SD[0],SD[1],SD[2],SD[3],SD[4],0);
			ObjShot_SetScale(shot,SD[5]/GetShotDataInfoA1(SD[4],TARGET_ENEMY,INFO_COLLISION));
			}
		SetForbidPlayerShot(false);
		SetForbidPlayerSpell(false);
		NotifyEventAll(EV_PLAYER_SHOT,SSShotDataPla);
		Obj_Delete(obj);
		IsLoadState = false;
		}
}