//#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["monoidRing"]
#System["./../../system/NSystem.dnh"]
#Player["./../../player/Reimu by plasmaflame22/Reimu_A.txt", "./../../player/Reimu by plasmaflame22/Reimu_C.txt"]
#include "./../../ZUNShot/ZUNShot_Const.txt"
#include "./../sharedFuncSamir.dnh"


let objBoss;
let width = 420;
let height = 440;
let life = 7000;
let time= 180;
let scene = GetEnemyBossSceneObjectID();

let path = GetCurrentScriptDirectory~"./../../SFX/";
let charge = LoadEffect(path~ "Charge.WAV", 80);
let horn = LoadEffect(path~ "Horn.WAV", 80);
let shot2 = LoadEffect(path~ "ATTACK2.WAV", 60);
let shot4 = LoadEffect(path~ "ATTACK4.WAV", 80);
let shot5 = LoadEffect(path~ "ATTACK5.WAV", 70);
let whistle = LoadEffect(path~ "Whistle.WAV", 60);
let twinkle = LoadEffect(path~ "TWINKLE.WAV", 80);



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


@Initialize{
    objBoss = ObjEnemy_Create(OBJ_ENEMY_BOSS);
	ObjEnemy_Regist(objBoss);
	SetPlayerClip(5,5, 415, 435);
    ObjEnemyBossScene_StartSpell(scene);
	
	SetCommonData("non1", "no");
	SetCommonData("spell", "monoid");
	
	animSpell(objBoss, 1);
	TFinalizeSpell(scene, objBoss, false, true);
	
	Name(1, objBoss);
    Indicator(objBoss, 1);
    takeDamage(objBoss, scene, life);
	
	ObjMove_SetDestAtFrame(objBoss, width/2, 0.35*height, 60);
	Main;
}

@MainLoop{
    ObjEnemy_SetIntersectionCircleToShot(objBoss, ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 32); 
    ObjEnemy_SetIntersectionCircleToPlayer(objBoss, ObjMove_GetX(objBoss), ObjMove_GetY(objBoss), 28);
    yield;
}


task Main{
	SetForbidPlayerShot(false);
	SetForbidPlayerSpell(false);
    ObjEnemy_SetDamageRate(objBoss, 0, 0);
	Spell("Ring theory:[r]Monoids united", objBoss, 1);
    wait(200); 
	ObjEnemy_SetDamageRate(objBoss, 10, 0);
	
	let ang = rand(0,360);
	slowSpir(8, 7, [0.7, 2.1], ang, 3.5, 24, 56, 3, 60);
	wait(45);
	slowSpir(8, 7, [0.7, 2.1], ang, -3.5, -24, 51, 3, 60);
	wait(40);
	ObjEnemy_SetDamageRate(objBoss, 60, 10);
	
	while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0.8*life && ObjEnemyBossScene_GetInfo(scene, INFO_TIMER)>3*time/4){yield;}
	ObjEnemy_SetDamageRate(objBoss, 10, 0);
	ObjSound_Play(LoadEffect(path~"ATTACK3.WAV", 90));
	loop(5){DeleteShotAll(TYPE_SHOT,TYPE_FADE); yield;}
	arrow(12);
	wait(120);
	ObjEnemy_SetDamageRate(objBoss, 60, 10);
	
	while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>life*0.6 && ObjEnemyBossScene_GetInfo(scene, INFO_TIMER)>time/2){yield;}
	ObjEnemy_SetDamageRate(objBoss, 10, 0);
	ObjSound_Play(LoadEffect(path~"ATTACK3.WAV", 90));
	loop(5){DeleteShotAll(TYPE_SHOT,TYPE_FADE); yield;}
	trails(6, 200);
	wait(120);
	ObjEnemy_SetDamageRate(objBoss, 60, 10);
	
	
	while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>life*0.35 && ObjEnemyBossScene_GetInfo(scene, INFO_TIMER)> time/3){yield;}
	ObjEnemy_SetDamageRate(objBoss, 10, 0);
	ObjSound_Play(LoadEffect(path~"ATTACK3.WAV", 90));
	loop(5){DeleteShotAll(TYPE_SHOT,TYPE_FADE); yield;}
	
	let numBul = 20; 
	while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){
	    ObjSound_Play(shot5);
	    let ang = rand(0,360);
	    ascent(i in 0..numBul){
			if(ObjEnemy_GetInfo(objBoss, INFO_LIFE)<=0){return;}
		    CreateShotA1(X(objBoss), Y(objBoss), 1.6, ang +360/numBul *i, 76, 5);
		}
		wait(60);
		ObjEnemy_SetDamageRate(objBoss, 60, 10);
	}	
}

//task trail(obj, delayLaser, spread, speed, graphic, numBul, delay){


task trails(delay, pause){
    let dir =1;
    while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){
		if(ObjEnemy_GetInfo(objBoss, INFO_LIFE)<=0){return;}
	    let y = rand(0.15*height, 0.35*height); let ydest = y + rand(0.15*height, 0.35*height);
		let obj = CreateShotA1(width/2 - dir * (width/2 +20) , y, 0,0, 284, 0);
		ObjShot_SetSpellResist(obj, true);
		let ang = findAngRad(width/2 + dir * width/2, X(obj), ydest, y)[0];
		ObjMove_SetAngle(obj, ang);
		trail(obj, [40, 5], 30, [4,6], [241, 242], 2, 1);
		spawn(obj,delay);
		wait(pause); dir*=-1;
	}
}


// delayLaser used for objects not moving yet. First argument is the actual delay, the second is the final speed of the object bullet.

task trail(obj, delayLaser, spread, speed, graphic, numBul, delay){
    let s = spread/2; 
	if(delayLaser[0]> 1){
	    DelayLaser(obj, X(obj), Y(obj), ObjMove_GetAngle(obj), 700, 40, 25, delayLaser[0]);
		ObjSound_Play(horn);
		wait(delayLaser[0]); ObjMove_SetSpeed(obj, delayLaser[1]);
	}
	if(! Obj_IsDeleted(obj)){
	    ObjSound_Play(whistle); 
		sound(obj);
	}
	while(! Obj_IsDeleted(obj)){
	    let ang = ObjMove_GetAngle(obj);
	    loop(numBul){
		    if(Obj_IsDeleted(obj)){return;}
			CreateShotA1(ObjMove_GetX(obj), ObjMove_GetY(obj), rand(speed[0], speed[1]), ang+180+rand(-s,s), truncate(rand(graphic[0], graphic[1])), 0);
		}
		wait(delay);
	}
}	

task sound(obj){
	wait(5);
    shotSound(shot2, -1, 60, 3, obj, true, 0, scene, 0);
}


task spawn(obj, delay){
	wait(60);
    while(X(obj)>30 && X(obj)<width-30){
		if(ObjEnemy_GetInfo(objBoss, INFO_LIFE)<=0){return;}
	    let obja = CreateShotA1(X(obj) , Y(obj), 0,0, 232, 15);
		wait(delay); toPlayer(obja);
	}
}

task toPlayer(obja){
    wait(60);
	if(!Obj_IsDeleted(obja)){ObjMove_SetAngle(obja, GetAngleToPlayer(obja));}
	wait(60);
	if(!Obj_IsDeleted(obja)){ObjSound_Play(twinkle); ObjMove_SetSpeed(obja, 2);}
}


task arrow(pause){
    let dir = 1;
    while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){
	    if(ObjEnemy_GetInfo(objBoss, INFO_LIFE)<=0){return;}
	    let obj = CreateShotA1(width/2+ dir* rand(1, width/2-10), 0, rand(1, 2.4), 90, 411, 10);
		Obj_SetRenderPriorityI(obj, 60);
	    wait(pause);
		dir*=-1;
	}
}
		


task slowSpir(numBranch, numBul, speed, ang, smallAngInc, angInc, graphic, delay, pause){
    let inc = (speed[1]-speed[0])/numBul;
	while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){
		shotSound(shot4, numBul*delay, 45, 2, objBoss, false, 0, scene, 0);
		ascent(i in 0..numBul){
			ascent(j in 0..numBranch){
				if(ObjEnemy_GetInfo(objBoss, INFO_LIFE)<=0){return;}
				let obj = CreateShotA1(X(objBoss),Y(objBoss), speed[0]+inc*i, ang + smallAngInc*i + 360/numBranch *j, graphic, 4);
				Obj_SetRenderPriorityI(obj, 59);
			}
			wait(delay);
		}
		wait(pause); ang+= angInc;
	}
}

