task yesColor(me, H, x, y){ObjRender_SetColorHSV(me, H, 51/20*x, 51/20*y);}
//----------------------------------------------------------------------------------------------------
function CShotA1(xcoord, ycoord, speed, angle, graphic, delay){
	let bih = CreateShotA1(xcoord, ycoord, speed, angle, graphic, 0);
	ObjShot_SetIntersectionEnable(bih, false); grow(bih, delay);

	return bih;
}

function CShotA2(xcoord, ycoord, speed, angle, accel, maxspeed, graphic, delay){
	let bih = CreateShotA2(xcoord, ycoord, speed, angle, accel, maxspeed, graphic, 0);
	ObjShot_SetIntersectionEnable(bih, false); grow(bih, delay);

	return bih;
}

task grow(ye, varr){
	let x;
	ascent(i in 0..varr+1){
		if(Obj_IsDeleted(ye)){break;}

		x = i*90/varr;
		ObjRender_SetScaleXYZ(ye, 3 - sin(x)*2, 3 - sin(x)*2, 0); 
		ObjRender_SetAlpha(ye, 125 + sin(x)*130);
		yield;
	}
	
	if(Obj_IsDeleted(ye)){return;}
	ObjShot_SetIntersectionEnable(ye, true);
}

//----------------------------------------------------------------------------------------------------
function CScaledShotA1(xcoord, ycoord, speed, angle, graphic, delay, scale){
	let bih = CreateShotA1(xcoord, ycoord, speed, angle, graphic, 0);
	ObjShot_SetIntersectionEnable(bih, false); 
	growning(bih, delay, graphic, scale);

	return bih;
}
function CScaledShotA2(xcoord, ycoord, speed, angle, accel, maxspeed, graphic, delay, scale){
	let bih = CreateShotA2(xcoord, ycoord, speed, angle, accel, maxspeed, graphic, 0);
	ObjShot_SetIntersectionEnable(bih, false); 
	growning(bih, delay, graphic, scale);

	return bih;
}

task growning(ye, varr, graph, scaled){
	let rate;
	ascent(i in 0..varr+1){
		if(Obj_IsDeleted(ye)){break;}

		rate = Interpolate_Linear(scaled+1.5, scaled, i/varr);
		ObjRender_SetScaleXYZ(ye, rate, rate, 0);
		ObjShot_SetIntersectionScaleXY(ye, rate, rate);

		rate = Interpolate_Linear(255/2, 255, i/varr);
		ObjRender_SetAlpha(ye, rate);
		yield;
	}

	if(Obj_IsDeleted(ye)){return;}
	ObjShot_SetIntersectionEnable(ye, true);
}


//----------------------------------------------------------------------------------------------------
function CreateLLaser(xcoord, ycoord, speed, angle, accel, maxspeed, leng, width, graphic, delay){
	let obj = CreateLooseLaserA1(xcoord, ycoord, speed, angle, leng, width, graphic, delay);
	ObjMove_SetAcceleration(obj, accel);
	ObjMove_SetMaxSpeed(obj, maxspeed);
	ObjCrLaser_SetTipDecrement(obj, false);

	return obj;
}

function CreateCLaser(xcoord, ycoord, speed, angle, accel, maxspeed, leng, width, graphic, delay){
	let obj = CreateCurveLaserA1(xcoord, ycoord, speed, angle, leng, width, graphic, delay);
	ObjMove_SetAcceleration(obj, accel);
	ObjMove_SetMaxSpeed(obj, maxspeed);
	ObjCrLaser_SetTipDecrement(obj, false);

	return obj;
}

function CreateSTLaser(x, y, angle, len, width, graph, del){
	let st = CreateStraightLaserA1(x, y, angle, len, 0, 60*999, graph, 0);
	DLaser(st, width/3, 2); 
	size(st, width, del[0], 5, true);
	size(st, width*2, del[1], 9, false);
	
	return st;
}

function CreateDLaser(x, y, angle, len, width, graph, del){
	let st = CreateStraightLaserA1(x, y, angle, len, 0, 60*999, graph, 0);
	DLaser(st, width, 2); 
	size(st, width*1.5, del, 3, false);
	
	return st;
}

task DLaser(st, wid, n){
	ObjShot_SetIntersectionEnable(st, false); //ObjStLaser_SetSource(st, false);
	ascent(i in 0..wid/n){
		ObjLaser_SetIntersectionWidth(st, i*n);
		ObjLaser_SetRenderWidth(st, i*n - 3);
		yield;
	}
}

task size(st, wid, del, n, grow){
	if(grow){
		wait(del); if(Obj_IsDeleted(st)){return;}
		ObjShot_SetIntersectionEnable(st, true);
		
		ascent(i in 0..wid/n){
			ObjLaser_SetIntersectionWidth(st, i*n);
			ObjLaser_SetRenderWidth(st, i*n - 3);
			yield;
		}
	}
	else{
		wait(del); if(Obj_IsDeleted(st)){return;}
		ObjShot_SetIntersectionEnable(st, false);
		
		descent(i in 0..wid/n){
			ObjLaser_SetIntersectionWidth(st, i*n);
			ObjLaser_SetRenderWidth(st, i*n - 3);
			yield;
		}
		
		Obj_Delete(st);
	}

}

//----------------------------------------------------------------------------------------------------
task snakeu(obj, timer, variant){

	let wvel = variant;
	while(!Obj_IsDeleted(obj)){
		if(Obj_IsDeleted(obj)){break;} 
		ObjMove_SetAngularVelocity(obj, wvel); wvel *= -1;wait(timer);
	}
}

//----------------------------------------------------------------------------------------------------
function CustomCLaser(xcoord, ycoord, speed, angle, graphic, scale, blend){
	let obj = CreateShotA1(xcoord, ycoord, speed, angle, graphic, 0); gyy(obj, graphic, scale, blend);
	return obj;
}

task gyy(obj, graphic, scaler, blend){
	ObjRender_SetAlpha(obj, 0); ObjShot_SetIntersectionEnable(obj, false); ObjShot_SetSpellResist(obj, true);
  while(!Obj_IsDeleted(obj)){let CS = CreateShotA1(getx(obj), gety(obj), 0, geta(obj), graphic, 0); w1(CS, scaler); wait(scaler[3]);}
  task w1(me, scaling){
		ObjShot_SetSpellResist(me, true);
		ObjRender_SetBlendType(me, blend);
		if(Obj_IsDeleted(me)){return;}
		
    let sc = scaling[0]; let o = 90; 
    ascent(i in 0..90){
			if(Obj_IsDeleted(me)){break;}
      ObjRender_SetScaleXYZ(me, sc*sin(o), sc*sin(o), 0);
      ObjShot_SetIntersectionScaleXY(me, sc*sin(o), sc*sin(o));
      o -= scaling[1]; if(o < scaling[2]){o = 0; break;}
      yield;
    }

    Obj_Delete(me);
  }
}

//----------------------------------------------------------------------------------------------------
task AllQED(obj, number, hud_inclusive, bottom_inclusive){
	let lim = [0, 0, 0, 0];
	lim = (hud_inclusive) ? [0, stgw, 0, stgh] : [stx[0], stx[1], sty[0], sty[1]];

	while(number >= 1 && !Obj_IsDeleted(obj)){
		if(getx(obj) <= lim[0] || getx(obj) >= lim[1]){seta(obj, 180-geta(obj)); number--;}
			if(getx(obj) <= lim[0]){setx(obj, lim[0]);}
			else if(getx(obj) >= lim[1]){setx(obj, lim[1]);}

		else if(gety(obj) <= lim[2] || gety(obj) >= lim[3]){seta(obj, -1*geta(obj)); number--;}
			if(gety(obj) <= lim[2]){sety(obj, lim[2]);}
			else if(gety(obj) >= lim[3] && bottom_inclusive){sety(obj, lim[3]);}

		yield;
	}

}

task the_bad(st, start, dl, time){
	if(Obj_IsDeleted(st)){return;}

	let rate;
	ascent(i in 0..time+1){
		rate = Interpolate_Smooth(start, dl, i/time);
		ObjLaser_SetLength(st, rate);
		yield;
	}
}

//----------------------------------------------------------------------------------------------------
function CustomStarLine(xcoord, ycoord, speed, angle, graphic, blend, cake){
	let range = cake[0];
	let info = [cake[1], cake[2], cake[3], cake[4]];
	let obj = CreateShotA1(xcoord, ycoord, speed, angle, 1, 0); sapphire(obj, range, info, graphic, blend);
	return obj;
}

task sapphire(obj, range, info, graph, blendtype){
	ObjRender_SetAlpha(obj, 0); ObjShot_SetIntersectionEnable(obj, false);
	ObjShot_SetSpellResist(obj, true);

	//{
			let B = []; let L; 
			let r;
	//}

	r = geta(obj) + 90;
	ascent(i in 0..2){
		let a = r + 360/2*i;

		B = B ~ [CScaledShotA1(getx(obj) + range*cos(a), gety(obj) + range*sin(a), 0, r-90, graph[0], info[1], info[3])];
		ObjRender_SetBlendType(B[i], blendtype); ObjShot_SetAutoDelete(B[i], false);
		ObjShot_SetSpellResist(B[i], true);
	}
	L = CreateSTLaser(getx(B[0]), gety(B[0]), angtoO(B[0], B[1]), range*2, info[0], graph[1], [info[2], 60*999]);
	ObjShot_SetAutoDelete(L, false); ObjStLaser_SetSource(L, false);

	while(!Obj_IsDeleted(obj)){
		if(Obj_IsDeleted(obj)){break;}

		r = geta(obj) + 90;
		ascent(i in 0..2){
			let a = r + 360/2*i;
			setpos(B[i], getx(obj) + range*cos(a), gety(obj) + range*sin(a));
		}
		setpos(L, getx(B[0]), gety(B[0])); ObjStLaser_SetAngle(L, angtoO(B[0], B[1]));
		yield;
	}

	ascent(i in 0..2){
		if(Obj_IsDeleted(B[i])){continue;}
		Obj_Delete(B[i]);
	}
	size(L, info[0]*2, 1, 12, false);
}

//----------------------------------------------------------------------------------------------------
function CreateLineA1(xcoord, ycoord, speed, angle, graphic, delay, information){
	let Bullets = [];
	let numBullets = information[0];
	let spacing = information[1];

	ascent(i in 0..numBullets){
		Bullets = Bullets ~ [CShotA1(xcoord + spacing*cos(angle)*i, ycoord + spacing*sin(angle)*i, speed, angle, graphic, delay)];
		ObjShot_SetSpellResist(Bullets[i], true);
	}

	return Bullets;
}

//----------------------------------------------------------------------------------------------------
function PolygonShot(x, y, speed, angle, nSides, nBullets, way_angle, graphic, delay, scale, blend){
		
    let bpos_x = [];
    let bpos_y = [];
    ascent(i in 0..nSides){
      let tmp_angle = 360 / nSides * i;
      bpos_x = bpos_x ~ [cos(tmp_angle)];
      bpos_y = bpos_y ~ [sin(tmp_angle)];
    }

		let Bullets = [];
    ascent(i in 0..nSides){
      let from_x = x + bpos_x[i % nSides];
      let from_y = y + bpos_y[i % nSides];
      let to_x = x + bpos_x[(i + way_angle) % nSides];
      let to_y = y + bpos_y[(i + way_angle) % nSides];

      ascent(j in 0..nBullets){
				let tmp = (j + 1) / nBullets;
       	let vx = GetLinePosition(from_x, to_x, tmp);
        let vy = GetLinePosition(from_y, to_y, tmp);
        let dx = vx - x;
	     	let dy = vy - y;
        let va = atan2(dy, dx) + angle;
        let vs = sqrt(dx * dx + dy * dy);

        Bullets = Bullets ~ [CScaledShotA1(x, y, vs * speed, va, graphic, delay, scale)];
      }
		}

		for each(let adore : Bullets){
			Obj_SetValue(adore, "var_speed", getsp(adore)/speed);
			ObjRender_SetBlendType(adore, blend); 
		}

    function GetLinePosition(from_pos, to_pos, pos_t){
      return (from_pos + (to_pos - from_pos) * pos_t);
    }

		return Bullets;
}

task Lerp_SetDestAtFrame(obj, dx, dy, frame){
	let x = getx(obj); let y = gety(obj); let rate = []; let s = 0.1;
	ObjMove_SetAngle(obj, getDotAngle(dx, dy, x, y));
	ascent(i in 0..frame+1){
		s -= 0.1/(frame-1); ObjMove_SetSpeed(obj, s);
		rate = Interpolate_Accelerate([x, y], [dx, dy], i/frame);
		setx(obj, rate[0]);
		sety(obj, rate[1]);
		yield;
	}

	ObjMove_SetSpeed(obj, 0);
}

//----------------------------------------------------------------------------------------------------
function CustomFlowerA1(xcoord, ycoord, speed, angle, graphic, details, blend, hasLines, tangible){
	let numFlowers = details[0];
	let flowerAngle = details[1];
	let spinTech = [details[2], details[3]];
	let range = [details[4], details[5]];
	let scale = details[6];

	let obj = CreateShotA2(xcoord, ycoord, speed, angle, 0, 0, 1, 0); 
	flowering(obj, numFlowers, graphic, flowerAngle, spinTech, range, blend, scale, hasLines, tangible);

	return obj;
}

task flowering(main, numFlowers, graphic, angle, spin, spacing, blend, scal, isLines, hasHitbox){
	ObjRender_SetAlpha(main, 0); ObjShot_SetIntersectionEnable(main, false);
	ObjShot_SetAutoDelete(main, false); ObjShot_SetSpellResist(main, true); 
	if(Obj_IsDeleted(main)){return;}

	let speed = (spin[0] == 1) ? spin[1] : 0; 
	let B = []; let rate; let j = 0; let k = 0;
	let A;
	ascent(i in 0..numFlowers){
		let a = angle + 360/numFlowers*i;

		let aux = CreateShotA1(getx(main), gety(main), 0, a, graphic, 5);
		ObjShot_SetSpellResist(aux, true); ObjShot_SetAutoDelete(aux, false);
		ObjRender_SetBlendType(aux, blend); ObjRender_SetScaleXYZ(aux, scal, scal, 0);
		ObjShot_SetIntersectionScaleXY(aux, scal, scal);

		if(hasHitbox[0] == 0){ObjShot_SetIntersectionEnable(aux, false); ObjRender_SetAlpha(aux, hasHitbox[1]);}
		B = B ~ [aux];
	}

	let auy = spacing[1]; 
	
	if(isLines[0] == 1){sub_visibility(main, numFlowers, angle, speed, spacing, isLines[1]);}
	while(!Obj_IsDeleted(main)){
		if(outofBounds(main, absolute(spacing[0]))){break;}
		
		k = 0;
		for each(let petal : B){
			let a = angle + 360/numFlowers*k; k++;
			rate = Interpolate_Linear(0, spacing[0], j/auy);
			setpos(petal, getx(main) + rate*cos(a), gety(main) + rate*sin(a));
			seta(petal, a);
		}

		angle += speed;
		j++; if(j > auy){j = auy;}
		yield;
	}

	Obj_Delete(main);
	for each(let petal : B){
		if(Obj_IsDeleted(petal)){continue;}
		Obj_Delete(petal);
	}
}

task sub_visibility(main, numFlowers, angle, speed, spacing, alpha){
	let A = ObjPrim_Create(OBJ_PRIMITIVE_2D);
  ObjPrim_SetPrimitiveType(A, PRIMITIVE_LINESTRIP);
  ObjPrim_SetVertexCount(A, numFlowers+1);
	ObjRender_SetAlpha(A, alpha); ObjRender_SetColor(A, 222, 222, 222);

	ascent(i in 0..numFlowers+1){
		let a = angle + 360/numFlowers*i;
		ObjPrim_SetVertexPosition(A, i, spacing[0]*cos(a), spacing[0]*sin(a), 0);
	}

	let auy = spacing[1]; let j = 0; let rate;
	while(!Obj_IsDeleted(main)){
		if(outofBounds(main, absolute(spacing[0]))){break;}

		rate = Interpolate_Linear(0, 1, j/auy);
		ObjRender_SetPosition(A, getx(main), gety(main), 1);
		ObjRender_SetAngleZ(A, angle); ObjRender_SetScaleXYZ(A, rate, rate, 0);

		angle += speed;
		j++; if(j > auy){j = auy;}
		yield;
	}

	Obj_Delete(A);
}

task ifoutofBounds(obj, counter){
	loop{
		if(outofBounds(obj, counter)){break;} yield;
	}
	if(Obj_IsDeleted(obj)){return;}
	Obj_Delete(obj);
}

function outofBounds(obj, counter){
	let x = (getx(obj) > stgw+counter) || (getx(obj) < -counter); 
	let y = (gety(obj) > stgh+counter) || (gety(obj) < -counter);

	return (x || y); 
}

//----------------------------------------------------------------------------------------------------
task shrinkndie(obj, sc, frame){
	let rate;

	ascent(i in 0..frame+1){
		if(Obj_IsDeleted(obj)){break;}
		rate = Interpolate_Linear(sc, 0, i/frame);
		ObjRender_SetScaleXYZ(obj, rate, rate, 0);
		ObjShot_SetIntersectionScaleXY(obj, rate, rate); yield;
	}

	if(Obj_IsDeleted(obj)){return;}
	Obj_Delete(obj);
}

task smellPlayer(obj, timeout, frames){

	real calm = 0, rate;
	wait(timeout);
	loop(frames){
		if(Obj_IsDeleted(obj)){break;}
		rate = NormalizeAngle(geta(obj));

		seta(obj, Interpolate_Smooth(rate, angtoP(obj), calm/10));
		calm++; calm = (calm > 10) ? 10 : calm; 
		yield;
	}
}

//----------------------------------------------------------------------------------------------------
function CustomCLaser2(xcoord, ycoord, speed, angle, graphic, scale, blend, heck){
	let obj = CreateShotA1(xcoord, ycoord, speed, angle[0], graphic, 0); gxy(obj, graphic, scale, blend, angle[1], heck);
	return obj;
}

task gxy(obj, graphic, scaler, blend, angDif, heck){
	ObjRender_SetAlpha(obj, 0); ObjShot_SetIntersectionEnable(obj, false); ObjShot_SetSpellResist(obj, true);
  while(!Obj_IsDeleted(obj)){let CS = CreateShotA1(getx(obj), gety(obj), 0, geta(obj) + angDif, graphic, 0); w1(CS, scaler, heck); wait(scaler[2]);}
  task w1(me, scaling, get){
		ObjRender_SetScaleXYZ(me, scaler[3], scaler[3], 0);
		ObjShot_SetIntersectionScaleXY(me, scaler[3], scaler[3]);
		ObjShot_SetSpellResist(me, true);
		ObjShot_SetIntersectionEnable(me, get);
		ObjRender_SetBlendType(me, blend);
		if(Obj_IsDeleted(me)){return;}
		
    let sc = 255; let o = 90; 
    ascent(i in 0..90){
			if(Obj_IsDeleted(me)){break;}
			ObjRender_SetAlpha(me, sc*sin(o));
      o -= scaling[0]; if(o < scaling[1]){o = 0; break;}
      yield;
    }

    Obj_Delete(me);
  }
}

//----------------------------------------------------------------------------------------------------
function CreateMoveDuoSTLaser(x, y, speed, angle, ang, len, width, graph, del){
	bool pass = (angle == ang[0]);
	let obj = CreateShotA1(x, y, speed, angle, graph[0], 0); ObjShot_SetAutoDelete(obj, false);
	let ar = CreateDuoSTLaser(x, y, ang[0], ang[1], len, width, graph[1], del);
	pin_to(ar[0], obj, [ang[0], -ang[1]], pass); pin_to(ar[1], obj, [ang[0], ang[1]], pass); ifoutofBounds(obj, len);
	
	return obj;
}

function CreateDuoSTLaser(x, y, angle, angleDif, len, width, graph, del){
	let ar = [];

	let st = CreateStraightLaserA1(x, y, angle-angleDif, len, 0, 60*999, graph, 0);
	DLaser(st, width/3, 2); ObjStLaser_SetSource(st, true);
	size(st, width, del[0], 5, true);
	size(st, width*2, del[1], 9, false);
	ar = ar ~ [st];

	st = CreateStraightLaserA1(x, y, angle+angleDif, len, 0, 60*999, graph, 0);
	DLaser(st, width/3, 2); ObjStLaser_SetSource(st, true);
	size(st, width, del[0], 5, true);
	size(st, width*2, del[1], 9, false);
	ar = ar ~ [st];
	
	return ar;
}

task pin_to(obj, pin, angle, pass){

	real feels;
	loop{
		if(Obj_IsDeleted(obj) || Obj_IsDeleted(pin)){break;}
		setpos(obj, getx(pin), gety(pin)); 

		if(pass){feels = geta(pin);}
		else{feels = angle[0];}

		ObjStLaser_SetAngle(obj, feels + angle[1]);
		yield;
	}

	if(!Obj_IsDeleted(pin)){Obj_Delete(pin);}
	if(!Obj_IsDeleted(obj)){Obj_Delete(obj);}
}

//----------------------------------------------------------------------------------------------------
task pulsating(obj, scale, frame){
	let rate; 
	loop{
		if(Obj_IsDeleted(obj)){break;}

		ascent(i in 0..frame+1){
			rate = Interpolate_Linear(scale[0], scale[1], i/frame);

			ObjRender_SetScaleXYZ(obj, rate, rate, 0);
			ObjShot_SetIntersectionScaleXY(obj, rate, rate);
			yield;
		}
		descent(i in 0..frame+1){
			rate = Interpolate_Linear(scale[0], scale[1], i/frame);

			ObjRender_SetScaleXYZ(obj, rate, rate, 0);
			ObjShot_SetIntersectionScaleXY(obj, rate, rate);
			yield;
		}
	}
}

//----------------------------------------------------------------------------------------------------
task alpha_XtoY(obj, x, y, frames){
	wait(frames[0]); let alpha;
	ascent(i in 0..frames[1]){
		alpha = Interpolate_Smooth(x, y, i/(frames[1]-1));
		ObjRender_SetAlpha(obj, alpha);
		yield;
	}
}

//----------------------------------------------------------------------------------------------------
function CAVE_CreateSTLaser(x, y, angle, len, width, graph, del, radiusPlayer){
	let obj = CreateSTLaser(x, y, angle, len, width, graph, del);
	cave(obj, len, radiusPlayer);
	return obj;
}

task cave(obj, len, radius){
	while(!Obj_IsDeleted(obj)){
		let angle = ObjStLaser_GetAngle(obj);
		{
			let lx = getx(obj); let ly = gety(obj);
			let px = GetPlayerX(); let py = GetPlayerY();
				
			let dx = px - lx; let dy = py - ly;
			let vx = cos(angle); let vy = sin(angle);
				
			let lw = dx * vy - dy * vx;
			let ld = dx * vx + dy * vy;
				
			ObjLaser_SetLength(obj, len);
			if (ld > 0) {
				let lh = radius * radius - lw * lw;
				if (lh > 0) {
					let ll = ld - sqrt(lh);
					ObjLaser_SetLength(obj, max(ll, 0));
				}
			}
		}
		yield;
	}
}