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 ShotHome(x, y, v, a, g, d, homespeed, homeEnd){
	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;

		let minDis = 10000;
		let enem = [x + 500*cos(a), y + 500*sin(a), minDis];
		let speed = v;

		let c = 0;
		while(!Obj_IsDeleted(obj)){
			pos = [ObjRender_GetX(obj), ObjRender_GetY(obj)];

			let ar = GetIntersectionRegistedEnemyID;
			if(length(ar) > 0 && (c < homeEnd || homeEnd < 0)){
				ascent(i in 0..(length(ar))){
					let dis = GetDist(pos[0], ObjMove_GetX(obj), pos[1], ObjMove_GetY(ar[i]));
					if(dis<enem[2]){
						enem[2] = dis;
						enem[0] = ObjMove_GetX(ar[i]);
						enem[1] = ObjMove_GetY(ar[i]);
					}
				}

				let dir = NormalizeAngle(atan2(enem[1] - pos[1], enem[0] - pos[0]));

				TurnToAngle(obj, homespeed, dir);
			}

			z = ObjMove_GetAngle(obj);

			c++;
			yield;
		}
		if(!Point_IsInArea(pos, -8, -8, GetStgFrameWidth + 8, GetStgFrameHeight + 8)){Obj_Delete(obj_Anim); return;}

		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;
		let alpha = 255;
		loop(10){
			ObjRender_SetScaleXYZ(obj_Anim, scale, scale, 0);
			ObjRender_SetAlpha(obj_Anim, alpha);
			scale += 1/10;
			alpha -= 255/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);
	ObjShot_SetAutoDelete(obj, false);

	let obj_Anim = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj_Anim, GetCurrentScriptDirectory ~ "Image/Shot.png");
	Obj_SetRenderPriorityI(obj_Anim, 40);
	ObjRender_SetAngleZ(obj_Anim, a);
	ObjRender_SetScaleY(obj_Anim, 0);
	ObjRender_SetAlpha(obj_Anim, 96);
	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);}

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

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

			if(c % 3 == 0){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*10, 112, laserLength - c*10, 128);
			ObjSprite2D_SetDestRect(obj_Anim, 0, -8, laserLength, 8);

			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);
			ObjShot_SetPenetration(shot, 2);
			Obj_SetVisible(shot, false);
			ObjShot_SetAutoDelete(shot, false);

			let shot_Anim = ObjPrim_Create(OBJ_SPRITE_2D);
			ObjPrim_SetTexture(shot_Anim, GetCurrentScriptDirectory ~ "Image/Shot.png");
			ObjSprite2D_SetSourceRect(shot_Anim, 224, 80, 256, 112);
			ObjSprite2D_SetDestCenter(shot_Anim);
			ObjRender_SetBlendType(shot_Anim, BLEND_ALPHA);
			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 + 64)){
					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(1, 3, i/10), linear(0.75, 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{
	FlashRectangle(GetPlayerX, GetPlayerY, GetPlayerX, GetPlayerY - 600, 256, 20);

	function FlashRectangle(x, y, destX, destY, width, t){
		let beamAngle = GetAngle(x, y, destX, destY);

		let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D);
		ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLESTRIP);
		Obj_SetRenderPriorityI(obj, 60);
		ObjPrim_SetTexture(obj, GetCurrentScriptDirectory ~ "Image/Field.png");
		ObjPrim_SetVertexCount(obj, 4);
		ObjRender_SetBlendType(obj, BLEND_ALPHA);
		ObjRender_SetColor(obj, 0, 0, 0);
		ObjRender_SetAlpha(obj, 160);

		let wideNum = 3;
		let border = ObjPrim_Create(OBJ_PRIMITIVE_2D);
		ObjPrim_SetPrimitiveType(border, PRIMITIVE_LINELIST);
		Obj_SetRenderPriorityI(border, 60);
		ObjPrim_SetTexture(border, GetCurrentScriptDirectory ~ "Image/Field.png");
		ObjPrim_SetVertexCount(border, (wideNum+1)*4 + 2);
		ObjRender_SetBlendType(border, BLEND_ALPHA);
		ObjRender_SetColor(border, 255, 255, 255);
		ObjRender_SetAlpha(border, 255);

		ascent(i in 0 .. wideNum+1){
			let j = i*4;
			let ratio = i/(wideNum);

			ObjPrim_SetVertexPosition(border, j, x - (width/2)*ratio*cos(beamAngle - 90), y - (width/2)*ratio*sin(beamAngle - 90), 0);
			ObjPrim_SetVertexPosition(border, j+1, destX - (width/2)*ratio*cos(beamAngle - 90), destY - (width/2)*ratio*sin(beamAngle - 90), 0);

			ObjPrim_SetVertexPosition(border, j+2, x + (width/2)*ratio*cos(beamAngle - 90), y + (width/2)*ratio*sin(beamAngle - 90), 0);
			ObjPrim_SetVertexPosition(border, j+3, destX + (width/2)*ratio*cos(beamAngle - 90), destY + (width/2)*ratio*sin(beamAngle - 90), 0);
		}

		ObjPrim_SetVertexPosition(border, (wideNum+1)*4, x - (width/2)*cos(beamAngle - 90), y - (width/2)*sin(beamAngle - 90), 0);
		ObjPrim_SetVertexPosition(border, (wideNum+1)*4 + 1, x + (width/2)*cos(beamAngle - 90), y + (width/2)*sin(beamAngle - 90), 0);

		let shot = ObjShot_Create(OBJ_SHOT);
		ObjShot_SetPenetration(shot, 100);
		ObjShot_SetDamage(shot, damage*15);
		ObjShot_SetEraseShot(shot, true);

		DrawBeam;

		return obj;

		task DrawBeam{
			ascent(i in 0 .. 4){
				ObjPrim_SetVertexUVT(obj, i, 0, 0);
			}

			let startWidth = width;
			ascent(c in 0 .. t+1){
				if(c > 3){ObjShot_SetEraseShot(shot, false);}
				width = linear(startWidth, 0, c/t);

				ascent(i in 0 .. wideNum+1){
					let j = i*4;
					let ratio = i/wideNum;

					ObjPrim_SetVertexPosition(border, j, x - ((width/2)*ratio)*cos(beamAngle - 90), y - ((width/2)*ratio)*sin(beamAngle - 90), 0);
					ObjPrim_SetVertexPosition(border, j+1, destX - ((width/2)*ratio)*cos(beamAngle - 90), destY - ((width/2)*ratio)*sin(beamAngle - 90), 0);

					ObjPrim_SetVertexPosition(border, j+2, x + ((width/2)*ratio)*cos(beamAngle - 90), y + ((width/2)*ratio)*sin(beamAngle - 90), 0);
					ObjPrim_SetVertexPosition(border, j+3, destX + ((width/2)*ratio)*cos(beamAngle - 90), destY + ((width/2)*ratio)*sin(beamAngle - 90), 0);
				}
				ObjPrim_SetVertexPosition(border, (wideNum+1)*4, x - (width/2)*cos(beamAngle - 90), y - (width/2)*sin(beamAngle - 90), 0);
				ObjPrim_SetVertexPosition(border, (wideNum+1)*4 + 1, x + (width/2)*cos(beamAngle - 90), y + (width/2)*sin(beamAngle - 90), 0);

				ObjPrim_SetVertexPosition(obj, 0, x - width/2*cos(beamAngle - 90), y - width/2*sin(beamAngle - 90), 0);
				ObjPrim_SetVertexPosition(obj, 1, x + width/2*cos(beamAngle - 90), y + width/2*sin(beamAngle - 90), 0);
				ObjPrim_SetVertexPosition(obj, 2, destX - width/2*cos(beamAngle - 90), destY - width/2*sin(beamAngle - 90), 0);
				ObjPrim_SetVertexPosition(obj, 3, destX + width/2*cos(beamAngle - 90), destY + width/2*sin(beamAngle - 90), 0);

				ObjShot_SetPenetration(shot, 100);
				ObjShot_SetIntersectionLine(shot, x, y, destX, destY, width/2);
				yield;
			}
			Obj_Delete(obj);
			Obj_Delete(border);
			Obj_Delete(shot);
		}
	}
}

task SpellTsubakura{
	SetPlayerInvincibilityFrame(300);
	PlaySoundA1(4, 70, 0);

	let manage = GetSpellManageObject;
	CanShoot = false;

	DarkenTintScreen(GetPlayerX, GetPlayerY, 32, [128, 128, 128], 240);

	let dir = 0;
	let counter = 0;
	let num = 3;
	loop(5){
		PlaySoundA1(10, 70, 0);
		loop(3){
			SpellShot(GetPlayerX, GetPlayerY, 10, dir);
			dir += 360/3;
		}
		dir += 45;
		loop(8){yield;}
	}
	loop(10){
		PlaySoundA1(10, 70, 0);
		loop(5){
			SpellShot(GetPlayerX, GetPlayerY, 10, dir);
			dir += 360/5;
		}
		dir += 29;
		loop(4){yield;}
	}
	loop(30){
		PlaySoundA1(10, 70, 0);
		loop(7){
			SpellShot(GetPlayerX, GetPlayerY, 10, dir);
			dir += 360/7;
		}
		dir += 22;
		loop(2){yield;}
	}

	loop(180){yield;}
	CanShoot = true;
	Obj_Delete(manage);
	loop(90){yield;}

	
	task SpellShot(x, y, v, a){
		let obj = ObjShot_Create(OBJ_SHOT);
		ObjShot_Regist(obj);
		ObjShot_SetGraphic(obj, 3);
		ObjShot_SetDamage(obj, 0.5);
		ObjShot_SetPenetration(obj, 10);
		ObjShot_SetSpellFactor(obj, true);
		ObjShot_SetEraseShot(obj, true);
		ObjShot_SetAutoDelete(obj, false);

		ObjMove_SetPosition(obj, x, y);
		ObjMove_SetAcceleration(obj, 0.1);
		ObjMove_SetMaxSpeed(obj, v);
		ObjMove_SetAngle(obj, a);

		Trail;
		Hitbox;

		task Trail{
			let count = 0;
			while(!Obj_IsDeleted(obj)){
				if(count % 3 == 0){
					TrailShot(ObjMove_GetX(obj), ObjMove_GetY(obj), 20);
				}
				count++;
				yield;
			}

			task TrailShot(xx, yy, t){
				let obj2 = ObjShot_Create(OBJ_SHOT);
				ObjShot_Regist(obj2);
				ObjShot_SetGraphic(obj2, 3);
				ObjShot_SetDamage(obj2, 0);
				ObjShot_SetPenetration(obj2, 10);
				ObjShot_SetSpellFactor(obj2, true);
				ObjShot_SetAutoDelete(obj2, false);
				ObjMove_SetPosition(obj2, xx, yy);

				let scale = 1;
				ascent(i in 0 .. t+1){
					scale = linear(1, 0, i/t);
					ObjShot_SetPenetration(obj2, 10);
					ObjRender_SetScaleXYZ(obj2, scale, scale, 0);
					yield;
				}
				Obj_Delete(obj2);
			}
		}

		task Hitbox{
			let pos = [];
			let damageMultiplier = 0;
			let count = 0;
			while(!Obj_IsDeleted(obj)){
				if(!Obj_IsInArea(obj, -32, -32, GetStgFrameWidth + 32, GetStgFrameHeight + 32)){Obj_Delete(obj); break;}
				pos = [ObjMove_GetX(obj), ObjMove_GetY(obj)];
				if(count > 30){damageMultiplier += 0.3;}

				ObjShot_SetPenetration(obj, 10);
				ObjShot_SetDamage(obj, damage*damageMultiplier);

				count++;
				yield;
			}

			PlaySoundA1(round(rand(11, 13)), 100, 0);
			Splatter(pos[0], pos[1], rand(0.5, 1), 90, damageMultiplier);
		}

		task Splatter(x, y, size, t, dd){
			let obj2 = ObjShot_Create(OBJ_SHOT);
			ObjShot_Regist(obj2);
			ObjShot_SetIntersectionCircleA1(obj2, 0);
			ObjShot_SetDamage(obj2, damage*dd);
			ObjShot_SetPenetration(obj2, 100);
			ObjShot_SetSpellFactor(obj2, true);
			ObjShot_SetEraseShot(obj2, true);
			ObjMove_SetPosition(obj2, x, y);

			let objRender = ObjPrim_Create(OBJ_SPRITE_2D);
			Obj_SetRenderPriorityI(objRender, 40);
			ObjPrim_SetTexture(objRender, GetCurrentScriptDirectory ~ "Image/splash.png");
			ObjSprite2D_SetSourceRect(objRender, 0, 0, 256, 256);
			ObjSprite2D_SetDestCenter(objRender);
			ObjRender_SetScaleXYZ(objRender, 0, 0, 0);
			ObjRender_SetAngleZ(objRender, rand(0, 360));
			ObjRender_SetPosition(objRender, x, y, 0);

			let scale = 0;
			let alpha = 255;
			ascent(i in 0 .. 15){
				scale = linear(0, size, i/15);

				ObjRender_SetScaleXYZ(objRender, scale, scale, 0);
				ObjRender_SetAlpha(objRender, alpha);
				ObjShot_SetIntersectionCircleA1(obj2, 64*scale);

				ObjShot_SetPenetration(obj2, 100);
				yield;
			}
			ascent(i in 15 .. t+1){
				alpha = linear(255, 0, (i - 15)/(t - 15));

				ObjRender_SetScaleXYZ(objRender, scale, scale, 0);
				ObjRender_SetAlpha(objRender, alpha);
				ObjShot_SetIntersectionCircleA1(obj2, 64*scale);

				ObjShot_SetPenetration(obj2, 100);
				yield;
			}
		}
	}
}