//#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["Spell #1"]
#Background["./BG/BG.dnh"]
#Player["./Player/AoCF_YukariReimu/AoCF_YukariReimu.dnh"]
#System["./System/System.dnh"]
#include "./LIB/Library_Index.dnh"

let bossObj;
let bossX = 0;
let bossY = 0;
let bosslife;

let bossImg = GetCurrentScriptDirectory ~ "IMG/Yabusame.png";

let diff = GetCommonData("Difficulty", 0);

@Initialize{//Declare the boss and assign the texture
	bossObj = ObjEnemy_Create(OBJ_ENEMY_BOSS);
	ObjEnemy_Regist(bossObj);

	SetAreaCommonData("System", "CurrentActiveScript", GetOwnScriptID);

	CutinPythonA1("Psychokinesis Dream Sign \"Sleepwalking in Circles\"", ["Easy", "Normal", "Hard", "Lunatic"][diff], GetCurrentScriptDirectory ~ "IMG/TwoCut.png", [192, 0, 128]);
	ObjEnemyBossScene_StartSpell(GetEnemyBossSceneObjectID);
	PlaySoundA1(13, 70, 0);

	//Move the boss onto the game field
	ObjMove_SetDestAtWeight(bossObj, GetCenterX, GetCenterY, 10, 10);
	ObjEnemy_SetDamageRate(bossObj, 0, 0);
	mainTask;
	
	if(GetCommonData("Boss", "usami") == "usami"){Tag;} //switch to Doremy
	else{
		SetCommonData("Boss", "doremy");
		AnimateBoss_Doremy(bossObj);
	}

	SetShotAutoDeleteClip(256, 256, 256, 128);
}

@Event{
	alternative(GetEventType())
	case(EV_REQUEST_LIFE){
		SetScriptResult(3000);
	}
	case(EV_REQUEST_TIMER){
		SetScriptResult(60);
	}
	case(EV_REQUEST_SPELL_SCORE){
		SetScriptResult(6000000 + diff*100000);
	}
}

@Loading{
}

@MainLoop{
	bossX = ObjMove_GetX(bossObj);
	bossY = ObjMove_GetY(bossObj);

	ObjEnemy_SetIntersectionCircleToShot(bossObj, bossX, bossY, 40);
	ObjEnemy_SetIntersectionCircleToPlayer(bossObj, bossX, bossY, 20);
	yield;
}

@Finalize{

}

task mainTask{
	EnemyName(bossObj, "Sumireko & Doremy", 255, 0, 192);

	FlameAura(bossObj, [255, 0, 192], 2);
	BottomEnemyMarker(bossObj, bossObj);
	wait(90);
	PlaySoundA1(17, 70, 0);
	ConcentrationEffect(bossObj, "Cherry", 60, 5, 128, [255, 0, 192], BLEND_ADD_ARGB);
	wait(60);
	PlaySoundA1(30, 70, 0);
	loop(30){
		BossExplodeObject(bossX, bossY, "Cherry", rand(3, 6), rand(0, 360), [255, 0, 192], BLEND_ADD_ARGB);
		BossExplodeObject(bossX, bossY, "Cherry", rand(3, 6), rand(0, 360), [255, 255, 255], BLEND_ADD_ARGB);
	}
	wait(90);

	fire;

	endTask;
	wait(120);

	ObjEnemy_SetDamageRate(bossObj, 60, 50);
	ObjEnemy_PlayHitSound(bossObj);
}

task Tag{
	if(GetCommonData("Boss", "usami") == "usami"){
		PossessionTag(ObjMove_GetX(bossObj), ObjMove_GetY(bossObj));
		ObjAnim_ForceStop(bossObj);
		Obj_SetValue(bossObj, "anim_forcestop", false);

		SetCommonData("Boss", "doremy");
		AnimateBoss_Doremy(bossObj);
	}else if(GetCommonData("Boss", "usami") == "doremy"){
		PossessionTag(ObjMove_GetX(bossObj), ObjMove_GetY(bossObj));
		ObjAnim_ForceStop(bossObj);
		Obj_SetValue(bossObj, "anim_forcestop", false); 

		SetCommonData("Boss", "usami");
		AnimateBoss_Usami(bossObj);
	}
}

task fire{
	let dir = 0;
	let switch = 1;
	loop{
		if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){return;}
		Encircle([GetPlayerX, GetPlayerY], [GetCenterX, GetCenterY], 300, [0.125*switch, 0.25*switch, 0.375*switch, 0.5*switch][diff], switch);
		switch *= (-1);
		wait(120);
		if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){return;}
		Tag;
		wait(30);
		if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){return;}
		ObjAnim_SetAttackA2(bossObj, 240);

		wait(300);
		if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){return;}
		moveDeceleration(bossObj, GetCenterX + rand(-96, 96), GetCenterY + rand(0, -128), 90, true);
		Tag;
		wait(180);
	}
}

task Encircle(pos, orbitpos, time, a2, switch){
	let core = ObjPrim_Create(OBJ_SPRITE_2D);
	Obj_SetRenderPriorityI(core, 30);
	ObjPrim_SetTexture(core, GetCurrentScriptDirectory ~ "IMG/psychic.png");
	ObjSprite2D_SetSourceRect(core, 0, 0, 128, 128);
	ObjSprite2D_SetDestCenter(core);
	ObjRender_SetPosition(core, pos[0], pos[1], 0);
	ObjRender_SetScaleXYZ(core, 0, 0, 0);
	Obj_SpinXYZ(core, 0, 0, -7, 0);

	//spawn bullets
	let dir = -90;
	let radius = 64;
	let delayTime = time - 60;

	alternative(diff)
	case(0){
		loop(45){
			if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){return;}
			PlaySoundA1(95, 50, 0);
			PlaySoundA1(54, 60, delayTime);
			PlaySoundA1(54, 60, delayTime + 60);
			PlaySoundA1(54, 60, delayTime + 90);
			loop(3){
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1.5, dir + 180, PELLET_RED, delayTime + 60);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1, dir + 120, PELLET_PURPLE, delayTime + 90);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 2, dir, S_STAR_BLUE+1000, delayTime);
				dir += 360/3;
			}
			dir += 3.5*switch;
			radius++;
			delayTime++;
			wait(2);
		}
	}
	case(1){
		loop(45){
			if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){return;}
			PlaySoundA1(95, 50, 0);
			PlaySoundA1(54, 60, delayTime);
			PlaySoundA1(54, 60, delayTime + 60);
			PlaySoundA1(54, 60, delayTime + 90);
			loop(3){
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1.5, dir + 180, PELLET_RED, delayTime + 60);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1, dir + 120, PELLET_PURPLE, delayTime + 90);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1, dir - 120, PELLET_PURPLE, delayTime + 90);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 2, dir, S_STAR_BLUE+1000, delayTime);
				dir += 360/3;
			}
			dir += 3.5*switch;
			radius++;
			delayTime++;
			wait(2);
		}
	}
	case(2){
		loop(60){
			if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){return;}
			PlaySoundA1(95, 50, 0);
			PlaySoundA1(54, 60, delayTime);
			PlaySoundA1(54, 60, delayTime + 60);
			PlaySoundA1(54, 60, delayTime + 90);
			loop(3){
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1.5, dir + 180, PELLET_RED, delayTime + 60);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1, dir + 120, PELLET_PURPLE, delayTime + 90);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1, dir - 120, PELLET_MAGENTA, delayTime + 90);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 2, dir, S_STAR_BLUE+1000, delayTime);
				dir += 360/3;
			}
			dir += 5*switch;
			radius++;
			delayTime++;
			yield;
		}
	}
	case(3){
		loop(60){
			if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){return;}
			PlaySoundA1(95, 50, 0);
			PlaySoundA1(54, 60, delayTime);
			PlaySoundA1(54, 60, delayTime + 60);
			PlaySoundA1(54, 60, delayTime + 90);
			loop(3){
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1.5, dir + 180, PELLET_RED, delayTime + 60);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1, dir + 120, PELLET_PURPLE, delayTime + 90);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 1, dir - 120, PELLET_MAGENTA, delayTime + 90);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 2, dir + 90, S_STAR_BLUE+1000, delayTime);
				EncircleBullet(pos[0] + radius*cos(dir), pos[1] + radius*sin(dir), 2, dir - 90, S_STAR_BLUE+1000, delayTime);
				dir += 360/3;
			}
			dir += 5*switch;
			radius++;
			delayTime++;
			yield;
		}
	}

	wait(60);

	PlaySoundA1(8, 60, 0);
	ascent(i in 0 .. 61){
		if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){break;}
		ObjRender_SetScaleXYZ(core, overshoot(0, 2, i/60, 1), overshoot(0, 2, i/60, 1), 0);
		yield;
	}

	let a = GetPointAngle(pos[0], pos[1], orbitpos[0], orbitpos[1]);
	let rad = GetDistance(pos[0], pos[1], orbitpos[0], orbitpos[1]);
	loop(time){
		if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){break;}
		ObjRender_SetPosition(core, orbitpos[0] + rad*cos(a), orbitpos[1] + rad*sin(a), 0);

		a += a2;
		yield;
	}

	let aplus = a2;
	ascent(i in 0 .. 31){
		ObjRender_SetScaleXYZ(core, linear(2, 0, i/30), linear(2, 0, i/30), 0);
		ObjRender_SetPosition(core, orbitpos[0] + rad*cos(a), orbitpos[1] + rad*sin(a), 0);

		a += a2;
		a2 += aplus/(|aplus|) * 0.125;
		yield;
	}
	Obj_Delete(core);


	task EncircleBullet(x, y, v, a, g, t){
		let obj = ShotA1(x, y, 0, a, g, 10);
		ObjMove_AddPatternA2(obj, t, NO_CHANGE, NO_CHANGE, 0.05, 0, v);
		ObjShot_SetAutoDelete(obj, false);

		let shota = GetPointAngle(ObjMove_GetX(obj), ObjMove_GetY(obj), ObjRender_GetX(core), ObjRender_GetY(core));
		let shotrad = GetDistance(ObjMove_GetX(obj), ObjMove_GetY(obj), ObjRender_GetX(core), ObjRender_GetY(core));
		loop(t){
			ObjMove_SetPosition(obj, ObjRender_GetX(core) + shotrad*cos(shota), ObjRender_GetY(core) + shotrad*sin(shota));
			yield;
		}

		ObjShot_SetAutoDelete(obj, true);
	}
}

task endTask{
	while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0) {
		yield;
	}
	DeleteShotAll(TYPE_ALL, TYPE_ITEM);
	SetAutoDeleteObject(true);
	Obj_Delete(bossObj);
	wait(60);
	CloseScript(GetOwnScriptID());
}