function TShotRegular(x, y, v, a, g, d){
	let obj = ObjShot_Create(OBJ_SHOT);
	ObjShot_Regist(obj);
	ObjMove_SetPosition(obj, x, y);
	ObjMove_SetSpeed(obj, v);
	ObjMove_SetAngle(obj, a);
	ObjShot_SetGraphic(obj, g);
	ObjShot_SetDamage(obj, d);
	ObjShot_SetPenetration(obj, 1);

	let obj_Anim = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj_Anim, GetCurrentScriptDirectory ~ "Image/Shot.png");
	Obj_SetRenderPriorityI(obj_Anim, 60);
	AnimateOnRemoval;
	return obj;

	task AnimateOnRemoval{
		let pos = [0, 0];
		while(!Obj_IsDeleted(obj)){
			pos = [ObjRender_GetX(obj), ObjRender_GetY(obj)];
			yield;
		}

		ObjRender_SetPosition(obj_Anim, pos[0], pos[1], 0);
		ObjRender_SetBlendType(obj_Anim, BLEND_ADD_ARGB);
		ObjRender_SetAlpha(obj_Anim, 128);
		ObjRender_SetAngleZ(obj_Anim, rand(-15, 15));
		ObjSprite2D_SetSourceRect(obj_Anim, 0, 0, 16, 32);
		ObjSprite2D_SetDestRect(obj_Anim, -8, -16, 8, 16);

		ascent(i in 0 .. 3){
			ObjSprite2D_SetSourceRect(obj_Anim, 0, 0 + i*32, 16, 32 + i*32);
			ObjSprite2D_SetDestRect(obj_Anim, -8, -16, 8, 16);

			ObjRender_SetAlpha(obj_Anim, 255 - (255/3) * i);
			loop(3){yield;}
		}
		Obj_Delete(obj_Anim);
	}
}

function TShotUnfocus(x, y, v, a, g, d, color, bounce){
	let obj = ObjShot_Create(OBJ_SHOT);
	ObjShot_Regist(obj);
	ObjMove_SetPosition(obj, x, y);
	ObjMove_SetSpeed(obj, v);
	ObjMove_SetAngle(obj, a);
	ObjShot_SetGraphic(obj, g);
	ObjShot_SetDamage(obj, d);
	ObjShot_SetPenetration(obj, 1);
	ObjRender_SetScaleXYZ(obj, 0.5, 1.25, 0);
	ObjRender_SetColor(obj, color[0], color[1], color[2]);

	let obj_Anim = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj_Anim, GetCurrentScriptDirectory ~ "Image/Shot.png");
	Obj_SetRenderPriorityI(obj_Anim, 60);
	AnimateOnRemoval;
	return obj;

	task AnimateOnRemoval{
		let pos = [0, 0];
		let z = a;
		while(!Obj_IsDeleted(obj)){
			pos = [ObjRender_GetX(obj), ObjRender_GetY(obj)];
			z = ObjMove_GetAngle(obj);

			if(bounce){
				if(ObjMove_GetX(obj) < -24 || ObjMove_GetX(obj) > GetStgFrameWidth + 24){ObjMove_SetAngle(obj, -ObjMove_GetAngle(obj) + 180);}
			}
			yield;
		}

		ObjRender_SetPosition(obj_Anim, pos[0], pos[1], 0);
		ObjRender_SetBlendType(obj_Anim, BLEND_ADD_ARGB);
		ObjRender_SetAlpha(obj_Anim, 128);
		ObjRender_SetAngleZ(obj_Anim, z + 90);
		ObjSprite2D_SetSourceRect(obj_Anim, 16, 0, 80, 64);
		ObjSprite2D_SetDestRect(obj_Anim, -32, -32, 32, 32);
		ObjRender_SetScaleXYZ(obj_Anim, 0.5, 1.25, 0);
		ObjRender_SetColor(obj_Anim, color[0], color[1], color[2]);

		ascent(i in 0 .. 3){
			ObjSprite2D_SetSourceRect(obj_Anim, 16, 0 + i*64, 80, 64 + i*64);
			ObjSprite2D_SetDestRect(obj_Anim, -32, -32, 32, 32);

			//ObjRender_SetAlpha(obj_Anim, 255 - (255/3) * i);
			loop(3){yield;}
		}
		Obj_Delete(obj_Anim);
	}
}

task PlayerExplode(path){
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjRender_SetBlendType(obj, BLEND_ADD_ARGB);
	Obj_SetRenderPriority(obj, 0.60);
	ObjPrim_SetTexture(obj, path);
	ObjSprite2D_SetSourceRect(obj, 0, 0, 63, 63);
	ObjSprite2D_SetDestRect(obj, -32, -32, 32, 32);

	let angle = 0;
	angle = 0;
	loop(4){
		NegativeExplodeCircle(GetPlayerX + 64*cos(angle), GetPlayerY + 64*sin(angle), 75);
		angle += 90;
	}
	NegativeExplodeCircle(GetPlayerX, GetPlayerY, 75);
	NegativeExplodeCircle(GetPlayerX, GetPlayerY, 50);

	let alpha = 255;
	let scale = 0;
	loop(30){
		scale += 0.2;
		alpha -= 8;
		ObjRender_SetColor(obj, alpha, alpha, alpha);
		ObjRender_SetPosition(obj, GetPlayerX, GetPlayerY, 0);
		ObjRender_SetScaleXYZ(obj, scale, scale, 1);
		yield;
	}
	Obj_Delete(obj);

	task NegativeExplodeCircle(x, y, speed){
		let obj = ObjPrim_CreateRegularPolygon(x, y, 0, 32, 16);
		ObjRender_SetBlendType(obj, BLEND_INV_DESTRGB);
		Obj_SetRenderPriorityI(obj, 70);

		ObjRender_SetScaleXYZ(obj, 0, 0, 0);

		let s = 0;
		loop(300){
			ObjRender_SetScaleXYZ(obj, s, s, 0);
			s += speed/100;
			yield;
		}
		Obj_Delete(obj);
	}
}

task TMagicCircle {
	let countVertex = 64;
	let listRadius = [];
	loop(countVertex) {
		listRadius = listRadius ~ [0];
	}

	let path = current ~ "Image/Default_Player_MagicCircle.png";
	let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D);
	ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLESTRIP);
	ObjPrim_SetVertexCount(obj, countVertex);
	ObjRender_SetBlendType(obj, BLEND_ADD_ARGB);
	Obj_SetRenderPriority(obj, 0.60);
	ObjPrim_SetTexture(obj, path);
	ascent(iVert in 0..countVertex / 2) {
		let left = iVert * 16;
		let indexVert = iVert * 2;
		ObjPrim_SetVertexUVT(obj, indexVert + 0, left, 0);
		ObjPrim_SetVertexUVT(obj, indexVert + 1, left, 16);		
	}

	let cx = 0;
	let cy = 0;
	let maxRadius = 128;
	let alpha = 0;
	let frame = 0;
	let angleRender = 0;
	let frameInvOld = 0;

	while(true) {
		let frameInv = GetPlayerInvincibilityFrame();

		if(frameInv <= 0) {
			Obj_SetVisible(obj, false);
			frameInvOld = 0;
		}
		else {
			if(frameInvOld == 0) {
				ascent(iVert in 0..countVertex) {
					listRadius[iVert] = 0;
				}
				alpha = 0;
				frame = 0;
			}
			frameInvOld = frameInv;

			let px = GetPlayerX();
			let py = GetPlayerY();

			alpha += 1 / 120;
			alpha = min(alpha, 1);
			angleRender += 360 / countVertex / 2;
			Obj_SetVisible(obj, true);

			frameInv = min(100, frameInv);
			let rRate = frameInv / 100;

			ascent(iVert in 0..countVertex / 2) {
				let indexVert = iVert * 2;
				let angle = 360 / (countVertex / 2 - 1) * iVert;

				let vx1 = listRadius[indexVert] * cos(angle);
				let vy1 = listRadius[indexVert] * sin(angle);
				ObjPrim_SetVertexPosition(obj, indexVert + 0, vx1, vy1, 0);

				let vx2 = listRadius[indexVert+1] * cos(angle);
				let vy2 = listRadius[indexVert+1] * sin(angle);
				ObjPrim_SetVertexPosition(obj, indexVert + 1, vx2, vy2, 0);

				if(frame >= 0) {
					let dr = (maxRadius * rRate - listRadius[indexVert]) / 8;
					listRadius[indexVert] = listRadius[indexVert] + dr;
				}
				if(frame > 10) {
					let rRateIn = rRate - 0.12;
					if(rRateIn < 0){rRateIn=0;}
					let dr= (maxRadius * rRateIn - listRadius[indexVert + 1]) / 16;
					listRadius[indexVert + 1] = listRadius[indexVert + 1] + dr;
				}

			}

			ObjRender_SetColor(obj, 192 * alpha, 192 * alpha, 255 * alpha);
			ObjRender_SetPosition(obj, px, py, 0);
			ObjRender_SetAngleZ(obj, angleRender);

			frame++;
		}

		yield;
	}
}

function GetDist(x1,y1,x2,y2){
	return ((x2-x1)^2+(y2-y1)^2)^0.5;
}

function GetAngle(x1,y1,x2,y2){
	return atan2(y2-y1,x2-x1);
}

task ScreenShakeA1(shaketime, intensity){
	let x = Get2DCameraX;
	let y = Get2DCameraY;
	while(shaketime>0){
		Set2DCameraFocusX(GetStgFrameWidth/2 + rand(-intensity, intensity));
		Set2DCameraFocusY(GetStgFrameHeight/2 + rand(-intensity, intensity));
		shaketime--;
		yield;
	}
	Set2DCameraFocusX(GetStgFrameWidth/2);
	Set2DCameraFocusY(GetStgFrameHeight/2);
	yield;
}

task GrazePiece{
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj, GetCurrentScriptDirectory ~ "Image/graze_eff.png");
	ObjSprite2D_SetSourceRect(obj, 0, 0, 32, 32);
	ObjSprite2D_SetDestCenter(obj);
	ObjRender_SetBlendType(obj, BLEND_ADD_RGB);
	ObjRender_SetScaleXYZ(obj, 0.2, 0.2, 0.2);
	ObjRender_SetPosition(obj, GetPlayerX, GetPlayerY, 0);

	let s = 0.2;
	let a = rand(0, 360);
	let x = GetPlayerX;
	let y = GetPlayerY;
	while(s > 0){
		ObjRender_SetScaleXYZ(obj, s, s, s);
		ObjRender_SetPosition(obj, x, y, 0);
		s -= 0.01;
		x += 10*cos(a);
		y += 10*sin(a);
		yield;
	}
	Obj_Delete(obj);
}

function acceleration(a,b,x) {
	let v = x * x;
	return (b * v) + (a * (1 - v));
}

function deceleration(a,b,x) {
	let v = 1 - (1 - x) * (1 - x);
	return (b * v) + (a * (1 - v));
}

task moveAcceleration(object,x,y,time) {
	let px = ObjRender_GetX(object);
	let py = ObjRender_GetY(object);
	let hash = IntToString(px)~IntToString(py);
	Obj_SetValue(object,"interhash",hash);
	let i = 0;
	while (!Obj_IsDeleted(object) && Obj_GetValue(object,"interhash") == hash && i < time) {
		i++;
		ObjRender_SetPosition(object,acceleration(px,x,i / time),acceleration(py,y,i / time), 0);
		yield;
	}
}

task moveDeceleration(object,x,y,time) {
	let px = ObjRender_GetX(object);
	let py = ObjRender_GetY(object);
	let hash = IntToString(px)~IntToString(py);
	Obj_SetValue(object,"interhash",hash);
	let i = 0;
	while (!Obj_IsDeleted(object) && Obj_GetValue(object,"interhash") == hash && i < time) {
		i++;
		ObjRender_SetPosition(object,deceleration(px,x,i / time),deceleration(py,y,i / time), 0);
		yield;
	}
}

function ObjPrim_CreateRegularPolygon(x, y, z, corn, distToCenter){
	let v_count = corn + 2;

	let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D);
	ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLEFAN);
	ObjPrim_SetTexture(obj, GetCurrentScriptDirectory ~ "Image/Field.png");
	ObjPrim_SetVertexCount(obj, v_count);
	ObjRender_SetPosition(obj, x, y, z);

	ObjPrim_SetVertexPosition(obj, 0, 0, 0, 0);
	ObjPrim_SetVertexUVT(obj, 0, 0, 0);

	let dir = 0;
	ascent(i in 1 .. v_count){
	    ObjPrim_SetVertexPosition(obj, i, distToCenter*cos(dir), distToCenter*sin(dir), 0);

	    ObjPrim_SetVertexUVT(obj, i, 0, 0);

        dir += 360/corn;
	}
	return obj;
}

task SnakeLine(x, y, starta, t, color){
	let pos_arr = GenerateTrack(t);
	let v_count = 4;

	let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D);
	ObjPrim_SetPrimitiveType(obj, PRIMITIVE_LINESTRIP);
	ObjPrim_SetTexture(obj, GetCurrentScriptDirectory ~ "Image/Field.png");
	ObjPrim_SetVertexCount(obj, v_count);
	ObjRender_SetColor(obj, color[0], color[1], color[2]);
	ObjRender_SetBlendType(obj, BLEND_ADD_RGB);
	Obj_SetRenderPriorityI(obj, 75);

	let j = 0;
	loop(t - 4){
		ascent(i in 0 .. v_count){
			ObjPrim_SetVertexPosition(obj, i, pos_arr[j+i][0], pos_arr[j+i][1], 0);
			ObjPrim_SetVertexUVT(obj, i, 0, 0);
		}
		j++;
		loop(2){yield;}
	}
	Obj_Delete(obj);

	function GenerateTrack(tracklength){
		let curr_x = x;
		let curr_y = y;
		let curr_a = starta;

		let new_x = 0;
		let new_y = 0;
		let new_a = 0;

		let dist = rand(16, 48);

		let finalArray = [];
		loop(tracklength){
			dist = rand(16, 48);

			new_a = curr_a + rand(-15, 15);
			new_x = curr_x + dist*cos(new_a);
			new_y = curr_y + dist*sin(new_a);

			finalArray = finalArray ~ [[new_x, new_y]];

			curr_x = new_x;
			curr_y = new_y;
			curr_a = new_a;
		}

		return finalArray;
	}
}

task DarkenTintScreen(x, y, pri, color, t){
	let obj = ObjPrim_CreateRegularPolygon(x, y, 0, 48, 128);
	Obj_SetRenderPriorityI(obj, pri);
	ObjRender_SetColor(obj, color[0], color[1], color[2]);
	ObjRender_SetBlendType(obj, BLEND_SUBTRACT);

	ObjPrim_SetVertexColor(obj, 0, 64, 64, 64);

	ObjRender_SetScaleXYZ(obj, 0, 0, 0);

	let s = 0;
	loop(20){
		ObjRender_SetScaleXYZ(obj, s, s, 0);
		s += 5/20;
		yield;
	}
	loop(t){yield;}
	loop(20){
		ObjRender_SetScaleXYZ(obj, s, s, 0);
		s -= 5/20;
		yield;
	}
	Obj_Delete(obj);
}

task SplashObject(type, x, y, speed, dir, color){ //Based on Ozzy's functions
	let objStar = ObjPrim_Create(OBJ_SPRITE_2D);

	let alpha = 130;
	let spinA = rand(0,180);
	let spinB = rand(0,180);
	// let RED = rand(100,255);
	// let GREEN = rand(100,255);
	// let BLUE = rand(100,255);
	let RED = color[0];
	let GREEN = color[1];
	let BLUE = color[2];
	let scale = 0;
	
	ObjRender_SetBlendType(objStar, BLEND_ADD_ARGB);
	Obj_SetRenderPriorityI(objStar, 45);
	ObjPrim_SetTexture(objStar, type);
	ObjSprite2D_SetSourceRect(objStar, 0, 0, 128, 128);
	ObjSprite2D_SetDestCenter(objStar);
	
	while(!Obj_IsDeleted(objStar)) {
		ObjRender_SetPosition(objStar, x, y, 0);
		ObjRender_SetScaleXYZ(objStar, scale, scale, scale);
		ObjRender_SetAngleXYZ(objStar, 0, 0, spinA);
		ObjRender_SetAlpha(objStar, alpha);
		ObjRender_SetColor(objStar, RED*(alpha/255), GREEN*(alpha/255), BLUE*(alpha/255));
		if(scale < 0.19 && speed > 0){scale += 0.03;}
		if(speed > 1.0){speed -= 0.094;}
		if(speed <= 1.0 && alpha > 0){alpha -= 16; scale -= 0.008;}
		if(alpha <= 0){Obj_Delete(objStar);}
		spinA += rand(1, 2);
		spinB += rand(-1, -2);
		x += speed*cos(dir);
		y += speed*sin(dir);
		yield;
	}
}