#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["vs Border Team spell card 01 hard"]
#Text["vs Border Team spell card 01 hard"]

let tensei = false;

let ballTex = "script/player/dcs_player/magicBorder.png";
let ballTex2 = "script/player/dcs_player/yinyangglow.png";
let gapTex = "script/player/dcs_player/sukima.png";
let gapTex2 = "script/player/dcs_player/sukimar.png";
let gapTexLaser = "script/player/dcs_player/sukimalaser.png";
let gapTexLaser2 = "script/player/dcs_player/sukimalaserGlow.png";
let cutReimu = "script/thdcs/system/face/reimunorm.png";
let cutYukari = "script/thdcs/system/face/yukarinorm.png";

#include "script/thdcs/system/shotlibrary.txt"
#include "script/thdcs/functions/function_common.txt"
#include "script/thdcs/functions/function_global.txt"
#include "script/thdcs/functions/function_bosseff.txt"
#include "script/thdcs/functions/function_cutin.txt"

@Initialize {
	SetCommonData("spellScriptID",GetOwnScriptID);

	SetCommonData("isDuet", true);
	SetCommonData("bossCircleType",0);
	SetCommonData("bossAttackType",2);
	SetCommonData("bossBgType",31);
	renderBoss(31);
	renderBoss2(32);
	bossMagicCircle2;
	setAura(bossObj,255,92,92);
	setAura(boss2Obj,128,32,255);
	setInvulnerableTime(bossObj,120);
	setInvulnerableTime(boss2Obj,120);

	if(GetAreaCommonData("system","gameLang",0) == 0) { SetCommonData("cardName","zV uR̃`[gv"); } 
	if(GetAreaCommonData("system","gameLang",0) == 1) { SetCommonData("cardName","Musou Tensei uNatural cheatv"); } 	

	ObjMove_SetPosition(bossObj,bossX,bossY);
	ObjMove_SetPosition(boss2Obj,GetCommonData("boss2X",boss2X),GetCommonData("boss2Y",boss2Y));
	
	ObjMove_SetDestAtSpeed(bossObj,GetCenterX-64,120,5);
	ObjMove_SetDestAtSpeed(boss2Obj,GetCenterX+64,120,5);

	cutin(NAZRIN,cutReimu,0,0,1024,1024,0.4);
	cutin2(DUET1,0,cutYukari,0,0,1024,1024,0.4);

	SetAutoDeleteObject(true);
	mainTask;
} 

@Event { 
	alternative(GetEventType()) 
	case(EV_REQUEST_LIFE) { 
		SetScriptResult(330);
	}
	case(EV_REQUEST_TIMER) { 
		SetScriptResult(70);
	}
	case(EV_REQUEST_SPELL_SCORE) {
	    let spellCardBonus = calculateAndGetSpellCardBonus();
		SetScriptResult(spellCardBonus);
	}	
	case(EV_USER+9999) {
		SetCommonData("spellcardID","border01hard"); 
	}
} 

@MainLoop { yield; } 
@Finalize { } 

task mainTask { 
	yield;
	scriptEnding;	
	ObjMove_SetDestAtSpeed(bossObj,GetCenterX,120,5);	
	control;
} 

// Duet control
task control {
	let locX = 0;
	let locY = 0;
	wait(60);
	while(!Obj_IsDeleted(bossObj)) {
		// open gaps
		yukariGapEx(bossX,bossY,"gap");	
		yukariGapEx(boss2X,boss2Y,"gap");
		ObjEnemy_SetDamageRate(bossObj,0,0);	
		ObjEnemy_SetDamageRate(boss2Obj,0,0);	
		wait(15);
		// disappear
		ObjRender_SetAlpha(bossObj,0);
		ObjRender_SetAlpha(boss2Obj,0);
		ObjMove_SetPosition(bossObj,GetClipMinX-112,GetClipMinY-112); ObjMove_SetPosition(boss2Obj,GetClipMinX-112,GetClipMinY-112);
		wait(15);
		// pick random loc at bottom and set the gap
		locX = rand_int(GetClipMinX+96,GetClipMaxX-96);
		yukariGapEx(locX,GetClipMaxY-32,"gap");
		wait(60);
		// move there
		ObjMove_SetPosition(boss2Obj,locX,GetClipMaxY-32);
		ObjMove_SetPosition(bossObj,locX-32,ObjMove_GetY(boss2Obj));		
		wait(15);
		// appear
		ObjRender_SetAlpha(bossObj,255);
		ObjRender_SetAlpha(boss2Obj,255);
		ObjEnemy_SetDamageRate(bossObj,100,100);	
		ObjEnemy_SetDamageRate(boss2Obj,100,100);			
		wait(15);
		// attack 
		boss2Attack = 1;
		yukariGapEx(boss2X-96,boss2Y,"kunai");
		yukariGapEx(boss2X+96,boss2Y,"kunai");	
		yukariGapEx(boss2X-96,boss2Y,"laser");
		yukariGapEx(boss2X+96,boss2Y,"laser");
		wait(30);
		yukariGapEx(boss2X-96,boss2Y,"laser");
		yukariGapEx(boss2X+96,boss2Y,"laser");
		wait(15);
		// open gap
		yukariGapEx(boss2X,boss2Y,"gap");	
		ObjEnemy_SetDamageRate(bossObj,0,0);	
		ObjEnemy_SetDamageRate(boss2Obj,0,0);				
		wait(15);
		// disappear
		ObjRender_SetAlpha(bossObj,0);
		ObjRender_SetAlpha(boss2Obj,0);		
		ObjMove_SetPosition(bossObj,GetClipMinX-112,GetClipMinY-112); ObjMove_SetPosition(boss2Obj,GetClipMinX-112,GetClipMinY-112);
		wait(30);
		// pick random loc at top and set the gap
		locX = rand_int(GetClipMinX+96,GetClipMaxX-96);
		yukariGapEx(locX,GetClipMinY+48,"gap");
		wait(30);
		// move there
		ObjMove_SetPosition(boss2Obj,rand_int(GetClipMinX+96,GetClipMaxX-96),GetClipMinY+48);		
		ObjMove_SetPosition(bossObj,ObjMove_GetX(boss2Obj)-32,ObjMove_GetY(boss2Obj));		
		wait(15);
		// appear
		ObjRender_SetAlpha(bossObj,255);
		ObjRender_SetAlpha(boss2Obj,255);	
		ObjEnemy_SetDamageRate(bossObj,100,100);	
		ObjEnemy_SetDamageRate(boss2Obj,100,100);			
		wait(15);
		// attack
		yukariGapEx(boss2X-96,boss2Y,"kunai");
		yukariGapEx(boss2X+96,boss2Y,"kunai");		
		yukariGapEx(boss2X-96,boss2Y,"laser");
		yukariGapEx(boss2X+96,boss2Y,"laser");	
		wait(30);
		yukariGapEx(boss2X-96,boss2Y,"laser");
		yukariGapEx(boss2X+96,boss2Y,"laser");		
		wait(180);
		// disappear 
		yukariGapEx(bossX,bossY,"gap");
		yukariGapEx(boss2X,boss2Y,"gap");
		ObjRender_SetAlpha(bossObj,0);
		ObjRender_SetAlpha(boss2Obj,0);
		wait(15);
		// move there
		ObjMove_SetPosition(bossObj,GetCenterX,GetCenterY-96);					
		ObjMove_SetPosition(boss2Obj,GetCenterX-96,GetCenterY-112);		
		wait(15);
		// appear
		yukariGapEx(bossX,bossY,"gap");
		yukariGapEx(boss2X,boss2Y,"gap");		
		ObjRender_SetAlpha(bossObj,255);
		ObjRender_SetAlpha(boss2Obj,255);
		boss2Attack = 0;
		
		// reimu's turn
		reimuMove;
		wait(120);
		ObjMove_SetDestAtSpeed(boss2Obj,rand_int(GetClipMinX+96,GetClipMaxX-96),GetClipMinY+48,3);		
		wait(60);
		boss2Attack = 1;
		yukariGapEx(boss2X-96,boss2Y-16,"laser");
		wait(15);
		yukariGapEx(boss2X-96,boss2Y,"laser");
		wait(15);
		yukariGapEx(boss2X+32,boss2Y+32,"laser");		
		wait(15);
		yukariGapEx(boss2X-32,boss2Y+48,"laser");		
		wait(15);	
		boss2Attack = 0;	
		wait(240);
	}
	
}

// Reimu's behaviour
task reimuMove {
	let dir = 0;
	bossAttack = 1;
	concenEffect(bossObj,30,1,255,32,32);
	concenEffect(bossObj,30,1,255,255,255);
	concenEffect(bossObj,30,1,255,32,32);
	concenEffect(bossObj,30,1,255,255,255);		
	PlaySFX(SFX_CAT00);
	wait(15);
	reimuTensei(90);
	PlaySFX(SFX_BALLHUM);
	ascent(i in 0..5) { 
		reimuDiscoBallEx(bossX,bossY,dir,i);
		dir+=360/5; 
	}
	wait(60);
	bossAttack = 0;
	reimuRandMove;
	reimuAmuletCirc;
}

// Random Reimu movement
task reimuRandMove {
	loop(5) {
		ObjMove_RandomPosWeight(bossObj,rand_int(30,60),rand_int(15,30),25,30,GetClipMinX+128,GetClipMinY+112,GetClipMaxX-128,GetClipMinY+120);
		wait(60);
	}
}

// Reimu circular amulet shot
task reimuAmuletCirc {
	wait(60);
	let dir = 0;
	loop(3) { 
		PlaySFX(SFX_TAN00);
		ascent(i in 0..4) { 
			ascent(j in 0..24) { 
				CreateShotA2(bossX,bossY,1,dir,0.05,3-i/2,96,10); 
				dir+=360/24;
			} 
			dir+=33;
			wait(3);
		}
		wait(90);
	}
}
			
// Musou Tensei 
task reimuTensei(duration) {
	tensei = true;
	ObjRender_SetAlpha(bossObj,55);
	ObjEnemy_SetDamageRate(bossObj,0,0);
	loop(duration) {	
		if(Obj_IsDeleted(bossObj)) { break; } 
		reimuTenseiAura(bossX,bossY);
		wait(3);
	}
	ObjRender_SetAlpha(bossObj,255);
	ObjEnemy_SetDamageRate(bossObj,100,100);	
	tensei = false;
}

// glowy aura of Reimu for Musou Tensei
task reimuTenseiAura(x,y) {
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	let dir = 0;
	let v = 0;
	let alphaValue = 255;
	let vx = v*cos(dir);
	let vy = v*sin(dir);

	ObjPrim_SetTexture(obj,imgMidReimu);
	ObjRender_SetBlendType(obj,BLEND_ADD_ARGB);
	ObjRender_SetAlpha(obj,alphaValue);
	ObjRender_SetColor(obj,255,255,255);
	Obj_SetRenderPriorityI(obj,20);
	ObjRender_SetScaleXYZ(obj,1,1,0);
	ObjSprite2D_SetSourceRect(obj,0,0,96,128);
	ObjSprite2D_SetDestCenter(obj);
	ObjMove_SetAcceleration(obj,0.1);
	ObjMove_SetMaxSpeed(obj,3);

	dir = rand(0,360);
	colorMixer(obj,0,255,255,255);

	while(!Obj_IsDeleted(obj)) {
		ObjRender_SetPosition(obj,x,y,0);
		ObjRender_SetAlpha(obj,alphaValue);
		vx = v*cos(dir);
		vy = v*sin(dir);
		v+=0.1;
		if(alphaValue > 0) { alphaValue-=4; }
		if(alphaValue <= 0) { Obj_Delete(obj); }
		yield;
		x += vx;
		y += vy;
	}
}

// Yin Yang ball for Musou Tensei (does spell damage)
task reimuDiscoBallEx(x,y,dir,ballnum) {
	
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	let obj2 = ObjShot_Create(OBJ_SHOT);
	
	let c = 0;
	let r = 0;
	let diracc = 1;
	let dirball = 0;
	let v = 0;
	let vx = v*cos(dir);
	let vy = v*sin(dir);
	let ballSpin = rand_int(0,359);
	let scale = 0.5;
	let firetime = 160 + ballnum*30;

	// invisible shot for collision
	ObjShot_Regist(obj2);
	ObjMove_SetPosition(obj2,x,y);	
	ObjShot_SetSpellResist(obj2,true);
	
	// Reimu ball object
	ObjPrim_SetTexture(obj,ballTex);
	ObjRender_SetBlendType(obj,BLEND_ALPHA);
	ObjRender_SetAlpha(obj,255);
	ObjRender_SetColor(obj,128,128,128);
	Obj_SetRenderPriorityI(obj,41);
	ObjRender_SetScaleXYZ(obj,scale,scale,0);
	ObjSprite2D_SetSourceRect(obj,0,0,128,128);
	ObjSprite2D_SetDestCenter(obj);
	ObjRender_SetPosition(obj,x,y,0);
	ObjRender_SetPosition(obj,bossX+r*cos(dir),bossY+r*sin(dir),0);

	reimuBallGlowEx(obj,ObjMove_GetX(obj),ObjMove_GetY(obj),0.5,255,255,255,255);

	while(!Obj_IsDeleted(obj)) {
		// essential for the invisible shot
		ObjMove_SetPosition(obj2,ObjRender_GetX(obj),ObjRender_GetY(obj));
		ObjShot_SetIntersectionCircleA1(obj2,24);
		
		// anim
		ObjRender_SetAngleZ(obj,ballSpin);
		ballSpin+=5;
		if(r < 64) { r+=1.2; }

		// Ball behaviour
		if(c < firetime) {
			ObjRender_SetPosition(obj,bossX+r*cos(dir),bossY+r*sin(dir),0);
			dir-=diracc;
			if(diracc < 2) { diracc+=0.05; } 

		}
		if(c == firetime) { 
			x = ObjRender_GetX(obj); 
			y = ObjRender_GetY(obj); 
			dir = GetPointToPointAngle(GetPlayerX,GetPlayerY,ObjRender_GetX(obj),ObjRender_GetY(obj)); 
			PlaySFX(SFX_BALLMOVE);
		}
		if(c > firetime) {
			vx = v*cos(dir);
			vy = v*sin(dir);
			x += vx;
			y += vy;
			v = 5;
			ObjRender_SetPosition(obj,x,y,0);

			dirball = GetPointToPointAngle(GetPlayerX,GetPlayerY,ObjRender_GetX(obj),ObjRender_GetY(obj));
			if(dir < dirball) { dir+=0.8; } 
			if(dir > dirball) { dir-=0.8; } 
			
			if(ObjRender_GetX(obj) < GetClipMinX-64 || ObjRender_GetX(obj) > GetClipMaxX+64 || ObjRender_GetY(obj) < GetClipMinY-64 || ObjRender_GetY(obj) > GetClipMaxY+64) {
				Obj_Delete(obj);
			}
		}
		// Deletion code incase the ball gets stuck somewhere (happens)
		if(c > 300+ballnum*30) {		
			Obj_Delete(obj);	
			break;
		}
		c++;
		yield;
	}
	Obj_Delete(obj);
}

// glow effect
task reimuBallGlowEx(followObj,x,y,parts,alphaValue,red,green,blue) {

	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	let partSizeScale = parts;

	ObjPrim_SetTexture(obj,ballTex2);
	ObjRender_SetBlendType(obj,BLEND_ADD_ARGB);
	Obj_SetRenderPriorityI(obj,41);
	ObjRender_SetScaleXYZ(obj,parts,parts,0);
	ObjSprite2D_SetSourceRect(obj,0,0,128,128);
	ObjSprite2D_SetDestCenter(obj);
	ObjRender_SetPosition(obj,ObjMove_GetX(followObj),ObjMove_GetY(followObj),0);

	colorMixer(obj,255,255,255,255);

	while(!Obj_IsDeleted(followObj)) {
		ObjRender_SetPosition(obj,ObjRender_GetX(followObj),ObjRender_GetY(followObj),0);

		ObjRender_SetAlpha(obj,alphaValue);
		ObjRender_SetScaleXYZ(obj,parts,parts,0);

		// glittering effect
		parts = rand(partSizeScale,(partSizeScale+0.2));
		yield;
	}
	Obj_Delete(obj);
}

// Yukari's gap object
task yukariGapEx(x,y,type) {
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	let obj2 = ObjPrim_Create(OBJ_SPRITE_2D);

	ObjPrim_SetTexture(obj,gapTex);
	ObjRender_SetBlendType(obj,BLEND_ALPHA);
	ObjRender_SetAlpha(obj,254);
	ObjRender_SetColor(obj,128,128,128);
	Obj_SetRenderPriorityI(obj,20);
	ObjRender_SetScaleXYZ(obj,0.3,0.3,0);
	ObjSprite2D_SetSourceRect(obj,0,0,512,256);
	ObjSprite2D_SetDestCenter(obj);
	ObjRender_SetPosition(obj,x,y,0);
	ObjRender_SetAngleXYZ(obj,90,0,0);
	
	ObjPrim_SetTexture(obj2,gapTex2);
	ObjRender_SetBlendType(obj2,BLEND_ADD_ARGB);
	ObjRender_SetAlpha(obj2,0);
	ObjRender_SetColor(obj2,255,255,255);
	Obj_SetRenderPriorityI(obj2,21);
	ObjRender_SetScaleXYZ(obj2,0.3,0.3,0);
	ObjSprite2D_SetSourceRect(obj2,0,0,512,256);
	ObjSprite2D_SetDestCenter(obj2);
	ObjRender_SetPosition(obj2,x,y,0);
	ObjRender_SetAngleXYZ(obj2,90,0,0);	

	sukimaAnimationEx(obj,false,false);
	sukimaAnimationEx(obj2,true,false);
	
	if(type == "kunai") { gapKunai(obj); } 
	if(type == "laser") { 
		let laserAim = GetPointToPointAngle(GetPlayerX,GetPlayerY,ObjRender_GetX(obj),ObjRender_GetY(obj));
		CreateStraightLaserA1(ObjRender_GetX(obj),ObjRender_GetY(obj),laserAim,600,24,50,2,60);
		wait(60);
		sukimaLaserHandleEx(ObjRender_GetX(obj),ObjRender_GetY(obj),laserAim,2048,24);						
	}
	if(type == "gap") { }
}

// Kunais shot from gaps
task gapKunai(obj) { 
	let dir = GetAngleToPlayer(obj);
	ascent(i in 0..16) {
		dir = GetAngleToPlayer(obj);
		PlaySFX(SFX_TAN00);
		CreateShotA2(ObjRender_GetX(obj)+rand_int(-96,96)*cos(dir),ObjRender_GetY(obj)+rand_int(-16,16)*sin(dir),0.5,dir+rand_int(-25,25),0.05,4,76,10);
		wait(3);
		CreateShotA2(ObjRender_GetX(obj)+rand_int(-96,96)*cos(dir),ObjRender_GetY(obj)+rand_int(-16,16)*sin(dir),0.5,dir+rand_int(-25,25),0.05,4,76,10);
		wait(3);
	}
}	

// Sukima folding animation and alpha setting/fading.
task sukimaAnimationEx(obj,anim,laseronly) {
	PlaySFX(SFX_SUKIMA);
	let foldX = 90;
	let alphaValue = 0;
	loop(30) { 
		ObjRender_SetAngleX(obj,foldX);
		foldX-=3;
		yield;
	}		
	if(anim) { 
		alphaValue = 0; 
		while(alphaValue < 254) { 
			ObjRender_SetAlpha(obj,alphaValue); 
			alphaValue+=8;
			yield; 
		}	
	}
	if(!anim) { 
		alphaValue = 254; 
		while(alphaValue > 128) { 
			ObjRender_SetAlpha(obj,alphaValue); 
			alphaValue-=8; yield; 
			} 
	}
	wait(45);
	loop(10) { 
		ObjRender_SetAngleX(obj,foldX);
		foldX+=9;
		yield;
	}	
	Obj_Delete(obj);
}

// Sukima laser handle + spell damage
task sukimaLaserHandleEx(x,y,dir,lengte,dikte) {
	let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D);
	let snijl = lengte / 2;
	let maxsnijd = dikte - 12;
	let snijd = 0;
	let glide = 0;
	let c = 0;

	// Laser primitive object
	ObjPrim_SetPrimitiveType(obj,PRIMITIVE_TRIANGLESTRIP);
	ObjPrim_SetVertexCount(obj,4);	
	ObjPrim_SetTexture(obj,gapTexLaser); 
	ObjRender_SetBlendType(obj,BLEND_ADD_ARGB);
	ObjRender_SetAlpha(obj,255);
	Obj_SetRenderPriorityI(obj,40);	
	ObjRender_SetPosition(obj,x,y,0);

	// Set the angle depending on the previous
	ObjRender_SetAngleZ(obj,dir-90);
	
	sukimaLaserHandleGlowEx(x,y,dir,lengte,dikte);
	
	// SFX and quaking
	PlaySFX(SFX_LAZER02);
	quakeCam2D(3,30); quakeCam3D(3,30);
	
	while(! Obj_IsDeleted(obj)) {
		ObjPrim_SetVertexPosition(obj, 0, -snijd, snijl,0);
		ObjPrim_SetVertexUVT(obj, 0, 0, 0+glide);
		
		ObjPrim_SetVertexPosition(obj, 1, snijd, snijl,0);
		ObjPrim_SetVertexUVT(obj, 1, 64, 0+glide);
		
		ObjPrim_SetVertexPosition(obj, 2, -snijd, snijl-snijl,0);
		ObjPrim_SetVertexUVT(obj, 2, 0, 256+glide);
		
		ObjPrim_SetVertexPosition(obj, 3, snijd, snijl-snijl,0);
		ObjPrim_SetVertexUVT(obj, 3, 64, 256+glide);
		
		if(c < 60) { if(snijd < maxsnijd) { snijd+=4; } }
		if(c >= 60) { 
			snijd-=2;
			if(snijd == 0) { Obj_Delete(obj); } 
		}
		c++;
		glide+=2;
		yield;
	}
}

// Effect for the rushing ballerinas
task sukimaLaserHandleGlowEx(x,y,dir,lengte,dikte) {
	let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D);
	let snijl = lengte / 2;
	let maxsnijd = dikte;
	let snijd = 0;
	let glide = 0;
	let c = 0;

	ObjPrim_SetPrimitiveType(obj,PRIMITIVE_TRIANGLESTRIP);
	ObjPrim_SetVertexCount(obj,4);	
	ObjPrim_SetTexture(obj,gapTexLaser2); 
	ObjRender_SetBlendType(obj,BLEND_ADD_ARGB);
	ObjRender_SetAlpha(obj,255);
	Obj_SetRenderPriorityI(obj,40);	
	ObjRender_SetPosition(obj,x,y,0);
	ObjRender_SetAngleZ(obj,dir-90);

	colorMixer(obj,255,255,255,255); 

	while(! Obj_IsDeleted(obj)) {
		ObjPrim_SetVertexPosition(obj, 0, -snijd, snijl,0);
		ObjPrim_SetVertexUVT(obj, 0, 0, 0+glide);
		
		ObjPrim_SetVertexPosition(obj, 1, snijd, snijl,0);
		ObjPrim_SetVertexUVT(obj, 1, 64, 0+glide);
		
		ObjPrim_SetVertexPosition(obj, 2, -snijd, snijl-snijl,0);
		ObjPrim_SetVertexUVT(obj, 2, 0, 256+glide);
		
		ObjPrim_SetVertexPosition(obj, 3, snijd, snijl-snijl,0);
		ObjPrim_SetVertexUVT(obj, 3, 64, 256+glide);
		
		if(c < 60) { if(snijd < maxsnijd) { snijd+=4; } }
		if(c >= 60) { 
			snijd-=2;
			if(snijd == 0) { Obj_Delete(obj); } 
		}
		c++;
		glide+=2;
		yield;
	}
}

task scriptEnding {
	while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0) {
		yield;
	}

	DeleteShotAll(TYPE_ALL, TYPE_ITEM);
	Obj_Delete(bossObj);

	CloseScript(GetOwnScriptID());
}
 