function ShotRegular(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];
		let rect = GetShotDataInfoA1(g, TARGET_PLAYER, INFO_RECT);
		let shit = [rect[2] - rect[0], rect[3] - rect[1]];
		let z = a;

		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);
		ObjSprite2D_SetSourceRect(obj_Anim, rect[0], rect[1], rect[2], rect[3]);
		ObjSprite2D_SetDestRect(obj_Anim, -shit[0]/2, -shit[1]/2, shit[0]/2, shit[1]/2);
		ObjRender_SetAngleZ(obj_Anim, z + 90 + rand(-8, 8));

		let scale = 1;
		loop(10){
			ObjRender_SetScaleX(obj_Anim, scale);
			scale -= 1/10;
			loop(2){yield;}
		}
		Obj_Delete(obj_Anim);
	}
}

function TLaser(parent, a, d){
	let obj = ObjShot_Create(OBJ_STRAIGHT_LASER);
	ObjShot_Regist(obj);
	ObjMove_SetPosition(obj, ObjRender_GetX(parent), ObjRender_GetY(parent));
	ObjMove_SetAngle(obj, a);
	ObjShot_SetGraphic(obj, 0);

	let obj_Anim = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj_Anim, GetCurrentScriptDirectory ~ "Image/texts.png");
	Obj_SetRenderPriorityI(obj_Anim, 40);
	ObjRender_SetAngleZ(obj_Anim, a);
	ObjRender_SetScaleY(obj_Anim, 0);
	ObjRender_SetAlpha(obj_Anim, 160);
	HandleLaser;
	return obj;

	task HandleLaser{
		let pos = [0, 0];
		let endPos = [0, 0];
		let c = 0;

		let enememes = [];
		let laserLength = 0;
		while(!Obj_IsDeleted(obj)){
			if(Obj_IsDeleted(parent)){Obj_Delete(obj);}

			if(c < 5){
				ObjRender_SetScaleY(obj_Anim, deceleration(0, 1, c/5));
			}

			laserLength = GetDist(endPos[0], endPos[1], ObjRender_GetX(parent), ObjRender_GetY(parent));

			HitboxBullet;

			ObjMove_SetPosition(obj, ObjRender_GetX(parent), ObjRender_GetY(parent));
			ObjRender_SetPosition(obj_Anim, ObjMove_GetX(obj), ObjMove_GetY(obj), 0);
			ObjSprite2D_SetSourceRect(obj_Anim, 0 - c*12, 0, laserLength - c*12, 32);
			ObjSprite2D_SetDestRect(obj_Anim, 0, -16, laserLength, 16);

			c++;
			yield;
		}

		c = 0;
		loop(5){
			ObjRender_SetScaleY(obj_Anim, deceleration(1, 0, c/5));
			c++;
			yield;
		}
		Obj_Delete(obj_Anim);

		task HitboxBullet{
			let shot = CreateShotA1(ObjRender_GetX(parent), ObjRender_GetY(parent), 0, a, 1, 0);
			ObjShot_SetDamage(shot, d/2);
			ObjShot_SetPenetration(shot, 2);
			Obj_SetVisible(shot, false);

			let shot_Anim = ObjPrim_Create(OBJ_SPRITE_2D);
			ObjPrim_SetTexture(shot_Anim, GetCurrentScriptDirectory ~ "Image/Shot.png");
			ObjSprite2D_SetSourceRect(shot_Anim, 32, 0, 64, 16);
			ObjSprite2D_SetDestCenter(shot_Anim);
			ObjRender_SetBlendType(shot_Anim, BLEND_ADD_ARGB);
			ObjRender_SetAngleZ(shot_Anim, a);
			ObjRender_SetAlpha(shot_Anim, 96);
			Obj_SetVisible(shot_Anim, false);
			Obj_SetRenderPriorityI(shot_Anim, 60);

			let dis = 0;
			while(!Obj_IsDeleted(shot)){
				if(ObjShot_GetPenetration(shot) < 2){
					endPos = [ObjMove_GetX(shot), ObjMove_GetY(shot)];
				}
				if(!Obj_IsInArea(shot, -16, -16, GetStgFrameWidth + 16, GetStgFrameHeight + 48)){
					Obj_Delete(shot_Anim);
					endPos = [ObjMove_GetX(shot), ObjMove_GetY(shot)];
					Obj_Delete(shot);
					return;
				}

				ObjMove_SetPosition(shot, ObjRender_GetX(parent) + dis*cos(a), ObjRender_GetY(parent) + dis*sin(a));
				dis += 20;
				yield;
			}

			ObjRender_SetPosition(shot_Anim, endPos[0], endPos[1], 0);
			Obj_SetVisible(shot_Anim, true);

			ascent(i in 0 .. 11){
				ObjRender_SetScaleXYZ(shot_Anim, linear(2, 4, i/10), linear(2, 0, i/10), 0);
				ObjRender_SetPosition(shot_Anim, endPos[0] + linear(0, 64, i/10)*cos(a), endPos[1] + linear(0, 64, i/10)*sin(a), 0);
				yield;
			}
			Obj_Delete(shot_Anim);
		}
	}
}

task CastFlashBomb{
	Expand(GetPlayerX, GetPlayerY, [255, 0, 255], 5, 10, 180);
}

task Expand(x, y, color, speed, strength, time){
	let vertexcount = 60;
	let innerrad = 0; //inner radius of the circle
	let outerrad = 0; //outer radius of the circle
 
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLESTRIP);
	ObjPrim_SetTexture(obj, GetCurrentScriptDirectory ~ "Image/line.png");
	ObjPrim_SetVertexCount(obj, vertexcount);
	ObjRender_SetBlendType(obj, BLEND_ADD_ARGB);
	ObjRender_SetColor(obj, color[0], color[1], color[2]);
	Obj_SetRenderPriorityI(obj, 30);
    loop(time){
    	let shots = GetShotIdInCircleA2(x, y, outerrad, TARGET_ENEMY);
    	ascent(i in 0 .. length(shots)){
    		let bulpos = [ObjMove_GetX(shots[i]), ObjMove_GetY(shots[i])];
			let bulan = GetAngle(bulpos[0], bulpos[1], x, y);
    		if(GetDist(x, y, ObjMove_GetX(shots[i]), ObjMove_GetY(shots[i])) > innerrad && GetDist(x, y, ObjMove_GetX(shots[i]), ObjMove_GetY(shots[i])) < outerrad){
    			ObjMove_SetPosition(shots[i], bulpos[0] - strength*cos(bulan), bulpos[1] - strength*sin(bulan));
    		}
    	}

    	ascent(i in 0..vertexcount/2){
    		let indexvert = i*2;
    		let angle = i*360/(vertexcount*0.5-1)-270;
    		ObjPrim_SetVertexPosition(obj, indexvert+0, x+innerrad*cos(angle), y+innerrad*sin(angle), 0);
       		ObjPrim_SetVertexPosition(obj, indexvert+1, x+outerrad*cos(angle), y+outerrad*sin(angle), 0);

            ObjPrim_SetVertexUVT(obj, indexvert, 0, 2048/(vertexcount/2-1)*i);
            ObjPrim_SetVertexUVT(obj, indexvert+1, 256, 2048/(vertexcount/2-1)*i);
    	}

        if(outerrad > 128){innerrad += speed;}
        outerrad += speed;
        yield;
    }
    Obj_Delete(obj);
}

task SpellClause{
	SetPlayerInvincibilityFrame(420);
	PlaySoundA1(4, 70, 0);
	DarkenTintScreen(GetPlayerX, GetPlayerY, 35, [0, 96, 0], 300);

	let manage = GetSpellManageObject;
	CanShoot = false;

	PlaySoundA1(10, 70, 0);
	ScreenShakeA1(300, 8);
	GatherEffect(GetPlayerX, GetStgFrameHeight/2, 120);
	GatherShots(GetPlayerX, GetStgFrameHeight/2, 120);
	loop(300){yield;}



	CanShoot = true;
	loop(30){yield;}

	Obj_Delete(manage);

	task GatherEffect(x, y, time){
		let obj = ObjPrim_Create(OBJ_SPRITE_2D);
		Obj_SetRenderPriorityI(obj, 65);
		ObjPrim_SetTexture(obj, GetCurrentScriptDirectory ~ "Image/grav_01.png");
		ObjSprite2D_SetSourceRect(obj, 0, 0, 64, 64);
		ObjSprite2D_SetDestCenter(obj);
		ObjRender_SetScaleXYZ(obj, 10, 10, 0);
		ObjRender_SetAlpha(obj, 0);
		ObjRender_SetPosition(obj, x, y, 0);

		ascent(i in 0 .. time+1){
			ObjRender_SetAlpha(obj, linear(0, 255, i/time));
			ObjRender_SetScaleXYZ(obj, linear(10, 1, i/time), linear(10, 1, i/time), 0);
			yield;
		}
		loop(60){yield;}

		ascent(i in 0 .. 61){
			ObjRender_SetScaleXYZ(obj, linear(1, 0, i/30), linear(1, 0, i/30), 0);
			yield;
		}
		Obj_Delete(obj);
	}

	task GatherShots(x, y, time){
		let shots = [];
		let force = 0;
		let maximumForce = 100;
		loop(time){
			shots = GetShotIdInCircleA1(x, y, 600);
			ascent(i in 0 .. length(shots)){
				let target = shots[i];
				let angle = GetAngle(x, y, ObjMove_GetX(target), ObjMove_GetY(target));
				let dist = GetDist(x, y, ObjMove_GetX(target), ObjMove_GetY(target));
				ObjShot_SetSpellResist(target, true);
				ObjMove_SetPosition(target, ObjMove_GetX(target) - force*(dist/600)*cos(angle), ObjMove_GetY(target) - force*(dist/600)*sin(angle));
				ObjMove_SetSpeed(target, 0);
			}
			force += maximumForce/time;
			yield;
		}

		descent(t in 0 .. 61){
			shots = GetShotIdInCircleA1(x, y, 32);
			DeleteShotAll(TYPE_SHOT, TYPE_ITEM);
			ascent(i in 0 .. length(shots)){
				let target = shots[i];
				let angle = GetAngle(x, y, ObjMove_GetX(target), ObjMove_GetY(target));
				ObjShot_SetSpellResist(target, true);
				ObjMove_SetPosition(target, x, y);
				ObjMove_SetSpeed(target, 0);
				ObjShot_SetDeleteFrame(target, t + 5);
			}
			force += maximumForce/time;
			yield;
		}

		if(length(shots) <= 0){return;}

		PlaySoundA1(11, 70, 0);
		PlaySoundA1(12, 70, 0);

		let count = length(shots);
		let num = count/60;
		let a = GetAngle(GetPlayerX, GetPlayerY, x, y);
		let a_div = 0;
		loop(60){
			DeleteShotAll(TYPE_SHOT, TYPE_ITEM);

			loop(num){
				let obj = ShotRegular(x, y, rand(20, 30), a + rand(-a_div, a_div), 2, damage*8);
				ObjShot_SetPenetration(obj, 1000);
				ObjShot_SetSpellFactor(obj, true);
			}

			a_div += 1.5;
			yield;
		}
	}
}