//---------------------------------------------------------------------------------
// Type Constants
//---------------------------------------------------------------------------------

/* EMPTY */

//---------------------------------------------------------------------------------
// Aesthetic / Effect Functions
//---------------------------------------------------------------------------------

task Explosion_SetDestAtPos(
	let sX,
	let sY,
	let expRadius,
	let delTime,
	let blendMode,
	let RGB
	){
	ObjEffect_Explosion(sX,sY,expRadius,delTime,blendMode,RGB);
}

task Explosion_SetDestAtObj(
	let objTarget,
	let expRadius,
	let delTime,
	let blendMode,
	let RGB
	){
	let oX = ObjMove_GetX(objTarget);
	let oY = ObjMove_GetY(objTarget);
	ObjEffect_Explosion(oX,oY,expRadius,delTime,blendMode,RGB);
}

function ObjBoss_SetHexCircleA1(objTarget,blendMode,RGB){
	let objArray = [];
	let rMod = 1;
	times(2){
		let obj = ObjEffect_SetHexLayer(objTarget,1,192,3*rMod,blendMode,RGB);
		rMod = -rMod;
		objArray = concatenate(objArray,[obj]);
	}
	return objArray;
}

//---------------------------------------------------------------------------------
// Effect / Sprite Initializers
//---------------------------------------------------------------------------------

function ObjDelay_SetPropertiesA1(let RGB, let blendMode){
	let objMain = ObjPrim_Create(OBJ_SPRITE_2D);
	
	let xRect = [];
	alternative(RGB)
	case(WHITE,GRAY){ xRect = [0,64]; }
	case(RED){ xRect = [64,128]; }
	case(PURPLE,MAGENTA){ xRect = [128,192]; }
	case(BLUE){ xRect = [192,256]; }
	case(AQUA,CYAN){ xRect = [256,320]; }
	case(GREEN){ xRect = [320,384]; }
	case(YELLOW){ xRect = [384,448]; }
	case(ORANGE){ xRect = [448,512]; }
	others{
		xRect = [0,64];
		ObjRender_SetColorArray(objMain,RGB);
	}

	ObjPrim_SetTexture(objMain,EFFECT_DELAY_MAIN);
	Obj_SetRenderPriority(objMain,0.50);
	ObjRender_SetBlendType(objMain,blendMode);
	ObjSprite2D_SetSourceRect(objMain,xRect[0],0,xRect[1],64);
	ObjSprite2D_SetDestCenter(objMain);
	
	return objMain;
}

function ObjDelay_SetPropertiesA2(let RGB, let blendMode){
	let objMain = ObjPrim_Create(OBJ_SPRITE_2D);
	
	let xRect = [];
	alternative(RGB)
	case(WHITE,GRAY){ xRect = [0,64]; }
	case(RED){ xRect = [64,128]; }
	case(PURPLE,MAGENTA){ xRect = [128,192]; }
	case(BLUE){ xRect = [192,256]; }
	case(AQUA,CYAN){ xRect = [256,320]; }
	case(GREEN){ xRect = [320,384]; }
	case(YELLOW){ xRect = [384,448]; }
	case(ORANGE){ xRect = [448,512]; }
	others{
		xRect = [0,64];
		ObjRender_SetColorArray(objMain,RGB);
	}

	ObjPrim_SetTexture(objMain,EFFECT_DELAY_SOFT);
	Obj_SetRenderPriority(objMain,0.50);
	ObjRender_SetBlendType(objMain,blendMode);
	ObjSprite2D_SetSourceRect(objMain,xRect[0],0,xRect[1],64);
	ObjSprite2D_SetDestCenter(objMain);
	
	return objMain;
}

task ObjEffect_BulletBreakA1(let sX, let sY, let setAlpha, let RGB, let maxScale, let blendMode){
	let objMain = ObjPrim_Create(OBJ_SPRITE_2D);
	
	ObjPrim_SetTexture(objMain,BULLETBREAK_MAIN);
	Obj_SetRenderPriority(objMain,0.50);
	ObjRender_SetBlendType(objMain,blendMode);
	ObjRender_SetColorArray(objMain,RGB);
	ObjRender_SetAlpha(objMain,setAlpha);
	
	ObjSprite2D_SetSourceRect(objMain,0,0,64,64);
	ObjSprite2D_SetDestCenter(objMain);
	
	ObjRender_SetPosition(objMain,sX,sY,0);
	ObjRender_SetAngleXYZ(objMain,180*rand_int(1,2),0,rand_deg);
	ObjRender_SetScaleXYZ(objMain,maxScale,maxScale,0);
	
	ascent(let a in 0..8){
		let addRect = a*64;
		ObjSprite2D_SetSourceRect(objMain,addRect,0,addRect+64,64);
		wait(3);
	}
	Obj_Delete(objMain);
}

task ObjEffect_BulletBreakA2(let sX, let sY, let RGB, let maxScale, let blendMode){
	let objMain = ObjPrim_Create(OBJ_SPRITE_2D);

	let xRect = [];
	alternative(RGB)
	case(GRAY){ xRect = [0,32]; }
	case(RED){ xRect = [64,96]; }
	case(MAGENTA){ xRect = [96,128]; }
	case(PURPLE){ xRect = [128,160]; }
	case(BLUE){ xRect = [192,224]; }
	case(CYAN){ xRect = [225,256]; }
	case(AQUA){ xRect = [256,288]; }
	case(GREEN){ xRect = [320,352]; }
	case(YELLOW){ xRect =  [416,448]; }
	case(ORANGE){ xRect = [448,480]; }
	case(WHITE){ xRect = [480,512]; }
	others{
		xRect = [480,512]; 
		ObjRender_SetColorArray(objMain,RGB);
	}
	
	ObjPrim_SetTexture(objMain,BULLETBREAK_SUB);
	Obj_SetRenderPriority(objMain,0.50);
	ObjRender_SetBlendType(objMain,blendMode);
	ObjSprite2D_SetSourceRect(objMain,xRect[0],0,xRect[1],32);
	ObjSprite2D_SetDestCenter(objMain);
	
	ObjRender_SetPosition(objMain,sX,sY,0);
	ObjRender_SetAngleXYZ(objMain,0,0,rand_deg);
	ObjRender_SetAlpha(objMain,192);
	
	let dMax = 20;
	descent(let d in 1..dMax+1){
		let decScale = d*maxScale/dMax;
		let decAlpha = d*255/dMax;
		ObjRender_SetScaleXYZ(objMain,decScale,decScale,0.00);
		ObjRender_SetAlpha(objMain,decAlpha);
		yield;
	}
	Obj_Delete(objMain);
}

function ObjInverse_SetProperties{
	let objInv = ObjPrim_Create(OBJ_SPRITE_2D);
	
	ObjPrim_SetTexture(objInv,EFFECT_INVERSE);
	Obj_SetRenderPriority(objInv,0.65);
	ObjRender_SetBlendType(objInv,BLEND_INV_DESTRGB);
	ObjSprite2D_SetSourceRect(objInv,0,0,512,512);
	ObjSprite2D_SetDestCenter(objInv);
	
	return objInv;
}

function ObjNuke_SetProperties(let blendMode, let rectColor){
	let objNuke = ObjPrim_Create(OBJ_SPRITE_2D);
	
	ObjPrim_SetTexture(objNuke,NUCLEAR_MAIN);
	Obj_SetRenderPriority(objNuke,0.58);
	ObjRender_SetBlendType(objNuke,blendMode);
	ObjSprite2D_SetSourceRect(objNuke,512*rectColor,0,512*(rectColor+1),512);
	ObjSprite2D_SetDestCenter(objNuke);
	
	return objNuke;
}

function ObjRing_SetProperties{
	let objRing = ObjPrim_Create(OBJ_SPRITE_2D);

	ObjPrim_SetTexture(objRing,EFFECT_RING);
	Obj_SetRenderPriority(objRing,0.51);
	ObjRender_SetBlendType(objRing,BLEND_ADD_ARGB);
	ObjSprite2D_SetSourceRect(objRing,0,0,1024,1024);
	ObjSprite2D_SetDestCenter(objRing);
	
	return objRing;
}

//---------------------------------------------------------------------------------
// Effect / Sprite Tasks
//---------------------------------------------------------------------------------

task ObjEffect_Explosion(
	let sX, 
	let sY,
	let expRadius,
	let delTime,
	let blendMode,
	let RGB
	){
	let objMain = ObjPrim_Create(OBJ_SPRITE_2D);
	
	ObjPrim_SetTexture(objMain,EFFECT_EXPLODE);
	Obj_SetRenderPriority(objMain,0.61);
	ObjRender_SetPosition(objMain,sX,sY,0);
	ObjRender_SetBlendType(objMain,blendMode);
	ObjSprite2D_SetSourceRect(objMain,0,0,128,128);
	ObjSprite2D_SetDestCenter(objMain);
	
	let tempScale = expRadius/(delTime*delTime/2);
	let nAlpha = 1;
	descent(let ccTime in 0..delTime){
		ObjRender_SetScaleXYZ(objMain,expRadius/64,expRadius/64,0);
		ObjRender_SetColor(objMain,RGB[0]*nAlpha,RGB[1]*nAlpha,RGB[2]*nAlpha);
		expRadius += ccTime*tempScale;
		nAlpha -= 1/ccTime;
		yield;
	}
	Obj_Delete(objMain);
}

function ObjEffect_SetHexLayer(objTarget,nScale,nAlpha,angVel,blend,RGB){
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	
	ObjPrim_SetTexture(obj,EFFECT_HEX);
	Obj_SetRenderPriority(obj,0.25);
	ObjRender_SetBlendType(obj,blend);
	ObjRender_SetAlpha(obj,nAlpha);
	ObjRender_SetColor(obj,RGB[0],RGB[1],RGB[2]);
	ObjSprite2D_SetSourceRect(obj,0,0,256,256);
	ObjSprite2D_SetDestCenter(obj);
	
	Hex_Control;
	return obj;
	
	task Hex_Control{
		let lpCount = 0;
		let maxAlpha = nAlpha;
		while(!Obj_IsDeleted(objTarget)){
			let eX = ObjMove_GetX(objTarget);
			let eY = ObjMove_GetY(objTarget);
			let agCircle = angVel*lpCount;
			let sinScale = GetGapY(nScale,0.15,absolute(agCircle));
			
			ObjRender_SetAngleXYZ(obj,0,0,-agCircle);
			ObjRender_SetScaleXYZ(obj,sinScale,sinScale,0);
			ObjRender_SetPosition(obj,eX,eY,0);
			
			if(!ObjEnemy_IsAlive(objTarget) && nAlpha > 0){
				ObjRender_SetAlpha(obj,nAlpha);
				nAlpha -= maxAlpha/(45-1);
			}
			
			lpCount++;
			yield;
		}
		Obj_Delete(obj);
	}
}

//---------------------------------------------------------------------------------
// Concentration Effects
//---------------------------------------------------------------------------------


// Additive Blend --------------------------------

task ObjBoss_SetChargeA1(let RGB, let lpCount, let wtTime, let maxCount){
	times(lpCount){
		ObjCharge_SetEffectA1(RGB,BLEND_ADD_ARGB,maxCount);
		ObjCharge_SetEffectA2(RGB,BLEND_ADD_ARGB,maxCount);
		wait(wtTime);
	}
}

// Subtractive Blend -----------------------------

task ObjBoss_SetChargeA2(let RGB, let lpCount, let wtTime, let maxCount){
	times(lpCount){
		ObjCharge_SetEffectA1(RGB,BLEND_SUBTRACT,maxCount);
		ObjCharge_SetEffectA2(RGB,BLEND_SUBTRACT,maxCount);
		wait(wtTime);
	}
}

task ObjCharge_SetEffectA1(let RGB, let blendMode, let maxCount){
	let objMain = ObjRender_SetProperties;
	let agRender = [rand_deg,rand_deg,rand_deg];
	ObjRender_SetAngleXYZ(objMain,agRender[0],agRender[1],agRender[2]);
	ascent(let a in 1..maxCount+1){
		let decScale = (maxCount-a)*5.00/maxCount;
		let addAlpha = a*255/maxCount;
		if(!Obj_IsDeleted(objBoss)){
			SetAfterHalo(decScale,agRender);
			ObjRender_SetPosition(objMain,GetBossX,GetBossY,0);
		}
		ObjRender_SetScaleXYZ(objMain,decScale,decScale,0.00);
		ObjRender_SetAlpha(objMain,addAlpha);
		yield;
	}
	Obj_Delete(objMain);
	
	task SetAfterHalo(let scale, let agArray){
		let objSub = ObjRender_SetProperties;
		ObjRender_SetAngleXYZ(objSub,agArray[0],agArray[1],agArray[2]);
		ObjRender_SetScaleXYZ(objSub,scale,scale,0);
		ascent(let d in 1..21){
			let decAlpha = d*16/20;
			if(!Obj_IsDeleted(objBoss)){ 
				ObjRender_SetPosition(objSub,GetBossX,GetBossY,0);
			}
			ObjRender_SetAlpha(objSub,decAlpha);
			yield;
		}
		Obj_Delete(objSub);
	}
	
	function ObjRender_SetProperties{
		let objRender = ObjPrim_Create(OBJ_SPRITE_2D);
		
		ObjPrim_SetTexture(objRender,EFFECT_EXPLODE);
		Obj_SetRenderPriority(objRender,0.55);
		ObjRender_SetBlendType(objRender,blendMode);
		ObjRender_SetColor(objRender,RGB[0],RGB[1],RGB[2]);
		ObjSprite2D_SetSourceRect(objRender,0,0,128,128);
		ObjSprite2D_SetDestCenter(objRender);
		
		return objRender;
	}
}

task ObjCharge_SetEffectA2(let RGB, let blendMode, let maxCount){
	times(truncate(maxCount/3)){
		SetLightLaser(ST_LASER_GRAY);
		if(Obj_IsDeleted(objBoss)){ return; }
		yield;
	}
	
	task SetLightLaser(let graph){
		let objLight = SetStraightLaser(0,0,0,rand_int(6,10),rand_deg,graph,0,0);
		ObjStLaser_EndDeleteRoutine(objLight,false);
		ObjRender_SetBlendType(objLight,blendMode);
		ObjRender_SetColorArray(objLight,RGB);
		ObjShot_SetIntersectionEnable(objLight,false);
		descent(let d in 1..21){
			let decLength = d*512/20;
		//	let decAlpha = d*255/20;
			if(!Obj_IsDeleted(objBoss)){
				ObjMove_SetPosition(objLight,GetBossX,GetBossY);
			}
			ObjLaser_SetLength(objLight,decLength);
		//	ObjRender_SetAlpha(objLight,decAlpha);
			yield;
		}
		Obj_Delete(objLight);
	}
}

// Delay Light (Target) --------------------------

task SetChargeEffectA1(
	let sX,
	let sY,
	let mX,
	let mY,
	let maxRadius,
	let wayCount,
	let blendMode,
	let RGB,
	let mvTime
	){
	let xAngle = rand_deg;
	let yAngle = rand_deg;
	let zAngle = rand_deg;
	ascent(let agCount in 0..wayCount){
		let wayAngle = zAngle+agCount*(360/wayCount);
		SetTrailEffect(xAngle,yAngle,wayAngle);
	}
	let pX = sX;
	let pY = sY;
	ascent(let a in 1..mvTime+1){
		let tRatio = a*1/mvTime;
		let dT = power(tRatio,2)*(3-2*tRatio);
		sX = pX+dT*(mX-pX);
		sY = pY+dT*(mY-pY);
		yield;
	}
	task SetTrailEffect(let xAngle, let yAngle, let zAngle){
		let sinRate = 180/mvTime;
		ascent(let a in 1..mvTime+1){
			let sinRadius = maxRadius*sin(a*sinRate);
			let rX = sX+sinRadius*(cos(yAngle)*cos(zAngle)-cos(xAngle)*sin(yAngle)*sin(zAngle));
			let rY = sY+sinRadius*(sin(yAngle)*cos(zAngle)+cos(xAngle)*cos(yAngle)*sin(zAngle));
			if(Pos_IsInWideScreen(rX,rY,64)){
				ObjDelay_SetTrailSegment(rX,rY,15);
			}
			zAngle += 5*(mvTime-a)/mvTime;
			yield;
			if(!ObjEnemy_IsAlive(objBoss)){ return; }
		}
		task ObjDelay_SetTrailSegment(let x, let y, let delTime){
			let objMain = ObjDelay_SetPropertiesA2(RGB,blendMode);
		//	let objMain = ObjDelay_SetPropertiesA2(GRAY,BLEND_ADD_ARGB);
			ObjRender_SetPosition(objMain,x,y,0);
		//	ObjRender_SetColorArray(objMain,RGB);
			Obj_SetRenderPriority(objMain,0.49);
			ObjRender_SetAngleXYZ(objMain,0,0,rand_deg);
			descent(let d in 1..delTime+1){
				let decScale = d*0.75/delTime;
				let decAlpha = d*128/delTime;
				ObjRender_SetScaleXYZ(objMain,decScale,decScale,0.00);
				ObjRender_SetAlpha(objMain,decAlpha);
				yield;
				if(Obj_IsDeleted(objMain)){ break; }
			}
			Obj_Delete(objMain);
		}
	}
}

// Delay Light (Boss) ----------------------------

task SetChargeEffectA2(
	let objTarget,
	let offSet,
	let wayCount,
	let blendMode,
	let RGB,
	let mvTime
	){
	let xAngle = rand_deg;
	let yAngle = rand_deg;
	let zAngle = rand_deg;
	let oX = ObjMove_GetX(objTarget)+offSet[0];
	let oY = ObjMove_GetY(objTarget)+offSet[1];
	ascent(let agCount in 0..wayCount){
		let wayAngle = zAngle+agCount*(360/wayCount);
		SetTrailEffect(xAngle,yAngle,wayAngle);
	}
	loop(mvTime){
		oX = ObjMove_GetX(objTarget)+offSet[0];
		oY = ObjMove_GetY(objTarget)+offSet[1];
		yield;
		if(!ObjEnemy_IsAlive(objBoss)){ return; }
	}
	task SetTrailEffect(let xAngle, let yAngle, let zAngle){
		let sinRate = 90/mvTime;
		let setAlpha = 0;
		ascent(let a in 1..mvTime+1){
			setAlpha += 128/(mvTime/2);
			let sinRadius = GetGapY(256,-256,a*sinRate);
			let rX = oX+sinRadius*(cos(yAngle)*cos(zAngle)-cos(xAngle)*sin(yAngle)*sin(zAngle));
			let rY = oY+sinRadius*(sin(yAngle)*cos(zAngle)+cos(xAngle)*cos(yAngle)*sin(zAngle));
			if(Pos_IsInWideScreen(rX,rY,64)){
				ObjDelay_SetTrailSegment(rX,rY,min(setAlpha,128),15);
			}
			zAngle += 5*(mvTime-a)/mvTime;
			yield;
			if(!ObjEnemy_IsAlive(objBoss)){ return; }
		}
		task ObjDelay_SetTrailSegment(let x, let y, let maxAlpha, let delTime){
			let objMain = ObjDelay_SetPropertiesA2(RGB,blendMode);
		//	let objMain = ObjDelay_SetPropertiesA2(GRAY,BLEND_ADD_ARGB);
			ObjRender_SetPosition(objMain,x,y,0);
		//	ObjRender_SetColorArray(objMain,RGB);
			Obj_SetRenderPriority(objMain,0.49);
			ObjRender_SetAngleXYZ(objMain,0,0,rand_deg);
			descent(let d in 1..delTime+1){
				let decScale = d*0.75/delTime;
				let decAlpha = d*maxAlpha/delTime;
				ObjRender_SetScaleXYZ(objMain,decScale,decScale,0.00);
				ObjRender_SetAlpha(objMain,decAlpha);
				yield;
				if(Obj_IsDeleted(objMain)){ break; }
			}
			Obj_Delete(objMain);
		}
	}
}