#include "./BossInclude.dnh"

@Event{
	let LIFE_VALUE = 950;
	let TIME_VALUE = 60;
	alternative(GetEventType)
	case(EV_REQUEST_LIFE){
		SetScriptResult(LIFE_VALUE);
	}
	case(EV_REQUEST_TIMER){
		SetScriptResult(TIME_VALUE);
	}
}

@Initialize{
	Boundary = [64,64,64,64];
	MAIN_Initialize;
	BOSS_Initialize("CHAR_SEIJA");
	BOSS_Finalize;
	//----------//
	ObjEnemy_SetCollision(objBoss,32,16);
	ObjEnemy_SetDamageRate(objBoss,0,0);
	ObjMove_SetDestAtBrake(objBoss,CenX,CenY,60);
	ObjAnim_SetActionA1(objBoss,ACT_MOVE,60);
	//----------//
	ObjScene_SetSpellCard(4,150);
	MainThread_Standard;
}

task MainThread_Standard{
//	WideScreen -----------------------------------
	wait(70);
	PlaySoundA1(SE_CHARGE_NORM);
	ObjAnim_SetActionA1(objBoss,ACT_SHOT_B,90);
	ObjBoss_SetStepChargeA1(objBoss);
	task ObjBoss_SetStepChargeA1(let objTarget){
		ascent(let i in 0..9){
			SetChargeEffectA2(objTarget,[0,-24],8,[SHOT_ARGB,SHOT_SUBT][i%2],WHITE,30);
			wait(5);
			if(!ObjEnemy_IsAlive(objTarget)){ return; }
		}
	}
	PlaySoundA1(SE_HUM_LOUD);
	SetWideScreen(90);
	ascent(let i in 0..12){
		let delTime = 120-(i*5);
		let objInv = DrawInverseCircle(GetBossX,GetBossY-24,0);
		ObjZone_SetExpandAtAccel(objInv,32/45,32,60);
		Obj_WaitDelete(objInv,delTime);
		wait(5);
	}
	wait(20);
//	Spell Card Start -----------------------------
	wait(40);
	PlaySoundA1(SE_CHARGE_WARP);
	ObjAnim_SetActionA1(objBoss,ACT_SHOT_A,60*99);
	ObjBoss_SetChargeA1(RED,6,10,30);
	ObjBoss_SetChargeA2(GREEN,6,10,30);
	wait(60);
	let rGlobal = -1;
	let expSpeed = 3.25;
	let waveTime = 45;
	SubThread_SetPatternT1;
	SubThread_SetPatternT2;
	SubThread_SetPatternT3;
	SubThread_SetPatternT4;
	wait(60);
	ObjEnemy_SetDamageRate(objBoss,25,15);
	
	task SubThread_SetPatternT1{
		wait(60);
		let objArray = [];
		while(ObjEnemy_IsAlive(objBoss)){
			let objMain = DrawInverseCircle(GetBossX,GetBossY,896);
			ObjZone_SetScaleReduction(objMain,896,expSpeed*2);
			let objSub = DrawInverseCircle(GetBossX,GetBossY,896);
			objArray = concatenate(objArray,[objSub]);
			wait(waveTime);
			if(length(objArray) > 3){
				ascent(let i in 0..2){
					Obj_Delete(objArray[i]);
					objArray = erase(objArray,i);
				}
			}
		}
	}
	
	task SubThread_SetPatternT2{
		let setAngle = 90+(360/8)/2;
		let agGlobal = 0;
		PlaySoundA1(SE_LASER_INV);
		ascent(let agCount in 0..8){
			let wayAngle = setAngle+agCount*(360/8);
			let objLoc = SetStraightLaser(GetBossX,GetBossY,0,24,wayAngle,ST_LASER_PURPLE,60,60*99);
			ObjStLaser_InitLaserControl(objLoc);
		}
		wait(60);
		let typeFlag = true;
		let agSpeed = 0;
		while(ObjEnemy_IsAlive(objBoss)){
			PlaySoundA1(SE_HUM_INV);
			ascent(let agCount in 0..8){
				let wayAngle = setAngle+agCount*(360/8);
				let objLoc = SetStraightLaser(0,0,expSpeed*waveTime,24,wayAngle,ST_LASER_PURPLE,0,60*99);
				ObjStLaser_AttachToBorder(objLoc,typeFlag);
			}
			typeFlag = switch(typeFlag);
			loop(waveTime){
				agGlobal += agSpeed*rGlobal;
				if(agSpeed < 0.50){
					agSpeed += 0.50/120;
				}
				yield;
			}
		}
		task ObjStLaser_InitLaserControl(let objTarget){
			ObjStLaser_SetExtensionAtFrame(objTarget,448,60);
			wait(60);
			let getAngle = ObjStLaser_GetAngle(objTarget);
			let getLength = ObjLaser_GetLength(objTarget)-expSpeed;
			while(getLength > 0){
				getLength -= expSpeed;
				let trueAngle = getAngle+agGlobal;
				ObjLaser_SetLength(objTarget,max(0,getLength));
				ObjStLaser_SetAngle(objTarget,trueAngle);
				yield;
			}
			Obj_Delete(objTarget);
		}
		task ObjStLaser_AttachToBorder(let objTarget, let typeFlag){
			ObjVar_SetColorValue(objTarget,PURPLE);
			ObjShot_SetAutoDelete(objTarget,false);
			if(typeFlag){
				ObjRender_SetAlpha(objTarget,128);
				ObjShot_SetIntersectionEnable(objTarget,false);
			}
			ObjStLaser_SetLightSource(objTarget,60*99);
			let iniAngle = ObjStLaser_GetAngle(objTarget);
			let iniRadius = 448;
			while(!Obj_IsDeleted(objTarget)){
				iniRadius -= expSpeed;
				if(iniRadius <= 0){ break; }
				let trueAngle = iniAngle+agGlobal;
				let rX = GetGapX(GetBossX,max(0,iniRadius),trueAngle);
				let rY = GetGapY(GetBossY,max(0,iniRadius),trueAngle);
				ObjMove_SetPosition(objTarget,rX,rY);
				ObjStLaser_SetAngle(objTarget,trueAngle);
				yield;
			}
			let getLength = ObjLaser_GetLength(objTarget)-expSpeed;
			while(!Obj_IsDeleted(objTarget)){
				getLength -= expSpeed;
				if(getLength <= 0){ break; }
				let trueAngle = iniAngle+agGlobal;
				ObjLaser_SetLength(objTarget,max(0,getLength));
				ObjStLaser_SetAngle(objTarget,trueAngle);
				yield;
			}
			Obj_Delete(objTarget);
		}
	}
	
	task SubThread_SetPatternT3{
		wait(90);
		while(ObjEnemy_IsAlive(objBoss)){
			let setAngle = 90+(360/8)/2;
			loop(40){
				PlaySoundA1(SE_SHOT_MAIN);
				PlaySoundO1(objBoss,SE_WAVE_NEW,45);
				PlaySoundO1(objBoss,SE_WAVE_SET,90);
				ascent(let iWay in 0..8){
					let wayAngle = setAngle+iWay*(360/8);
					let sX = GetBossX;
					let sY = GetBossY;
					let objLoc = CreateShotD2(sX,sY,2,2,wayAngle,-2/45,0,REV_RICE_RED,12,RED);
					ObjShot_SetReverseShotA1(objLoc,3/30,5,RICE_RED);
				}
				setAngle -= 1.33*rGlobal;
				wait(3);
				if(!ObjEnemy_IsAlive(objBoss)){ return; }
			}
			wait(45);
			setAngle += 1.33*rGlobal;
			let dMax = 9;
			descent(let d in 0..dMax){
				PlaySoundA1(SE_BURST_SIDE);
				let decSpeed = 1+d*3/(dMax-1);
				ascent(let iWay in 0..8){
					let wayAngle = setAngle+iWay*(360/8);
					let sX = GetBossX;
					let sY = GetBossY;
					let objLoc = CreateShotD1(sX,sY,decSpeed,decSpeed,wayAngle,BUBBLE_BLUE,-10,BLUE);
				}
				setAngle += 6.5*rGlobal;
				wait(5);
				if(!ObjEnemy_IsAlive(objBoss)){ return; }
			}
			wait(135);
		}
	}
	
	task SubThread_SetPatternT4{
		wait(210);
		let dispAngle = 90;
		while(ObjEnemy_IsAlive(objBoss)){
			PlaySoundA1(SE_WAVE_NEW);
			ascent(let iWay in 0..12){
				let wayAngle = 90+iWay*(360/12);
				let sX = GetGapX2(GetBossX,64,24,wayAngle,dispAngle);
				let sY = GetGapY2(GetBossY,64,24,wayAngle,dispAngle);
				CreateShotS2(sX,sY,0,wayAngle+dispAngle,3/120,3,FIRE_PURPLE,-10,PURPLE);
			}
			dispAngle += 12.25;
			wait(30);
		}
	}
	
	task ObjShot_SetReverseShotA1(let objTarget, let accSpeed, let maxSpeed, let revGraph){
		let iniGraph = ObjShot_GetImageID(objTarget);
		let iniColor = ObjVar_GetColorValue(objTarget);
		wait(45);
		if(Obj_IsDeleted(objTarget)){ return; }
		let oX = ObjMove_GetX(objTarget);
		let oY = ObjMove_GetY(objTarget);
		let getAngle = ObjMove_GetAngle(objTarget);
		ObjVar_DisableBreak(objTarget);
		Obj_WaitDelete(objTarget,1);
		// Transition --------------------
		let obj1 = CreateShotD2(oX,oY,2,2,getAngle,accSpeed,maxSpeed,revGraph,12,iniColor);
		wait(45);
		if(Obj_IsDeleted(obj1)){ return; }
		oX = ObjMove_GetX(obj1);
		oY = ObjMove_GetY(obj1);
		ObjVar_DisableBreak(obj1);
		Obj_WaitDelete(obj1,1);
		// Ending ------------------------
		CreateShotD2(oX,oY,3,3,getAngle,-1.5/30,1.5,iniGraph,12,iniColor);
	}
}

//---------------------------------------------------------------------------------
// Inverse Zone | Functions
//---------------------------------------------------------------------------------

function DrawInverseCircle(let sX, let sY, let setRadius){
	let objMain = ObjInverse_SetProperties;
	ObjRender_SetPosition(objMain,sX,sY,0);
	ObjRender_SetScaleXYZ(objMain,setRadius/512,setRadius/512,0.00);
	ObjRender_SetDeleteRoutine(objMain);
	return objMain;
	
	task ObjRender_SetDeleteRoutine(let objTarget){
		while(ObjEnemy_IsAlive(objBoss)){
			if(Obj_IsDeleted(objTarget)){ return; }
			yield;
		}
		let delTime = 30;
		descent(let d in 1..delTime+1){
			let decAlpha = d*255/delTime;
			ObjRender_SetAlphaFromRGB(objTarget,WHITE,decAlpha);
			yield;
		}
		Obj_Delete(objTarget);
	}
}

task ObjZone_SetExpandAtAccel(let objTarget, let accSpeed, let maxSpeed, let expCount){ 
	let expScale = 0;
	let expSpeed = 0;
	loop(expCount){
		expScale += expSpeed;
		if(expSpeed < maxSpeed){
			expSpeed += accSpeed;
		}
		ObjRender_SetScaleXYZ(objTarget,expScale/512,expScale/512,0.00);
		yield;
	}
}

task ObjZone_SetScaleReduction(let objTarget, let iniScale, let redSpeed){
	while(!Obj_IsDeleted(objTarget)){
		iniScale -= redSpeed;
		if(iniScale <= 0){ break; }
		ObjRender_SetScaleXYZ(objTarget,iniScale/512,iniScale/512,0.00);
		yield;
	}
	Obj_Delete(objTarget);
}