//---------------------------------------------------------------------------------
// Shot Constants
//---------------------------------------------------------------------------------

// Color Arrays ----------------------------------

let RED		= [255, 32, 32];
let ORANGE	= [255,128, 32];
let YELLOW	= [255,255, 32];
let GREEN	= [ 32,255, 32];
let AQUA	= [ 32,128,255];
let CYAN	= [ 32,255,255];
let BLUE	= [ 32, 32,255];
let PURPLE	= [255, 32,255];
let MAGENTA	= [255, 32,128];
let WHITE 	= [255,255,255];
let GRAY	= [128,128,128];
let BLACK   = [  0,  0,  0];

// Scale Constants -------------------------------

let TINY 	= 0.50;
let SMALL 	= 0.75;
let MEDIUM	= 1.00;
let LARGE	= 1.25;
let HUGE	= 1.50;

// Shot Blend Types ------------------------------

let SHOT_ALPHA	= BLEND_ALPHA;
let SHOT_ARGB	= BLEND_ADD_ARGB;
let SHOT_SUBT	= BLEND_SUBTRACT;

//---------------------------------------------------------------------------------
// Break Retrieval Functions
//---------------------------------------------------------------------------------

function ObjVar_SetSizeValue(let objTarget, let nScale){
	Obj_SetValue(objTarget,"BREAK_SIZE",nScale);
}

function ObjVar_SetColorValue(let objTarget, let RGB){
	Obj_SetValue(objTarget,"BREAK_COLOR",RGB);
}

function ObjVar_GetSizeValue(let objTarget){
	return Obj_GetValueD(objTarget,"BREAK_SIZE",SMALL);
}

function ObjVar_GetColorValue(let objTarget){
	return Obj_GetValueD(objTarget,"BREAK_COLOR",WHITE);
}

function ObjVar_DisableBreak(let objTarget){
	Obj_SetValue(objTarget,"BREAK_FLAG",false);
}

//---------------------------------------------------------------------------------
// Value Initializer
//---------------------------------------------------------------------------------

function ObjVar_InitValueA1(let objTarget, let nScale, let RGB){
	ObjVar_SetSizeValue(objTarget,nScale);
	ObjVar_SetColorValue(objTarget,RGB);
}

function ObjVar_InitValueAuto(let objTarget, let graphID, let RGB){
	let objRect = GetShotDataInfoA1(graphID,TARGET_ENEMY,INFO_RECT);
	let breakScale = (objRect[2]-objRect[0])*(4/128);
	if(breakScale < 1){
		breakScale = TINY;
	}else{
		breakScale = round(breakScale);
		if(breakScale == 1){
			breakScale = SMALL;
		}else if(breakScale == 2){
			breakScale = MEDIUM;
			// Exception 1: Laser Head (Light)
			if(graphID >= 277 && graphID <= 284){
				breakScale = SMALL;
			}
		}else if(breakScale == 4){
			breakScale = LARGE;
		}
	}
	ObjVar_SetSizeValue(objTarget,breakScale);
	ObjVar_SetColorValue(objTarget,RGB);
}

//---------------------------------------------------------------------------------
// Object Effects: Delay
//---------------------------------------------------------------------------------

// Delay Control Tasks --------------------------

task ObjShot_DelayControlA1(let objTarget, let wtTime, let blendMode){
	if(wtTime < 0){
		wtTime = -wtTime;
		ObjShot_FadeDelayA1(objTarget,wtTime);
	}else{
		if(wtTime != 0){
			ObjShot_CloudDelayA1(objTarget,wtTime,blendMode);
			ObjShot_SetDelay(objTarget,wtTime);
		}
		ObjRender_SetScaleXYZ(objTarget,0.50,0.50,0);
	}
}

task ObjShot_DelayControlB1(let objTarget, let wtSpeed, let wtTime, let blendMode){
	if(wtTime < 0){
		wtTime = -wtTime;
		ObjShot_FadeDelayB1(objTarget,wtSpeed,wtTime);
	}else{
		if(wtTime != 0){
			ObjShot_CloudDelayB1(objTarget,wtSpeed,wtTime,blendMode);
			ObjShot_SetDelay(objTarget,wtTime);
		}
		ObjRender_SetScaleXYZ(objTarget,0.50,0.50,0.00);
	}
}


// Standard Delay --------------------------------

task ObjShot_FadeDelayA1(let objTarget, let wtTime){
	let oX = ObjMove_GetX(objTarget);
	let oY = ObjMove_GetY(objTarget);
	let objSpeed = ObjMove_GetSpeed(objTarget);
	ObjShot_SetIntersectionEnable(objTarget,false);
	ascent(let a in 1..wtTime+1){
		let decScale = 0.50+(wtTime-a)*0.50/wtTime;
		let addAlpha = a*255/wtTime;
		ObjMove_SetPosition(objTarget,oX,oY);
		ObjMove_SetSpeed(objTarget,0);
		ObjRender_SetScaleXYZ(objTarget,decScale,decScale,0.00);
		ObjRender_SetAlpha(objTarget,addAlpha);
		yield;
		if(Obj_IsDeleted(objTarget)){ return; }
	}
	ObjMove_SetSpeed(objTarget,objSpeed);
	ObjShot_SetIntersectionEnable(objTarget,true);
	ObjRender_SetScaleXYZ(objTarget,0.50,0.50,0.00);
}

task ObjShot_CloudDelayA1(let objTarget, let wtTime, let blendMode){
	let RGB = ObjVar_GetColorValue(objTarget);
	let objMain = ObjDelay_SetPropertiesA1(RGB,blendMode);
	ObjRender_SetPositionToObj(objMain,objTarget);
	ObjRender_SetAngleXYZ(objMain,0,0,rand_deg);
	
	let maxScale = 1.00;
	let minScale = 0.25;
	if(ObjVar_GetSizeValue(objTarget) == MEDIUM){
		maxScale = 1.25;
		minScale = 0.50;
	}
	ascent(let a in 0..wtTime){
		let decScale = minScale+(wtTime-a)*(maxScale-minScale)/wtTime;
		let addAlpha = 64+a*192/(wtTime-1);
		ObjRender_SetScaleXYZ(objMain,decScale,decScale,0.00);
		ObjRender_SetAlpha(objMain,addAlpha);
		if(Obj_IsDeleted(objTarget)){ break; }
		yield;
	}
	Obj_Delete(objMain);
}

// Advanced Delay --------------------------------

task ObjShot_FadeDelayB1(let objTarget, let wtSpeed, let wtTime){
	let objSpeed = ObjMove_GetSpeed(objTarget);
	ObjMove_SetSpeed(objTarget,wtSpeed);
	ObjShot_SetIntersectionEnable(objTarget,false);
	ascent(let a in 1..wtTime+1){
		let decScale = 0.50+(wtTime-a)*0.50/wtTime;
		let addAlpha = a*255/wtTime;
		ObjRender_SetScaleXYZ(objTarget,decScale,decScale,0.00);
		ObjRender_SetAlpha(objTarget,addAlpha);
		yield;
		if(Obj_IsDeleted(objTarget)){ return; }
	}
	ObjMove_SetSpeed(objTarget,objSpeed);
	ObjShot_SetIntersectionEnable(objTarget,true);
	ObjRender_SetScaleXYZ(objTarget,0.50,0.50,0.00);
}

task ObjShot_CloudDelayB1(let objTarget, let wtSpeed, let wtTime, let blendMode){
	let RGB = ObjVar_GetColorValue(objTarget); 
	let objMain = ObjDelay_SetPropertiesA1(RGB,blendMode);
	ObjRender_SetPositionToObj(objMain,objTarget);
	ObjRender_SetAngleXYZ(objMain,0,0,rand_deg);
	ObjMove_DelayMotion;
	
	let maxScale = 1.00;
	let minScale = 0.25;
	if(ObjVar_GetSizeValue(objTarget) == MEDIUM){
		maxScale = 1.25;
		minScale = 0.50;
	}
	ascent(let a in 0..wtTime){
		let decScale = minScale+(wtTime-a)*(maxScale-minScale)/wtTime;
		let addAlpha = 64+a*192/(wtTime-1);
		ObjRender_SetScaleXYZ(objMain,decScale,decScale,0.00);
		ObjRender_SetAlpha(objMain,addAlpha);
		yield;
		if(Obj_IsDeleted(objTarget)){ break; }
	}
	Obj_Delete(objMain);
	
	task ObjMove_DelayMotion{
		let oX = ObjMove_GetX(objTarget);
		let oY = ObjMove_GetY(objTarget);
		let objAngle = ObjMove_GetAngle(objTarget);
		loop(wtTime){
			ObjMove_SetPosition(objTarget,oX,oY);
			ObjRender_SetPosition(objMain,oX,oY,0);
			oX += wtSpeed*cos(objAngle);
			oY += wtSpeed*sin(objAngle);
			if(Obj_IsDeleted(objMain)){ return; }
			yield;
		}
	}
}

// Laser Source ----------------------------------

task ObjLaser_SourceDelay(let objTarget, let IS_SINUATE, let blendMode){
	let RGB = ObjVar_GetColorValue(objTarget);
	let objMain = ObjDelay_SetPropertiesA1(RGB,blendMode);
	ObjRender_SetPositionToObj(objMain,objTarget);
	ObjRender_SetScaleXYZ(objMain,0.75,0.75,0);
	
	let spTime = truncate(ObjLaser_GetLength(objTarget)/ObjMove_GetSpeed(objTarget));
	if(IS_SINUATE){ spTime = truncate(ObjLaser_GetLength(objTarget)); }
	let setAngle = rand_deg;
	ascent(let a in 0..spTime){
		let sinScale = GetGapY(0.75,0.1,a*45);
		let addAngle = setAngle+a*75;
		ObjRender_SetScaleXYZ(objMain,sinScale,sinScale,0.00);
		ObjRender_SetAngleXYZ(objMain,0,0,addAngle);
		if(Obj_IsDeleted(objTarget)){ break; }
		yield;
	}
	Obj_Delete(objMain);
}

//---------------------------------------------------------------------------------
// Object Effects: Break
//---------------------------------------------------------------------------------

task ObjShot_SetBreakA1(let objTarget, let blendMode){
	let getColor = ObjVar_GetColorValue(objTarget);
	let getScale = ObjVar_GetSizeValue(objTarget);
	let posArray = CalculatePosition;
	if(!posArray){ return; }
	let oX = posArray[0];
	let oY = posArray[1];
	if(Pos_IsInWideScreen(oX,oY,32)){
		alternative(getScale)
		case(TINY){
			ObjEffect_BulletBreakA1(oX,oY,255,getColor,0.60,blendMode);
			ObjEffect_BulletBreakA2(oX,oY,getColor,0.37,blendMode);
		}
		case(SMALL){
			ObjEffect_BulletBreakA1(oX,oY,255,getColor,0.75,blendMode);
			ObjEffect_BulletBreakA2(oX,oY,getColor,0.50,blendMode);
		}
		case(MEDIUM){
			ascent(let a in 0..2){
				let rX = oX+rand(-12,12);
				let rY = oY+rand(-12,12);
				ObjEffect_BulletBreakA1(rX,rY,64+192*a,getColor,1.00,blendMode);
			}
			ObjEffect_BulletBreakA2(oX,oY,getColor,0.75,blendMode);
		}
		case(LARGE){
			ascent(let a in 0..3){
				let rX = oX+rand(-16,16);
				let rY = oY+rand(-16,16);
				ObjEffect_BulletBreakA1(rX,rY,64+96*a,getColor,1.25,blendMode);
			}
			ObjEffect_BulletBreakA2(oX,oY,getColor,1.00,blendMode);
		}
		others{
			ObjEffect_BulletBreakA1(oX,oY,255,getColor,getScale,blendMode);
			ObjEffect_BulletBreakA2(oX,oY,getColor,getScale-0.25,blendMode);
		}
	}
	
	function CalculatePosition{
		let posArray = [];
		while(!Obj_IsDeleted(objTarget)){
			let oX = ObjMove_GetX(objTarget);
			let oY = ObjMove_GetY(objTarget);
			posArray = [oX,oY];
			getColor = ObjVar_GetColorValue(objTarget);
			getScale = ObjVar_GetSizeValue(objTarget);
			if(!Obj_GetValueD(objTarget,"BREAK_FLAG",true)){
				return false;
			}
			yield;
		}
		return posArray;
	}
}

task ObjLaser_SetBreakA1(let objTarget, let blendMode){
	let getColor = ObjVar_GetColorValue(objTarget);
	let getScale = ObjVar_GetSizeValue(objTarget);
	let getAngle = ObjMove_GetAngle(objTarget)-180;
	let posArray = CalculatePosition;
	if(!posArray){ return; }
	local{
		let oX = posArray[0];
		let oY = posArray[1];
		let getLength = posArray[2];
		let numCount = truncate(getLength/16);
		ascent(let a in 1..numCount){
			let addLength = a*(getLength/(numCount-1));
			let rX = GetGapX(oX,addLength,getAngle);
			let rY = GetGapY(oY,addLength,getAngle);
			if(Pos_IsInWideScreen(rX,rY,32)){
				ObjEffect_BulletBreakA2(rX,rY,getColor,getScale-0.25,blendMode);
				if(!modc(a,2)){
					ObjEffect_BulletBreakA1(rX,rY,rand(128,255),getColor,getScale,blendMode);
				}
			}
		}
	}
	
	function CalculatePosition{
		let pX = ObjMove_GetX(objTarget);
		let pY = ObjMove_GetY(objTarget);
		let posArray = [];
		while(!Obj_IsDeleted(objTarget)){
			let oX = ObjMove_GetX(objTarget);
			let oY = ObjMove_GetY(objTarget);
			let objLeng = min(ObjLaser_GetLength(objTarget),GetDistance(pX,pY,oX,oY));
			posArray = [oX,oY,objLeng];
			getColor = ObjVar_GetColorValue(objTarget);
			getScale = ObjVar_GetSizeValue(objTarget);
			if(!Obj_GetValueD(objTarget,"BREAK_FLAG",true)){
				return false;
			}
			yield;
		}
		return posArray;
	}
}

/*
task ObjStLaser_SetBreakA1(let objTarget, let blendMode){
	let nColor = Obj_GetColorValue(objTarget);
	let nScale = Obj_GetSizeValue(objTarget);
	let nAngle = ObjStLaser_GetAngle(objTarget);
	let posArray = CalculatePosition;
	local{
		let oX = posArray[0];
		let oY = posArray[1];
		let nLength = posArray[2];
		let numCount = truncate(nLength/16);
		ascent(let ccCount in 1..numCount){
			let ccLength = ccCount*(nLength/numCount);
			let rX = GetGapX(oX,ccLength,nAngle);
			let rY = GetGapY(oY,ccLength,nAngle);
			if(Pos_IsInBoundaries(rX,rY,32)){
				ObjEffect_BulletBreakA2(oX,oY,nColor,nScale-0.25,blendMode);
				if(!modc(ccCount,2)){
					ObjEffect_BulletBreakA1(oX,oY,nColor,nScale,blendMode);
				}
			}
		}
	}
	
	function CalculatePosition{
		let posArray = [];
		while(!Obj_IsDeleted(objTarget)){
			let oX = ObjMove_GetX(objTarget);
			let oY = ObjMove_GetY(objTarget);
			let objLeng = ObjLaser_GetLength(objTarget);
			let objAngle
			posArray = [oX,oY,objLeng];
			nColor = Obj_GetColorValue(objTarget);
			nScale = Obj_GetSizeValue(objTarget);
			yield;
		}
		return posArray;
	}
}
*/

task ObjCrLaser_SetBreakA1(let objTarget, let blendMode){
	let getColor = ObjVar_GetColorValue(objTarget);
	let getScale = ObjVar_GetSizeValue(objTarget);
	let getSpeed = ObjMove_GetSpeed(objTarget);
	let posArray = CalculatePosition;
	if(!posArray){ return; }
	let aLength = max(1,length(posArray)-1); 
	ascent(let i in 0..aLength){
		let intValue = ceil(16/getSpeed);
		let sX = posArray[i][0];
		let sY = posArray[i][1];
		if(Pos_IsInWideScreen(sX,sY,32)){
			if(!modc(i,intValue)){
				ObjEffect_BulletBreakA2(sX,sY,getColor,getScale-0.25,blendMode);
			}
			if(!modc(i,intValue*2)){
				ObjEffect_BulletBreakA1(sX,sY,rand(128,255),getColor,getScale,blendMode);
			}
		}
	}
	
	function CalculatePosition{
		let posArray = [];
		let ccCount = 0;
		while(!Obj_IsDeleted(objTarget)){
			let pX = ObjMove_GetX(objTarget);
			let pY = ObjMove_GetY(objTarget);
			let pLength = truncate(ObjLaser_GetLength(objTarget)*0.85);
			posArray = concatenate(posArray,[[pX,pY]]);
			if(ccCount > truncate(pLength)){
				posArray = erase(posArray,0);
			}
			getSpeed = ObjMove_GetSpeed(objTarget);
			if(getSpeed == 0){ getSpeed = ObjMove_GetVirtualSpeed(objTarget); }
			ccCount++;
			if(!Obj_GetValueD(objTarget,"BREAK_FLAG",true)){
				return false;
			}
			yield;
		}
		return posArray;
	}
}

//---------------------------------------------------------------------------------
// Primary CreateShot Functions
//---------------------------------------------------------------------------------

// Standard CreateShot ---------------------------

function CreateShotS1(
	let x,
	let y,
	let speed,
	let angle,
	let graph,
	let delay,
	let color,
	){
	let objMain = CreateShotA1(x,y,speed,angle,graph,0);
	ObjVar_InitValueAuto(objMain,graph,color);
	ObjShot_DelayControlA1(objMain,delay,BLEND_ALPHA);
	ObjShot_SetBreakA1(objMain,BLEND_ADD_ARGB);
	return objMain;
}

function CreateShotS2(
	let x,
	let y,
	let speed,
	let angle,
	let accSpeed,
	let maxSpeed,
	let graph,
	let delay,
	let color,
	){
	let objMain = CreateShotA2(x,y,speed,angle,accSpeed,maxSpeed,graph,0);
	ObjVar_InitValueAuto(objMain,graph,color);
	ObjShot_DelayControlA1(objMain,delay,BLEND_ALPHA);
	ObjShot_SetBreakA1(objMain,BLEND_ADD_ARGB);
	return objMain;
}

// Advanced Delay --------------------------------

function CreateShotD1(
	let x,
	let y,
	let speed,
	let wtSpeed,
	let angle,
	let graph,
	let delay,
	let color,
	){
	let objMain = CreateShotA1(x,y,speed,angle,graph,0);
	ObjVar_InitValueAuto(objMain,graph,color);
	ObjShot_DelayControlB1(objMain,wtSpeed,delay,BLEND_ALPHA);
	ObjShot_SetBreakA1(objMain,BLEND_ADD_ARGB);
	return objMain;
}

function CreateShotD2(
	let x,
	let y,
	let speed,
	let wtSpeed,
	let angle,
	let accSpeed,
	let maxSpeed,
	let graph,
	let delay,
	let color,
	){
	let objMain = CreateShotA2(x,y,speed,angle,accSpeed,maxSpeed,graph,0);
	ObjVar_InitValueAuto(objMain,graph,color);
	ObjShot_DelayControlB1(objMain,wtSpeed,delay,BLEND_ALPHA);
	ObjShot_SetBreakA1(objMain,BLEND_ADD_ARGB);
	return objMain;
}

//---------------------------------------------------------------------------------
// Derivative CreateShot Functions
//---------------------------------------------------------------------------------

function RoundShotS1(
	let x,
	let y,
	let wayCount,
	let speed,
	let angle,
	let graph,
	let delay,
	let color,
	){
	let objArray = [];
	ascent(let agCount in 0..wayCount){
		let wayAngle = angle+agCount*(360/wayCount);
		let obj = CreateShotS1(x,y,speed,wayAngle,graph,delay,color);
		objArray = concatenate(objArray,[obj]);
	}
	return objArray;
}

function RoundShotS2(
	let x,
	let y,
	let wayCount,
	let speed,
	let angle,
	let accSpeed,
	let maxSpeed,
	let graph,
	let delay,
	let color,
	){
	let objArray = [];
	ascent(let agCount in 0..wayCount){
		let wayAngle = angle+agCount*(360/wayCount);
		let obj = CreateShotS2(x,y,speed,wayAngle,accSpeed,maxSpeed,graph,delay,color);
		objArray = concatenate(objArray,[obj]);
	}
	return objArray;
}

function WideShotS1(
	let x,
	let y,
	let wayCount,
	let wayWide,
	let speed,
	let angle,
	let graph,
	let delay,
	let color,
	){
	let arcAngle = angle-(wayWide/2);
	let objArray = [];
	ascent(let agCount in 0..wayCount){
		let wayAngle = arcAngle+agCount*(wayWide/(wayCount-1));
		if(wayCount == 1){ wayAngle = angle; }
		let obj = CreateShotS1(x,y,speed,wayAngle,graph,delay,color);
		objArray = concatenate(objArray,[obj]);
	}
	return objArray;
}

function WideShotS2(
	let x,
	let y,
	let wayCount,
	let wayWide,
	let speed,
	let angle,
	let accSpeed,
	let maxSpeed,
	let graph,
	let delay,
	let color,
	){
	let arcAngle = angle-(wayWide/2);
	let objArray = [];
	ascent(let agCount in 0..wayCount){
		let wayAngle = arcAngle+agCount*(wayWide/(wayCount-1));
		if(wayCount == 1){ wayAngle = angle; }
		let obj = CreateShotS2(x,y,speed,wayAngle,accSpeed,maxSpeed,graph,delay,color);
		objArray = concatenate(objArray,[obj]);
	}
	return objArray;
}

function SineShotS1(x,y,speed,angle,amp,freq,wave,graph,delay,color){
	let obj = CreateShotS1(x,y,speed,angle,graph,delay,color);
	
	Obj_SineWave;
	return obj;
	
	task Obj_SineWave{
		wait(absolute(delay));
		let agAmp = amp*freq*pi/(180*speed);
		let tmCount = 0;
		while(!Obj_IsDeleted(obj)){
			let pX = speed*tmCount;
			let pY = amp*sin(freq*tmCount+wave);
			let sX = GetGapX(x,pX,angle)-GetGapY(0,pY,angle);
			let sY = GetGapY(y,pX,angle)+GetGapX(0,pY,angle);
			let sinAngle = angle+atan(agAmp*cos(freq*tmCount+wave));
			ObjMove_SetPosition(obj,sX,sY);
			ObjMove_SetAngle(obj,sinAngle);
			tmCount++;
			yield;
		}
	}
}

function SetGravityShot(
	let sX,
	let sY,
	let baseSpeed,
	let baseAngle,
	let maxSpeed,
	let gravSpeed,
	let gravAngle,
	let graph,
	let delay,
	let color,
	){
	let objMain = CreateShotS1(sX,sY,0,baseAngle,graph,delay,color);
	ObjMove_SetGravityAngle(objMain,gravAngle);
	ObjMove_ManageGravity(objMain);
	return objMain;
	
	task ObjMove_ManageGravity(let objTarget){
		wait(absolute(delay));
		if(Obj_IsDeleted(objTarget)){ return; }
		let xSpeed = baseSpeed*cos(baseAngle);
		let ySpeed = baseSpeed*sin(baseAngle);
		while(!Obj_IsDeleted(objTarget)){
			let xAccel = gravSpeed*cos(ObjMove_GetGravityAngle(objMain));
			let yAccel = gravSpeed*sin(ObjMove_GetGravityAngle(objMain));
			xSpeed += xAccel;
			ySpeed += yAccel;
			let trueSpeed = GetPythagorean(xSpeed,ySpeed,false);
			let trueAngle = atan2(ySpeed,xSpeed);
			/*
			if(trueSpeed > maxSpeed){
				xSpeed -= xAccel;
				ySpeed -= yAccel;
				trueAngle = atan2(ySpeed,xSpeed);
			}
			*/
			ObjMove_SetSpeed(objTarget,min(trueSpeed,maxSpeed));
			ObjMove_SetAngle(objTarget,trueAngle);
			yield;
		}
	}
}

//---------------------------------------------------------------------------------
// Custom Laser Functions
//---------------------------------------------------------------------------------

function SetStraightLaser(
	let x,
	let y,
	let length,
	let width,
	let angle,
	let graph,
	let wtTime,
	let delTime,
	){
	let objMain = CreateStraightLaserA1(x,y,angle,length,width,60*999,graph,wtTime);
	Obj_SetValue(objMain,"IS_STRAIGHT_LASER",true);
	ObjLaser_SetGrazeInvalidFrame(objMain,5);
	ObjLaser_SetInvalidLength(objMain,0,0.1);
	ObjStLaser_SetSource(objMain,false);
	if(delTime > 0){
		ObjStLaser_ReduceDelete(objMain,wtTime+delTime,20);
	}
	ObjStLaser_SetDeleteRoutine(objMain);
	return objMain;
}

function SetLooseLaser(
	let x,
	let y,
	let length,
	let width,
	let speed,
	let angle,
	let mainGraph,
	let headGraph,
	let color
	){
	let objMain = CreateLooseLaserA1(x,y,speed,angle,length,width,mainGraph,0);
	ObjVar_InitValueA1(objMain,MEDIUM,color);
	ObjShot_SetSpellResist(objMain,false);
	if(headGraph != 0){
		ObjLaser_HeadControl(objMain,headGraph);
	}
	ObjLaser_SetGrazeInvalidFrame(objMain,5);
	ObjLaser_SourceDelay(objMain,false,BLEND_ADD_ARGB);
	ObjLaser_SetBreakA1(objMain,BLEND_ADD_ARGB);
	return objMain;
}

function SetCurveLaser(
	let x,
	let y,
	let length,
	let width,
	let speed,
	let angle,
	let mainGraph,
	let headGraph,
	let color
	){
	let objMain = CreateCurveLaserA1(x,y,speed,angle,length,width,mainGraph,0);
	ObjVar_InitValueA1(objMain,MEDIUM,color);
	ObjShot_SetSpellResist(objMain,false);
	if(headGraph != 0){
		ObjLaser_HeadControl(objMain,headGraph);
	}
	ObjLaser_SetGrazeInvalidFrame(objMain,5);
	ObjLaser_SourceDelay(objMain,true,BLEND_ADD_ARGB);
	ObjCrLaser_SetTipDecrement(objMain,0.25);
	ObjCrLaser_SetBreakA1(objMain,BLEND_ADD_ARGB);
	return objMain;
}

function SetSinuateLaser(
	let x,
	let y,
	let size,
	let speed,
	let angle,
	let blend,
	let graph,
	let color,
	){
	let objMain = CreateShotS1(x,y,speed,angle,graph,0,color);
	Obj_SetVisible(objMain,false);
	ObjShot_SetSpellResist(objMain,true);
	ObjShot_SetIntersectionEnable(objMain,false);
	
	ObjLaser_Control;
	return objMain;
	
	task ObjLaser_Control{
		while(!Obj_IsDeleted(objMain)){
			let oX = ObjMove_GetX(objMain);
			let oY = ObjMove_GetY(objMain);
			let objSpeed = ObjMove_GetSpeed(objMain);
			let objAngle = ObjMove_GetAngle(objMain);
			if(Obj_IsInWideScreen(objMain,size)){
				SinuateBaseO1(oX,oY,size*(objSpeed/3),size,objAngle,blend,WHITE,255,graph,45);
			}
			yield;
		}
	}
}

task SinuateBaseO1(
	let sX,
	let sY,
	let initLength,
	let initWidth,
	let setAngle,
	let blendMode,
	let RGB,
	let maxAlpha,
	let graph,
	let delTime
	){
	let objMain = SetStraightLaser(sX,sY,initLength,initWidth,setAngle,graph,0,0);
	ObjRender_SetAlpha(objMain,0);
	ObjRender_SetBlendType(objMain,blendMode);
	ObjRender_SetFadeIn(objMain);
	
	descent(let d in 1..delTime+1){
		let decLength = d*initLength/delTime;
		let decWidth = d*initWidth/delTime;
		ObjLaser_SetLength(objMain,decLength);
		ObjLaser_SetRenderWidth(objMain,decWidth);
		ObjLaser_SetIntersectionWidth(objMain,decWidth*0.75);
		if(decWidth < initWidth/2){
			ObjShot_SetIntersectionEnable(objMain,false);
		}
		yield;
	}
	Obj_Delete(objMain);
	
	task ObjRender_SetFadeIn(let objTarget){
		wait(5);
		ascent(let a in 1..6){
			let addAlpha = a*maxAlpha/5;
			ObjRender_SetAlpha(objMain,addAlpha);
			yield;
		}
	}
}

//---------------------------------------------------------------------------------
// Other Shot Functions
//---------------------------------------------------------------------------------

function SetNuclearShot(
	let x,
	let y,
	let maxRadius,
	let speed,
	let angle,
	let colCount,
	let blendMode,
	let wtTime,
	let delTime
	){
	let objMain = CreateShotA1(x,y,speed,angle,0,0);
	ObjShot_SetSpellResist(objMain,true);
	ObjNuke_CreateEffect(objMain);
	return objMain;
	
	task ObjNuke_CreateEffect(let objTarget){
		let objNuke = ObjNuke_SetProperties(blendMode,colCount);
		let objRadius = 0;
		ascent(let a in 1..wtTime+1){
			objRadius = a*maxRadius/wtTime;
			ObjNuke_SetObjectRadius(objTarget,objRadius);
			ObjShot_SetIntersectionCircleA1(objTarget,objRadius*0.95);
			ObjRender_SetScaleXYZ(objNuke,(objRadius*3)/512,(objRadius*3)/512,0);
			ObjRender_SetPositionToObj(objNuke,objTarget);
			yield;
			if(Obj_IsDeleted(objTarget)){ break; }
		}
		while(!Obj_IsDeleted(objTarget)){
			objRadius = ObjNuke_GetObjectRadius(objTarget);
			ObjRender_SetPositionToObj(objNuke,objTarget);
			ObjShot_SetIntersectionCircleA1(objTarget,objRadius*0.95);
			ObjRender_SetScaleXYZ(objNuke,(objRadius*3)/512,(objRadius*3)/512,0);
			yield;
		}
		descent(let d in 1..delTime+1){
			let decRadius = d*objRadius/delTime;
			let decAlpha = d*255/delTime;
			ObjRender_SetScaleXYZ(objNuke,(decRadius*3)/512,(decRadius*3)/512,0);
			ObjRender_SetAlpha(objNuke,decAlpha);
			yield;
		}
		Obj_Delete(objNuke);
	}
}