let imgEffects=GPSD~"img\effects.png";

function RandDir{
//returns either 1 or -1
	return (prand_int(0,1)-0.5)*2;
}

function IntString(number){
	let str=ToString(number);
	let str2="";
	let i=0;
	while(str[i]!='.'){
		str2=str2~[str[i]];
		i++;
	}
	return str2;
}
function DecimalString(number){
	let str=ToString(number);
	let i=length(str)-1;
	while(str[i]=='0'||str[i]=='.'){
		str=erase(str,i);
		i--;
	}
	return str;
}

function OffScreen(x,y,d){
	let ret=0;
	if(x<GetClipMinX-d||x>GetClipMaxX+d||y<GetClipMinY-d||y>GetClipMaxY+d){ret=1;}
	return ret;
}
function OnScreen(x,y,d){
	return !OffScreen(x,y,d);
}
function power2min(num){
	//returns the smallest power of 2 that is equal or greater than the number given

	let width=2;
	while(num>width){
		width*=2;
	}
	return width;
}
function InitEffect(x,y,texture,vertices,renderstate,layer){
	let obj=Obj_Create(OBJ_EFFECT);
	Obj_SetPosition(obj,x,y);
	ObjEffect_SetTexture(obj,texture);
	ObjEffect_CreateVertex(obj,vertices);
	ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
	ObjEffect_SetRenderState(obj,renderstate);
	ObjEffect_SetLayer(obj,layer);
	return obj;
}
function ObjEffect_SetXYRect(obj,x1,y1,x2,y2){
	ObjEffect_SetVertexXY(obj,0,x1,y1);
	ObjEffect_SetVertexXY(obj,1,x2,y1);
	ObjEffect_SetVertexXY(obj,2,x2,y2);
	ObjEffect_SetVertexXY(obj,3,x1,y2);
}
function ObjEffect_SetUVRect(obj,x1,y1,x2,y2){
	ObjEffect_SetVertexUV(obj,0,x1,y1);
	ObjEffect_SetVertexUV(obj,1,x2,y1);
	ObjEffect_SetVertexUV(obj,2,x2,y2);
	ObjEffect_SetVertexUV(obj,3,x1,y2);
}
function GPSD{
  let current = GetCurrentScriptDirectory;
  current = erase(current, length(current)-1);
  while(current[length(current)-1] != '\'){
    current = erase(current, length(current)-1);
  }
  return current;
}
function GPSDex(num){
  let current = GetCurrentScriptDirectory;
  loop(num){
    current = erase(current, length(current)-1);
    while(current[length(current)-1] != '\'){
      current = erase(current, length(current)-1);
    }
  }
  return current;
}

function Overlay(fade,wait,unfade,alpha,layer,renderstate,rf1,gf1,bf1){
//time to fade in, delay before fading out, time to fade out, max opacity, layer, render state, red, green, blue

	Overlay2(fade,wait,unfade, alpha,layer, renderstate, rf1,gf1,bf1,rf1,gf1,bf1,rf1,gf1,bf1,rf1,gf1,bf1,rf1,gf1,bf1,rf1,gf1,bf1,rf1,gf1,bf1,rf1,gf1,bf1,rf1,gf1,bf1,0,0,0,0,0,0,0,0);
}

task Overlay2(fade,wait,unfade, alpha,layer, renderstate, rf0,gf0,bf0,rf1,gf1,bf1, rf2,gf2,bf2, rf3,gf3,bf3, rf4,gf4,bf4,rf5,gf5,bf5, rf6,gf6,bf6, rf7,gf7,bf7, rf8,gf8,bf8, xoffset,yoffset, xsize,ysize,xspeed,yspeed,angle, angv) {

//time to fade in, delay before fading out, time to fade out, max opacity, layer, render state,
//red, then green, then blue values for the center vertex, then continue for each of the 8 others (TL,TC,TR,ML,MR,BL,BM,BR),
//x offset, y offset, x size, y size, x speed, y speed, angle, rotation


    let obj = Obj_Create(OBJ_EFFECT);
    let timefade=fade;
    let opacity=0;
    let phase=0;
    let phasetimer=0;
    let xc=GetCenterX+xoffset;let yc=GetCenterY+yoffset;
    let speed=500;
    xsize=192+xsize;
    ysize=224+ysize;

    // initial settings    

    Obj_SetPosition   (obj, GetCenterX+xoffset,GetCenterY+yoffset);
    Obj_SetSpeed      (obj, 500);
    Obj_SetAngle(obj, 0);
    ObjEffect_SetTexture(obj,GPSD~"img\white.png");
    ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
    ObjEffect_SetScale(obj,1,1);
    ObjEffect_SetAngle(obj,0,0,angle);
    ObjEffect_SetLayer(obj,layer);
    ObjEffect_CreateVertex(obj,10);
    ObjEffect_SetRenderState(obj,renderstate);

    ObjEffect_SetVertexXY(obj,0,0   ,0);
    ObjEffect_SetVertexXY(obj,1,0   ,-ysize);
    ObjEffect_SetVertexXY(obj,9,0   ,-ysize);
    ObjEffect_SetVertexXY(obj,2,-xsize,-ysize);
    ObjEffect_SetVertexXY(obj,3,-xsize,0);
    ObjEffect_SetVertexXY(obj,4,-xsize,ysize);
    ObjEffect_SetVertexXY(obj,5,0   ,ysize);
    ObjEffect_SetVertexXY(obj,6,xsize ,ysize);
    ObjEffect_SetVertexXY(obj,7,xsize ,0);
    ObjEffect_SetVertexXY(obj,8,xsize ,-ysize);


    loop(10){
	ObjEffect_SetVertexUV(obj, phasetimer, 1, 1);
	phasetimer++;
    }
    phasetimer=0;
    while(! Obj_BeDeleted(obj)) {

	if(0-timefade==unfade){
		Obj_Delete(obj);
	}
	if(phase!=1){
		timefade--;
		if(timefade>=0){
			opacity=alpha-(timefade/fade)*alpha;
		} else {
			if(phase<1){phase++;}
			opacity=alpha-(absolute(timefade)/unfade)*alpha;
		}	
	} else {
		phasetimer++;
		if(phasetimer>=wait){phase++;}
		opacity=alpha;
	}

	if(opacity<0){opacity=0;}
	if(opacity>255){opacity=255;}

	ObjEffect_SetVertexColor(obj,0, opacity ,rf0,gf0,bf0);
	ObjEffect_SetVertexColor(obj,1, opacity ,rf2,gf2,bf2);
	ObjEffect_SetVertexColor(obj,9, opacity ,rf2,gf2,bf2);
	ObjEffect_SetVertexColor(obj,2, opacity ,rf1,gf1,bf1);
	ObjEffect_SetVertexColor(obj,3, opacity ,rf4,gf4,bf4);
	ObjEffect_SetVertexColor(obj,4, opacity ,rf6,gf6,bf6);
	ObjEffect_SetVertexColor(obj,5, opacity ,rf7,gf7,bf7);
	ObjEffect_SetVertexColor(obj,6, opacity ,rf8,gf8,bf8);
	ObjEffect_SetVertexColor(obj,7, opacity ,rf5,gf5,bf5);
	ObjEffect_SetVertexColor(obj,8, opacity ,rf3,gf3,bf3);


	angle+=angv;
	ObjEffect_SetAngle(obj,0,0,angle);

	if(OnBomb==true){speed=0;}else{speed=500;}
	Obj_SetSpeed(obj,speed);
	xc+=xspeed;yc+=yspeed;
	Obj_SetPosition(obj,xc-speed,yc);
        yield;
    }
    Obj_Delete(obj);
}

function IsAWCPlayer{
	return GetPlayerScriptName=="awcplayer.txt";
}
function SetPlayer(num){
	SetCommonData("AWCPlayerNum",num);
}
function GetPlayer{
	return trunc(GetCommonDataDefault("AWCPlayerNum",-1));
}
function GetPlayerEx{
	return GetCommonDataDefault("AWCPlayerNum",-1);
}
function ExPlayer{
	return GetPlayerEx!=GetPlayer;
}
function GetPlayerStrU{
	if(IsAWCPlayer){
		return ["Lymia","Raibys","Nhimor","","","","Ender"][GetPlayer];
	}else{
		let string=GetPlayerScriptName;
		string[0]=ToUpper(string[0]);
		let k=0;
		let starterasing=false;
		loop(length(string)){
			if(string[k]=='.'||starterasing){
				string=erase(string,k);
				starterasing=true;
			}else{k++;}
		}
		return string;
	}
}
function GetPlayerStrL{
	return ["","lymia","raibys","nhimor","","","","ender"][GetPlayer+1];
}
function SE(str){
	PlaySE(GPSD~"se\"~str~".wav");
}
function SSE(str){
	StopSE(GPSD~"se\"~str~".wav");
}
function distance(x1,y1,x2,y2){
//returns the distance between two points (squared)
	let dy = (y2-y1);
	let dx = (x2-x1);
	return dx*dx+dy*dy;
}
function GetOption(num){
	return GetCommonDataDefault("OptionsMenu",[2,0,0,0,0,0,0.5])[num];
}
function Detail(high,med,low){
	if(GetOption(4)==0){return high;}
	if(GetOption(4)==1){return med;}
	return low;
}
function WaitEventStep(step){
	while(EventStep<step&&EventActive){
		yield;
	}
}


function LineToLinePoint(let x1, let y1, let x2, let y2, let x3, let y3, let x4, let y4){
//thanks Naut
   let point = [0, 0];
   point[0] = ( ((x1*y2 - y1*x2)*(x3 - x4) - (x1 - x2)*(x3*y4 - y3*x4)) / ((x1 - x2)*(y3 - y4) - (y1 - y2)*(x3 - x4)) );
   point[1] = ( ((x1*y2 - y1*x2)*(y3 - y4) - (y1 - y2)*(x3*y4 - y3*x4)) / ((x1 - x2)*(y3 - y4) - (y1 - y2)*(x3 - x4)) );
   return point;
}
function GetSign(num){
	if(num<0){return -1;}
	else{return 1;}
}

function YOnLineFromX(x1, y1, x2, y2, x3, default){
//Gets the y-coordinate of the point that has an x-coordinate of x3 and that is on the line defined by the points (x1, y1) and (x2, y2). Returns y2 if x1 is equal to x2.
//by Blargel
  let a_numerator = y2-y1;
  let a_denominator = x2-x1;
  if(a_denominator==0){
    return default;
  }
  else {
    let a = a_numerator/a_denominator;
    let xDist = x3-x2;
    let yDist = xDist*a;
    let y3 = y2+yDist;
    return y3;
  }
}

function XOnLineFromY(x1, y1, x2, y2, y3, default){
//Gets the x-coordinate of the point that has a y-coordinate of y3 and that is on the line defined by the points (x1, y1) and (x2, y2). Returns x2 if y1 is equal to y2.
//by Blargel
  let a_numerator = y2-y1;
  let a_denominator = x2-x1;
  if(a_numerator==0){
    return default;
  }
  else {
    let a = a_numerator/a_denominator;
    let yDist = y3-y2;
    let xDist = yDist/a;
    let x3 = x2+xDist;
    return x3;
  }
}

task ClearBullets(alpha,time){
	DeleteEnemyShotImmediatelyInCircle(ALL,GetCenterX,GetCenterY,600);
	let obj=InitEffect(0,0,GPSD~"img\white.png",4,ADD,1);
	ObjEffect_SetXYRect(obj,GetClipMinX,GetClipMinY,GetClipMaxX,GetClipMaxY);
	ObjEffect_SetUVRect(obj,0,0,2,2);
	let alphaadd=alpha/time;
	loop(time){
		Obj_SetColor(obj,4,alpha,255,255,255);
		alpha-=alphaadd;
		yield;
	}
	Obj_Delete(obj);
	
}
task MovingLine(x,y,a,length,time,repetitions){
	length/=30;
	let obj=InitEffect(x,y,imgEffects,4,ADD,2);
	ObjEffect_SetAngle(obj,0,0,a+90);
	ObjEffect_SetScale(obj,1,length);
	let textureoffset=0;
	let textureadd=30/time;
	loop(time){
		ObjEffect_SetXYRect(obj,-2,-textureoffset,3,0);
		ObjEffect_SetUVRect(obj,193,66,198,66+textureoffset);
		textureoffset+=textureadd;
		yield;
	}
	ObjEffect_SetXYRect(obj,-2,-30,3,0);
	repetitions--;
	loop(time*repetitions){
		ObjEffect_SetUVRect(obj,193,66+textureoffset%30,198,96+textureoffset%30);
		textureoffset+=textureadd;
		yield;
	}
	textureoffset=0;
	loop(time){
		ObjEffect_SetXYRect(obj,-2,-30,3,-textureoffset);
		ObjEffect_SetUVRect(obj,193,66+textureoffset,198,95);
		textureoffset+=textureadd;
		yield;
	}
	Obj_Delete(obj);
}
task Arrow(x,y,a,size,time,repetitions){
	MovingLine(x-cos(a)*size,y-sin(a)*size,a,size*2-2,time,repetitions);
	MovingLine(x+cos(a)*size-cos(a+30)*size,y+sin(a)*size-sin(a+30)*size,a+30,size-3,time,repetitions);
	MovingLine(x+cos(a)*size-cos(a-30)*size,y+sin(a)*size-sin(a-30)*size,a-30,size-3,time,repetitions);
}
task StageTitle(delay,x,y,num,angle){
	Wait(delay);
	loop(5){
		StageTitleGlow(x,y,num,angle);
	}
	Wait(310);
	DeleteGraphic(GPSD~"img\stage.png");
}

task StageTitleGlow(x,y,num,angle){
	num--;
	let numv=26;
	let width=15;	//width of object segment
	let width2=128;	//width of graphic
	let obj=InitEffect(x,y,GPSD~"img\stage.png",numv,ALPHA,7);
	ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLESTRIP);
	ObjEffect_SetAngle(obj,0,0,angle);
	let k=0;
	let i=0;
	loop(numv/2){
		ObjEffect_SetVertexUV(obj,k  ,i,0+32*num);
		ObjEffect_SetVertexUV(obj,k+1,i,32+32*num);
		k+=2;
		i+=width2/(numv/2);
	}
	let x;
	let frame=rand_int(0,1000);
	let xfreq=[rand(2,6),rand(2,6)];
	let yfreq=[rand(2,7),rand(2,7)];
	let xsize=[rand(10,25)*5,rand(10,25)*5];
	let ysize=[rand(10,25)*5,rand(10,25)*5];
	let wavelength=[rand(15,25),rand(15,25)];

	let xoffset;
	let yoffset;
	i=0;

	let alpha=0;
	let size=1;
	HandleSizeAlpha;

	loop(300){
		Obj_SetColor(obj,numv,alpha,255,255,255);
		k=0;
		x=-((numv/2)-1)/2;
		loop(numv/2){
			xoffset=0;
			yoffset=0;
			i=0;
			loop(2){
				xoffset+=cos(frame*xfreq[i]+k*wavelength[i])*xsize[i]*0.5;
				yoffset+=sin(frame*yfreq[i]+k*wavelength[i])*ysize[i]*0.5;
				i++;
			}
			ObjEffect_SetVertexXY(obj,k  ,x*width+xoffset*size,-16+yoffset*size);
			ObjEffect_SetVertexXY(obj,k+1,x*width+xoffset*size, 16+yoffset*size);

			x++;
			k+=2;
		}
		frame++;
		yield;
	}
	Obj_Delete(obj);


	task HandleSizeAlpha{
		let alphaadd=255/100;
		let frame=0;
		loop(100){
			alpha+=alphaadd;
			size=-cos((100-frame)*(90/100))+1.03;
			frame++;
			yield;
		}
		loop(100){

			yield;
		}
		frame=0;
		loop(100){
			alpha-=alphaadd;
			size=-cos((frame)*(90/100))+1.03;
			frame++;
			yield;
		}
	}

}

task TackleNhimor{
	let obj=InitEffect(0,0,GPSD~"img\yukaristuff.png",4,ALPHA,5);
	ObjEffect_SetXYRect(obj,-45,-42,45,42);
	ObjEffect_SetUVRect(obj,74,124,164,210);
	ObjEffect_SetScale(obj,1,1);

	let x=GetPlayerX+300;
	let y=GetPlayerY-300;
	let xv=-10;
	let yv=10;
	let frame=0;
	let i=0;
	let playerx=GetPlayerX;
	let playery=GetPlayerY;
	loop(90){
		x+=xv;
		y+=yv;
		Obj_SetPosition(obj,x,y);
		if(frame%4==0){
			i=0;
			while(GetCommonDataDefault("Exps"~IntString(i),0)>0&&i<50){
				i++;
			}
			SetCommonData("Expx"~IntString(i),x);SetCommonData("Expy"~IntString(i),y);SetCommonData("Exps"~IntString(i),1);SetCommonData("Expe"~IntString(i),0.6);SetCommonData("Expc"~IntString(i),[55,155,255]);SetCommonData("Expt"~IntString(i),0);SetCommonData("Expf"~IntString(i),10);SetCommonData("Expst"~IntString(i),0);	
			RanGhost1(x,y,frame);
		}
		frame++;
		SetPlayerX(playerx);
		SetPlayerY(playery);
		if(frame==30){
			SetCommonData("FakeDeath",1);
		}
		if(frame>30){
			SetPlayerY(600);
		}
		ObjEffect_SetAngle(obj,0,0,-frame*15.6);
		yield;
	}
	Obj_Delete(obj);
	loop{
		SetPlayerY(800);
		yield;
	}
}
task RanGhost1(x,y,startframe){
	let obj=InitEffect(0,0,GPSD~"img\yukaristuff.png",4,ALPHA,4);
	ObjEffect_SetAngle(obj,0,0,-startframe*15.6);
	ObjEffect_SetXYRect(obj,-45,-42,45,42);
	ObjEffect_SetUVRect(obj,74,124,164,210);
	ObjEffect_SetScale(obj,1,1);
	Obj_SetPosition(obj,x,y);
	let alpha=250;
	let alphaadd=250/70;
	let color=220;
	let coloradd=220/70;
	loop(70){
		Obj_SetColor(obj,4,alpha,color,color,255);
		alpha-=alphaadd;
		color-=coloradd;
		yield;
	}
	Obj_Delete(obj);
}

function GetTimesPlayed(char,stage,diff){
	return GetCommonDataDefault("PLAYED-"~IntString(char)~"-"~IntString(stage)~"-"~IntString(diff),0);
}
function IncTimesPlayed(char,stage,diff){
	if(!IsReplay){
		SetCommonData("PLAYED-"~IntString(char)~"-"~IntString(stage)~"-"~IntString(diff),GetTimesPlayed(char,stage,diff)+1);
		SaveCommonData;
	}
}

task DeleteAllEnemyInstant{
	SetCommonData("NoEndingFunction",true);
	DeleteAllEnemyWithoutBoss;
	DeleteEnemyShotImmediatelyInCircle(ALL,GetCenterX,GetCenterY,1000);
	yield;
	DeleteCommonData("NoEndingFunction");
}

function GetLineBorderPoint(px, py, tx, ty){
//given 2 points, returns the point of intersection with the screen border of the resulting ray
   let ta = atan2(ty-py, tx-px);

   if( ta>= atan2(GetClipMinY - py, GetClipMinX - px) && ta<=  atan2(GetClipMinY - py, GetClipMaxX - px)){
      return [1, px - (GetClipMinY-py)*tan(ta+90), GetClipMinY];
   }
   if( ta>= atan2(GetClipMinY - py, GetClipMaxX - px) && ta<=  atan2(GetClipMaxY - py, GetClipMaxX - px)){
      return [2, GetClipMaxX, py + (GetClipMaxX-px)*tan(ta)];
   }
   if( ta>= atan2(GetClipMaxY - py, GetClipMaxX - px) && ta<=  atan2(GetClipMaxY - py, GetClipMinX - px)){
      return [3, px - (GetClipMaxY-py)*tan(ta-90), GetClipMaxY];
   }
   if( ta> atan2(GetClipMaxY - py, GetClipMinX - px) || ta<  atan2(GetClipMinY - py, GetClipMinX - px)){
      return [0, GetClipMinX, py + (GetClipMinX-px)*tan(ta+180)];
   }
}
function GetLineBorderPointEX(px, py, tx, ty,threshold){
//same as above, but "threshold" pixels away from the border instead
   let ta = atan2(ty-py, tx-px);

   if( ta>= atan2((GetClipMinY-threshold) - py, (GetClipMinX-threshold) - px) && ta<=  atan2((GetClipMinY-threshold) - py, (GetClipMaxX+threshold) - px)){
      return [1, px - ((GetClipMinY-threshold)-py)*tan(ta+90), (GetClipMinY-threshold)];
   }
   if( ta>= atan2((GetClipMinY-threshold) - py, (GetClipMaxX+threshold) - px) && ta<=  atan2((GetClipMaxY+threshold) - py, (GetClipMaxX+threshold) - px)){
      return [2, (GetClipMaxX+threshold), py + ((GetClipMaxX+threshold)-px)*tan(ta)];
   }
   if( ta>= atan2((GetClipMaxY+threshold) - py, (GetClipMaxX+threshold) - px) && ta<=  atan2((GetClipMaxY+threshold) - py, (GetClipMinX-threshold) - px)){
      return [3, px - ((GetClipMaxY+threshold)-py)*tan(ta-90), (GetClipMaxY+threshold)];
   }
   if( ta> atan2((GetClipMaxY+threshold) - py, (GetClipMinX-threshold) - px) || ta<  atan2((GetClipMinY-threshold) - py, (GetClipMinX-threshold) - px)){
      return [0, (GetClipMinX-threshold), py + ((GetClipMinX-threshold)-px)*tan(ta+180)];
   }
}

function GetPointToLine(ox, oy, p1x, p1y, p2x, p2y){
	//code by Iryan
      let anorm=atan2(p1y-p2y, p1x-p2x)-90;
      let n1=cos(anorm);
      let n2=sin(anorm);

      let dist= ( (ox-p1x)*cos(anorm)+(oy-p1y)*sin(anorm) )/(( (n1)^2 + (n2)^2 )^0.5) ;

      return dist;
}
function GetPointToLineSegment(ox, oy, p1x, p1y, p2x, p2y){
	//code by Iryan
      let distance;

      let va=atan2(p1y-p2y, p1x-p2x);
      let vx=cos(va);
      let vy=sin(va);

      let anorm=va-90;
      let n1=cos(anorm);
      let n2=sin(anorm);

      let b= ( (oy-p1y-ox*vy/vx+p1x*vy/vx)/(n2-n1*vy/vx) );
      let a= ( (ox-p1x-n1*b)/vx  );

      if( a<0){
         let b= ( (oy-p2y-ox*vy/vx+p2x*vy/vx)/(n2-n1*vy/vx) );
         let a= ( (ox-p2x-n1*b)/vx  );
         if(a>0){ distance=( (ox-p1x)*cos(anorm)+(oy-p1y)*sin(anorm) )/(( (n1)^2 + (n2)^2 )^0.5);
         } else{
            distance=( (ox-p2x)^2 + (oy-p2y)^2 )^0.5;
         }
      } else{
         distance=( (ox-p1x)^2 + (oy-p1y)^2 )^0.5;

      }
      distance=(|distance|);
      return distance;
 }

function NormalizeAngle(angle){
  angle %= 360;
  if(angle<0){ angle += 360; }
  return angle;
}

function AngularDistance(angle1, angle2){
  let distance = NormalizeAngle(angle2 - angle1);
  if(distance>180){ distance-=360; }
  return distance;
}
function EnemyX2{
	return GetCommonDataDefault("EnemyX2",0);
}
function EnemyY2{
	return GetCommonDataDefault("EnemyY2",0);
}
function ManualEnemyMarker(value){
	if(value==true){
		SetCommonData("ManualEnemyMarker",true);
	}else{
		DeleteCommonData("ManualEnemyMarker");
	}
}
function SetEnemyMarkerManual(id,x,alpha){
	SetCommonData("CreateEnemyMarker"~IntString(id),[x,alpha]);
}
task FadeEnemyMarker(x,time){
	let alpha=1;
	ManualEnemyMarker(true);
	SetEnemyMarkerManual(1,-200,0);
	loop(time){
		alpha-=1/time;
		SetEnemyMarkerManual(0,x,alpha);
		yield;
	}

}
task FadeEnemyMarkerEX(x,time,alpha1,alpha2){
	ManualEnemyMarker(true);
	SetEnemyMarkerManual(1,-200,0);
	loop(time){
		alpha1+=(alpha2-alpha1)/time;
		SetEnemyMarkerManual(0,x,alpha1);
		yield;
	}

}
sub NoEnemyMarker{
	ManualEnemyMarker(true);
	SetEnemyMarkerManual(0,-200,0);
	SetEnemyMarkerManual(1,-200,0);
}
task ShakeScreenEX(intensity,time1,time2,time3){
	let frame=prand_int(0,4800);
	let intensityadd=intensity/time1;
	intensity=0;
	loop(time1){
		SetCommonData("ScreenShakeX",sin(frame*55)*intensity*0.65);
		SetCommonData("ScreenShakeY",sin(frame*80)*intensity);
		intensity+=intensityadd;
		yield;
		frame++;
	}
	loop(time2){
		SetCommonData("ScreenShakeX",sin(frame*55)*intensity*0.65);
		SetCommonData("ScreenShakeY",sin(frame*80)*intensity);
		yield;
		frame++;
	}
	let intensityadd=intensity/time3;
	loop(time3){
		SetCommonData("ScreenShakeX",sin(frame*55)*intensity*0.65);
		SetCommonData("ScreenShakeY",sin(frame*80)*intensity);
		intensity-=intensityadd;
		yield;
		frame++;
	}
	DeleteCommonData("ScreenShakeX");
	DeleteCommonData("ScreenShakeY");
}


function CollisionLineLine(x1,y1,x2,y2,x3,y3,x4,y4){
	let n1=((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4)); //AAAAAAHHHH
	let d1=((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4));
	let n2=((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4));
	let d2=((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4));
	if(d1==0){d1=0.0001;}	//prevent the universe from exploding
	if(d2==0){d2=0.0001;}
	return [n1/d1,n2/d2];
}
function CollisionLineLineSegment(x1,y1,x2,y2,x3,y3,x4,y4){
	//1 and 2 are the line, 3 and 4 are the line segment
	let point=CollisionLineLine(x1,y1,x2,y2,x3,y3,x4,y4);
	if(
	((point[0]<x3&&point[0]>x4)||(point[0]<x4&&point[0]>x3)) &&
	((point[1]<y3&&point[1]>y4)||(point[1]<y4&&point[1]>y3)) ){
		return point;
	}else{
		return [NULL,NULL];
	}
}
function LineInBox(x1,y1,x2,y2,x3,y3,x4,y4){
	if(x1==x2&&y1==y2){
		if(x1>=x3&&x1<=x4&&y1>=y3&&y1<=y4){
			return true;
		}
	}

	//1 and 2 are coordinates of the line, 3 and 4 are the top-left and bottom-right of the box
	let temp;
	temp=XOnLineFromY(x1,y1,x2,y2, y3, x3-1);
	if(temp>=x3&&temp<=x4){return true;}
	temp=XOnLineFromY(x1,y1,x2,y2, y4, x3-1);
	if(temp>=x3&&temp<=x4){return true;}

	temp=YOnLineFromX(x1,y1,x2,y2, x3, y3-1);
	if(temp>=y3&&temp<=y4){return true;}
	temp=YOnLineFromX(x1,y1,x2,y2, x4, y3-1);
	if(temp>=y3&&temp<=y4){return true;}
	return false;

}
function GetPointInRectangle(ox, oy, pcx, pcy, recl, recw, align){
//by Iryan

      let dist1;
      let dist2;
      let isit=false;

      dist1=(| GetPointToLine(ox, oy, pcx, pcy, pcx+cos(align), pcy+sin(align)) |);
      dist2=(| GetPointToLine(ox, oy, pcx, pcy, pcx+cos(align+90), pcy+sin(align+90)) |);

      if( (dist1<0.5*recw)&&(dist2<0.5*recl) ){ isit=true; }

      return(isit);
}
function FormatNum(num){
	let string=IntString(num);
	let len=length(string);
	let len2=len;
	while(len2>3){
		string=string[0..len2-3]~","~string[len2-3..len];
		len=length(string);
		len2-=3;
	}
	return string;
}
task FadeInObj(obj,maxalpha,time){
	let alpha=0;
	loop(time){
		alpha+=maxalpha/time;
		Obj_SetAlpha(obj,alpha);
		yield;
	}
	Obj_SetAlpha(obj,maxalpha);
}