
	let GCSD=GetCurrentScriptDirectory;
	#include_function GCSD~"..\..\spellcircle.txt"
	#include_function GCSD~"..\..\text.txt"
	#include_function GCSD~"..\..\functions2.txt"
	let imgWhite=GPSD~"img\white.png";
	let imgEnemy=GPSD~"img\minion.png";
	let imgNameBG=GPSD~"img\spellnamebg.png";
	SetRateScoreSystemEnable(false);

	let DSurvival=0;
	let fontopacity=0;
	let lastopacity=0;
	let nameopacity=0;
	let spelltext="";
	let spelltextx=0;
	let spelltexta=0;
	let istr="";
	let SpellID=0;
	let yielded=0;
	let spellcard=0;
	let deleteobjects=false;	//set to true in certain enemies' finalize, so objects are given one frame to delete themselves

	let framecheckmain=0;
	let framecheckdraw=0;
	let framerate=0;
	let frameskip=0;
	let dying=0;
	let BossDefeated=0;

	let practicing=0;

	let graphicstodelete=[];

function Obj_SetColor(obj,vertices,alpha,r,g,b){
	let k=0;
	loop(vertices){
		ObjEffect_SetVertexColor(obj,k,alpha,r,g,b);
		k++;
	}
}
function Randomize{
	psrand(GetCommonDataDefault("Random",rand(0,999)));
}
function ForbidShot2(par){
	ForbidShot(par);ForbidBomb(par);
	if(par==true){SetCommonData("ForbidShot",1);}else{DeleteCommonData("ForbidShot");}
}
function GCX{return GetCenterX;}
function GCY{return GetCenterY;}
function upper(num1,num2){
//returns the higher of two numbers
	if(num1>num2){return num1;}else{return num2;}
}
function lower(num1,num2){
//returns the lower of two numbers
	if(num1<num2){return num1;}else{return num2;}
}
function center(num1,num2,num3){
//returns the middle number
	return lower(upper(num1,num2),num3)
}
function CollisionEllipse(xpoint,ypoint,xellipse,yellipse,width,height){
	let ret=0;

	if(  ( ((absolute(xpoint-xellipse)*1)^2) + ((absolute(ypoint-yellipse)*(width/height))^2) )^0.5<=width  ){ret=1;}

	return ret;
}
function Rainbow(color,offset){
	return center(0,sin((offset-(color*120)+70))+0.5,1);
}
function RainbowArray(offset,mult,adda){
	return [Rainbow(0,offset)*mult+adda,Rainbow(1,offset)*mult+adda,Rainbow(2,offset)*mult+adda];
}
function SetBG(number){
	SetCommonData("SpellBG",number);
	isspellcard=1;
}
function FreezeTime(value){
	SetCommonData("TimeFrozen",value);
	SetCommonData("SetTimeFrozen",true);
}
function ObjEffect_SetAlpha(obj,vertices,alpha){
let k=0;
loop(vertices){
	ObjEffect_SetVertexColor(obj,k,alpha,255,255,255);
	k++;
}
}

function ObjEffect_SetVertexXYAuto(obj,width,height){
//width and height are "radius", actual size will be double

ObjEffect_SetVertexXY(obj,0,-width,-height);
ObjEffect_SetVertexXY(obj,1, width,-height);
ObjEffect_SetVertexXY(obj,2, width, height);
ObjEffect_SetVertexXY(obj,3,-width, height);

}

function ObjEffect_SetVertexUVAuto(obj,width,height){
//width and height are "radius", actual size will be double

ObjEffect_SetVertexUV(obj,0,-width, 0);
ObjEffect_SetVertexUV(obj,1, width, 0);
ObjEffect_SetVertexUV(obj,2, width, height*2);
ObjEffect_SetVertexUV(obj,3,-width, height*2);

}

let spellbonus=[1,1.4,1.8,2.2,2.6,3,3.5];
function EndingFunc(stage){
	SetShotAutoDeleteClip(64,64,64,64);
	if(!GetCommonDataDefault("NoEndingFunction",false)){

		if(GetCommonDataDefault("ThisSpellCaptured",0)==1){
			SetCommonData("SPELLS_CAPTURED",GetCommonDataDefault("SPELLS_CAPTURED",0)+1);
			if(IsReplay==false){
				IncrementCapture(SpellID);
			}
			SetCommonData("SPELLS_CAPTURED_STAGE",GetCommonDataDefault("SPELLS_CAPTURED_STAGE",0)+1);
			PlaySE(".\seGetSpellCardBonus.wav");
			SetCommonData("SpellCapEffect",1);
			SetCommonData("SpellBonus",spellbonus[lower(stage-1,7)]*100000*((GetCommonData("SpellTimer")/GetCommonData("TimerMax"))*0.5+0.5));
			//SetCommonData("SpellBonus",GetCommonData("TimerMax"));
			//GetCommonData("TimerMax");
		}
		if(IsTimeOut==true){SetCommonData("SPELLS_TIMEOUTED",GetCommonDataDefault("SPELLS_TIMEOUTED",0)+1);}
		if(IsTimeOut==true){SetCommonData("SPELLS_TIMEOUTED_STAGE",GetCommonDataDefault("SPELLS_TIMEOUTED_STAGE",0)+1);}

		ClearText(250);
		loop(length(graphicstodelete)){
			DeleteGraphic(graphicstodelete[0]);
			graphicstodelete=erase(graphicstodelete,0);
		}
	}
	if(GetCommonDataDefault("SpellBG",0)>0){
		SetBG(-GetCommonDataDefault("SpellBG",0));
	}
	DeleteEnemyShotInCircle(ALL,GetCenterX,GetCenterY,1000000);
	SetCommonData("NextLifeBar",true);
	if(length(GetArgument)>0){
		CreateEnemyFromFile(GetArgument[0],GetX,GetY,0,0,erase(GetArgument,0));
	}
}
task HandleTimer{
	let soundthreshold=10;
	let obj=[InitEffect(GetClipMaxX-11,16,imgText,4,ALPHA,5), InitEffect(GetClipMaxX+5,16,imgText,4,ALPHA,5)];
	ObjEffect_SetXYRect(obj[0],-32,0,0,32);
	ObjEffect_SetXYRect(obj[1],-32,0,0,32);
	let lastdigit=[-1,-1];
	let divider=[10,1];
	let k=0;
	let sdigit;
	let frame=0;
	loop{
		k=0;
		loop(2){
			sdigit=trunc(lower(GetTimer2,99)/divider[k])%10+26*2;
			if(lastdigit[k]!=sdigit){
				if(sdigit==26*2&&k==0){
					ObjEffect_SetUVRect(obj[k],0,0,0,0);
				}else{
					ObjEffect_SetUVRect(obj[k],sdigit*32,0,sdigit*32+32,32);
				}
				lastdigit[k]=sdigit;
			}
			k++;
		}
		SetCommonData("SpellTimer",GetTimer2-(1/60));
		if(GetTimer2<0&&frame>1){
			SetLife(0);
		}
		else if(GetTimer2<soundthreshold&&frame>1){
			soundthreshold--;
			if(soundthreshold>2){
				SE("timeout1");
			}else{
				SE("timeout2");
			}
		}
		frame++;
		yield;
	}
}

let pointnumber=[[0,0],[10,15,20],[12,18,24],[14,21,28],[16,24,32],[18,27,36],[20,30,40],[22,33,44],[30,40,50]];

function PointItems(x,y,stage,spell){		//ending function for bosses
	//spell: 0=nonspell,1=spell,2=lastspell

	if(!GetCommonDataDefault("NoEndingFunction",false)){

		let requiredsouls=[[8,6],[5,4]];

		let amnt=pointnumber[stage][spell];
		if(spell==2){amnt=0;}
		if(GetCommonDataDefault("NoSpawnPoints",0)==0){
			let angle=0;
			let radius2=0;
			let pii=0;
			let captured=0;
			if (GetCommonDataDefault("ThisSpellCaptured",0)==1){
				amnt = pointnumber[stage][lower(spell+1,2)];
				captured++;
			}
			if(spell==2){
				CreateItems(x,y,20,amnt/2,amnt/2,0,0);
			}else{
				CreateItems(x,y,20,amnt/2,amnt/2,0,30/requiredsouls[spell][captured]);
			}
		}
	}
}

task DrawSurvival{
	SetCommonData("SurvivalCardD",1);
	let maxtimer=GetTimer2;
	SetLife(10000);
	loop{
		SetLife(upper((GetTimer2/maxtimer)*10000,1));
		yield;
	}
}


function DrawFunctions{
	//this section of code lets objects get one extra frame
	//to react to bombing, rather than just freezing
	if(OnBomb==true){
		if(yielded==0){
			yield;
			yielded=1;
		}
	}else{
		yielded=0;
	}
}

function DelayEffect(rx,ry,graphic,time){
	CreateShotA(1,rx,ry,time);
	SetShotDataA(1,0,500,0,0,0,0,graphic);
	SetShotKillTime(1,0);
	FireShot(1);
}

let imgEnderBig=GPSD~"img\ender_cutin.png";
let imgEmpeghBig=GPSD~"img\empegh_cutin.png";
let imgOverloadBig=GPSD~"img\overload_cutin.png";
let imgIddyeaBig=GPSD~"img\iddyeacutin.png";
let imgYumemiBig=GPSD~"img\yumemi_cutin.png";
let imgYukariBig=GPSD~"img\yukari_cutin.png";

let cutinimages=[imgEnderBig,imgEmpeghBig,imgOverloadBig,imgIddyeaBig,imgYumemiBig,imgYukariBig,imgWhite,imgWhite,imgWhite];
let cutinx=[360,332,436,400,400,400,0,0,0];	//right side
let cutiny=[410,410,410,400,400,400,400,400,400];	//bottom side
let cutino=[60,60,120,80,100,100,-60,-60,-60];		//x offset

task CutIn2(character,name){
	//character: 0=Ender, 1=Empegh, 2=Overload, 3=Iddyea, 4=Yumemi, 5=Yukari, 6=Chen, 7=Patchy, 8=Alice

    yield;
    character=6;

    let image=cutinimages[character];
    let x=cutinx[character];
    let y=cutiny[character];
    let xoffset=cutino[character];

    let cutintimer=0;
    let opacity=0;
    let obji=0;
    let borderscroll=0;
    let size=0;
	
    let obj = Obj_Create(OBJ_EFFECT);

    SetFontStyle(0,1,0,360,0,30);
    SetKerning(3);
    if(length(name)<=34){
	SetFontColorNew(0,0,0,0,0,0);
	DrawTextNew(20,name,imgText,GetClipMaxX-15+2,273,-10,lower(3.7,115/length(name)),5,7,-1,155,(40/length(name)));
	SetFontColorNew(128,196,255,255,255,255);
	DrawTextNew(20,name,imgText,GetClipMaxX-15,270,-10,lower(3.7,115/length(name)),5,7,-1,255,(40/length(name)));
    }else{
	SetFontColorNew(0,0,0,0,0,0);
	DrawTextNew(20,name,imgText,GetClipMaxX-15+2,270-(upper(length(name)-40,0))*20+3,-10-(length(name)-34)*2,3,5,7,-1,155,(40/length(name)));
	SetFontColorNew(128,196,255,255,255,255);
	DrawTextNew(20,name,imgText,GetClipMaxX-15,270-(upper(length(name)-40,0))*20,-10-(length(name)-34)*2,3,5,7,-1,255,(40/length(name)));
    }
    spelltext=name;
    spelltextx=0;
    Obj_SetSpeed      (obj, 0);
    Obj_SetAngle(obj, 0);
    ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
    ObjEffect_SetScale(obj,1,1);
    ObjEffect_SetAngle(obj,0,0,0);
    ObjEffect_SetLayer(obj,4);
    ObjEffect_CreateVertex(obj,4);

    ObjEffect_SetTexture(obj,image);
    Obj_SetPosition(obj,(GetClipMaxX-x/2)+xoffset,GetClipMaxY-y/2);

    ObjEffect_SetVertexUV(obj, 0, 0, 0);
    ObjEffect_SetVertexUV(obj, 1, 0, y);
    ObjEffect_SetVertexUV(obj, 2, x, y);
    ObjEffect_SetVertexUV(obj, 3, x, 0);

    let tempcolor=[0,0,0];
    let tempy=0;

    Overlay2(64,47,7,60,1,ADD, 255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0, (GetClipMaxX-x/2)-GetCenterX+xoffset,0, (x/1.5)-192,0,0,0,0,0);
    Overlay2(64,47,7,40,1,ADD, 255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0, 0,(GetClipMaxY-y/3)-GetCenterY, 0,-70,0,0,0,0);

    while(! Obj_BeDeleted(obj)&&cutintimer<120) {

	borderscroll+=2;

	if(cutintimer<111){
		opacity+=4;
	} else {
		opacity-=16;
		if(size==0){
			Overlay2(7,20,50,140,1,ADD, 255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0, (GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, -150,200,0,0,0,0);
			Overlay2(7,20,50,80,1,ADD, 255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,  (GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, 200,-180,0,0,0,0);
			Overlay2(7,20,50,60,1,ADD, 255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,(GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, -168,300,0,0,45,0);
			Overlay2(7,20,50,60,1,ADD, 255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,(GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, 300,-200,0,0,45, 0);

			Overlay2(12,0,25,40,1,ADD, 255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,(GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, -198,300,4,0,45,0);
			Overlay2(12,0,25,40,1,ADD, 255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,(GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, 300,-230,4,0,45, 0);
			Overlay2(12,0,25,40,1,ADD, 255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0,(GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, -198,300,-4,0,45,0);
			Overlay2(12,0,25,40,1,ADD, 255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,(GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, 300,-230,-4,0,45, 0);

			Overlay2(12,0,35,80,1,ADD, 255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0, (GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, -198,200,5,0,0,0);
			Overlay2(12,0,35,80,1,ADD, 255,255,255,0,0,0,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,0,0,0, (GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, -198,200,-5,0,0,0);
			Overlay2(12,0,35,80,1,ADD, 255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,  (GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, 200,-230,0,5,0,0);
			Overlay2(12,0,35,80,1,ADD, 255,255,255,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,  (GetClipMaxX-x/2)-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, 200,-230,0,-5,0,0);

		}
		if(size==6){
			//PlaySE("warp");
			SpellNameBG;
			SpellcardName(name);
			ShowHistory(SpellID,58);
			spellcard=1;
		}
		size++;
	}

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

	ObjEffect_SetVertexColor(obj,0, opacity ,255,255,255);
	ObjEffect_SetVertexColor(obj,1, opacity ,255,255,255);
	ObjEffect_SetVertexColor(obj,2, opacity ,255,255,255);
	ObjEffect_SetVertexColor(obj,3, opacity ,255,255,255);

	ObjEffect_SetVertexXY(obj,0,0-x/2,0-y/2+cutintimer/4);
	ObjEffect_SetVertexXY(obj,1,0-x/2,y/2  +cutintimer/4);
	ObjEffect_SetVertexXY(obj,2,x/2,y/2  +cutintimer/4);
	ObjEffect_SetVertexXY(obj,3,x/2,0-y/2+cutintimer/4);
	ObjEffect_SetScale(obj,1-size/30,1+size/15);
	ObjEffect_SetAngle(obj,0,-size*8,0);
	if(cutintimer==119){ClearText(20);}
	if(cutintimer%3==0){
		Overlay2(15,10,15,80,1,ADD, 255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, (prand(GetClipMaxX-x*0.7,GetClipMaxX-x*0.3))-GetCenterX+xoffset,(GetClipMaxY-y/2)-GetCenterY, -188,200,prand(-2,2),0,0,0);
		Overlay2(15,10,15,40,1,ADD, 255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, (prand(GetClipMaxX-x*0.7,GetClipMaxX-x*0.3))-GetCenterX+xoffset,(GetClipMaxY-y/3)-GetCenterY, -188,200,0,prand(-2,2),90,0);


		//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

		if(length(name)<=34){
			//DrawTextNew(20,name,imgText,GetClipMaxX-15,270,-10,lower(3.7,115/length(name)),5,7,-1,255,(40/length(name)));
			tempcolor=RainbowArray(cutintimer*10,155,100);
			tempy=sin(90-10)*16;
			Overlay2(15,10,15,80,1,ADD, tempcolor[0],tempcolor[1],tempcolor[2],0,0,0,tempcolor[0],tempcolor[1],tempcolor[2],0,0,0,0,0,0,0,0,0,0,0,0,tempcolor[0],tempcolor[1],tempcolor[2],0,0,0, GetClipMaxX-15-GetCenterX,270+tempy-GetCenterY, -188,200,0,prand(-1,1),80,0);
		}else{
			//DrawTextNew(20,name,imgText,GetClipMaxX-15,270-(upper(length(name)-40,0))*20,-10-(length(name)-34)*2,3,5,7,-1,255,(40/length(name)));
			tempcolor=RainbowArray(cutintimer*10,155,100);
			tempy=sin(90+(-10-(length(name)-34)*2))*16;
			Overlay2(15,10,15,80,1,ADD, tempcolor[0],tempcolor[1],tempcolor[2],0,0,0,tempcolor[0],tempcolor[1],tempcolor[2],0,0,0,0,0,0,0,0,0,0,0,0,tempcolor[0],tempcolor[1],tempcolor[2],0,0,0, GetClipMaxX-15-GetCenterX,270+tempy-(upper(length(name)-40,0))*20-GetCenterY, -188,200,0,prand(-1,1),90+(-10-(length(name)-34)*2),0);
		}
	}

	spelltextx-=0.3;

	cutintimer++;

        yield;

    }
    obji=0;
    Obj_Delete(obj);
}

task SpellNameBG{

    let obj = Obj_Create(OBJ_EFFECT);

    Obj_SetPosition(obj, 178,40);
    Obj_SetSpeed(obj, 0);
    Obj_SetAngle(obj, 0);
    ObjEffect_SetTexture(obj,imgNameBG);
    ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
    ObjEffect_SetScale(obj,1,1);
    ObjEffect_SetAngle(obj,0,0,0);
    ObjEffect_SetLayer(obj,2);
    ObjEffect_CreateVertex(obj,4);
    ObjEffect_SetRenderState(obj,ALPHA);

    ObjEffect_SetVertexXY(obj,0,0,0);
    ObjEffect_SetVertexXY(obj,1,256,0);
    ObjEffect_SetVertexXY(obj,2,256,32);
    ObjEffect_SetVertexXY(obj,3,0,32);
    ObjEffect_SetVertexUV(obj,0,0,0);
    ObjEffect_SetVertexUV(obj,1,256,0);
    ObjEffect_SetVertexUV(obj,2,256,32);
    ObjEffect_SetVertexUV(obj,3,0,32);
    let alphaadd=220/30;
    let alpha=0;
    loop(30){
	alpha+=alphaadd;
	SpellSetColor(obj,alpha);
	yield;
    }

}
function SpellSetColor(obj,alpha){
	let kk=0;
	loop(4){
		ObjEffect_SetVertexColor(obj,kk,alpha,255,255,255);
		kk++;
	}
}

task ImageCircle(graphic,left,top,right,bottom,centerX,centerY,radius,width,segments,rotation,layer,alpha,renderstate,red,green,blue){

    yield;
    let obj = Obj_Create(OBJ_EFFECT);
    let n=0;

    Obj_SetPosition   (obj, centerX,centerY);
    Obj_SetSpeed      (obj, 0);
    Obj_SetAngle(obj, 0);
    ObjEffect_SetTexture(obj,graphic);
    ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLESTRIP);
    ObjEffect_SetScale(obj,1,1);
    ObjEffect_SetAngle(obj,0,0,rotation);
    ObjEffect_SetLayer(obj,layer);
    ObjEffect_CreateVertex(obj,(segments*2)+2);
    ObjEffect_SetRenderState(obj,renderstate);

    n=0;
    loop((segments*2)+2){
	ObjEffect_SetVertexColor(obj,n,alpha,red,green,blue);
	if(n%2==0){ObjEffect_SetVertexUV(obj,n,left+(right/segments)*floor(n/2),top);
	} else {   ObjEffect_SetVertexUV(obj,n,left+(right/segments)*floor(n/2),bottom);
	}
	ObjEffect_SetVertexXY(obj,n, cos((360/segments)*floor(n/2))*upper(radius-((n%2)-0.5)*width,0), sin((360/segments)*floor(n/2))*upper(radius-((n%2)-0.5)*width,0) );
	n++;
    }

    yield;
    Obj_Delete(obj);
}

function Plaintext(str){
	let n=0;
	while(n<length(str)){	
		if(str[n]==''){
			str=erase(str,n);
			if(str[n]=='u'){str[n]='[';}
			if(str[n]=='v'){str[n]=']';}
		}
		n++;
	}
	return str;
}

function HandleDeathFramerate{
	let ret=0;
	if(framecheckmain<30){framerate++;}
	if(framecheckmain>=30){
		frameskip=round(30/upper(framerate,0.1));
		framecheckmain-=30;
		framecheckdraw-=30;
		framerate=0;
	}

	framecheckdraw++;
	if(framecheckdraw>framecheckmain){
		ret=center(1,frameskip,3);
	}
	framecheckdraw=framecheckmain+ret;
	if(ret>0){dying=1;}
	return ret;
}
let isspellcard=0;
task StartFunctions(increment,showhistory,var3){
	SetEffectForZeroLife(2,0,0);
	DeleteCommonData("ManualEnemyMarker");

	if(increment==1){IncrementCount(SpellID);}
	HandleTimer;
	HandleLifebar;
	if(GetCommonDataDefault("SpellPractice",0)==0){
		practicing=0;
	}else{
		practicing=1;
		if(GetCommonDataDefault("PracticeAutoReset",0)!=0){
			LastSpell2;
		}
	}
	isspellcard=0;
	HandleCapturing;
	yield;
	while(EventActive){
		yield;
	}
	if(showhistory==1){
		ShowHistory(SpellID,35);
	}
}
function ShowHistory(ID,Y){
	if(IsAWCPlayer){
		let string="History " ~ IntString(GetCommonDataDefault("PracticeC"~IntString(ID),0))~" / "~IntString(GetCommonDataDefault("PracticeA"~IntString(ID),0));
		//DrawTextNew(250,string,imgText,405,Y,0,2.5,2.5,2,-1,255,1);
		let obj=ObjText(0,string,-1,255,255,255,255,170,170,170, 30);
		Obj_SetPosition(obj,405,Y+16);
		ObjEffect_SetLayer(obj,2);
		ObjEffect_SetScale(obj,0.55,0.55);
		graphicstodelete=graphicstodelete~[string];
	}
}
function IncrementCount(ID){
	if(IsAWCPlayer){
		if(IsReplay==false&&GetCommonDataDefault("PracticeA"~IntString(ID),0)<999){SetCommonData("PracticeA"~IntString(ID),GetCommonDataDefault("PracticeA"~IntString(ID),0)+1);SaveCommonData;}
	}
}
function IncrementCapture(ID){
	if(IsAWCPlayer){
		if(IsReplay==false&&GetCommonDataDefault("PracticeC"~IntString(ID),0)<999){SetCommonData("PracticeC"~IntString(ID),GetCommonDataDefault("PracticeC"~IntString(ID),0)+1);SaveCommonData;}
	}
}


function CreateExplosion(type,exx,exy,exs,color,ee){	//lasts 16 frames
	let i=0;
	while(GetCommonDataDefault("Exps"~IntString(i),0)>0&&i<50){
		i++;
	}
	SetCommonData("Expx"~IntString(i),exx);
	SetCommonData("Expy"~IntString(i),exy);
	SetCommonData("Exps"~IntString(i),exs);
	SetCommonData("Expe"~IntString(i),ee);
	SetCommonData("Expc"~IntString(i),color);
	SetCommonData("Expt"~IntString(i),type);
	SetCommonData("Expf"~IntString(i),16);
	SetCommonData("Expst"~IntString(i),0);
	return i;
}
function CreateExplosionFlat(type,exx,exy,exs,color,ee){
	let i=CreateExplosion(type,exx,exy,exs,color,ee);
	SetCommonData("Expst"~IntString(i),1);
}
function CreateExplosionEX(type,exx,exy,exs,color,ee,time){
	let i=0;
	while(GetCommonDataDefault("Exps"~IntString(i),0)>0&&i<50){
		i++;
	}
	SetCommonData("Expx"~IntString(i),exx);
	SetCommonData("Expy"~IntString(i),exy);
	SetCommonData("Exps"~IntString(i),exs);
	SetCommonData("Expe"~IntString(i),ee);
	SetCommonData("Expc"~IntString(i),color);
	SetCommonData("Expt"~IntString(i),type);
	SetCommonData("Expf"~IntString(i),time);
	SetCommonData("Expst"~IntString(i),0);
	return i;
}
function CreateExplosionFlatEX(type,exx,exy,exs,color,ee,time){
	let i=CreateExplosionEX(type,exx,exy,exs,color,ee,time);
	SetCommonData("Expst"~IntString(i),1);
}
function DamageGFX(radius){
	if(GetHitCount>0){
		DamageGFX2(radius);
	}
}
task DamageGFX2(radius){
    let offset=rand(0,radius);
    let angle=rand(0,360);
    let angle2=rand(0,360);
    let obj = Obj_Create(OBJ_EFFECT);

    Obj_SetSpeed      (obj, 500);
    Obj_SetAngle(obj, 0);
    ObjEffect_SetTexture(obj,imgEnemy);
    ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
    ObjEffect_SetAngle(obj,0,0,angle2);
    ObjEffect_SetLayer(obj,2);
    ObjEffect_SetRenderState(obj,ADD);
    ObjEffect_CreateVertex(obj,4);
    ObjEffect_SetScale(obj,radius/6+1,0.08);
    ObjEffect_SetVertexXY(obj,0,0-16,0-16);
    ObjEffect_SetVertexXY(obj,1,0-16,0+16);
    ObjEffect_SetVertexXY(obj,2,0+16,0+16);
    ObjEffect_SetVertexXY(obj,3,0+16,0-16);
    ObjEffect_SetVertexUV(obj, 0, 1, 97);
    ObjEffect_SetVertexUV(obj, 1, 1, 127);
    ObjEffect_SetVertexUV(obj, 2, 31, 127);
    ObjEffect_SetVertexUV(obj, 3, 31, 97);
    Obj_SetAutoDelete(obj,false);
    let color=prand(0,360);
    let i=0;
    loop(4){
	ObjEffect_SetVertexColor(obj,i,255,Rainbow(0,color)*50+150,Rainbow(1,color)*50+150,Rainbow(2,color)*50+150);
	i++;
    }
    loop(2){
	Obj_SetPosition   (obj, GetX+cos(angle)*offset-500,GetY+sin(angle)*offset);
	yield;
    }

    Obj_Delete(obj);
}
task HandleLifebar{
	loop{
		SetCommonData("BossLife",GetLife);
		SetCommonData("EnemyX2",GetX);
		SetCommonData("EnemyY2",GetY);
		yield;
	}
}

task SpellcardName(name){
	yield;
	SetFontColorNew(255,255,255,255,128,128);
	SetFontStyle(1,0,0,0,0,30);
//	DrawTextNew(250,name,imgText,405,40,0, 3,3, 2,-1,255,1);
//	DrawTextNew(250,name,imgText,405,40,0, lower(3,110/length(name)),3, 2,-1,255,1);

	let obj=ObjText(0,name,-1,255,255,255,255,255,128,128, 30);
	Obj_SetPosition(obj,405,54);
	ObjEffect_SetLayer(obj,2);
//	ObjEffect_SetScale(obj,0.6,0.65);
	ObjEffect_SetScale(obj,lower( (22.5)/(length(name)),0.65) ,0.65);
	graphicstodelete=graphicstodelete~[name];
}


task DelayBombTask{
	let timeset=GetTimer2;
	while(OnBomb==true){
		if(GetTimeOfInvincibility<10){
			SetInvincibility(20);
		}
		SetTimer2(timeset);
		yield;
	}
}
function DelayBombTaskNoShoot{
	let timeset=GetTimer2;
	while(OnBomb==true){
		if(GetTimeOfInvincibility<10){
			SetInvincibility(20);
		}
		SetTimer2(timeset);
		yield;
	}
}
task WaitEvent(frames){
	let timeset=GetTimer2;
	while(GetCommonDataDefault("Dialogue",0)==1||frames>0){
		frames--;
		if(GetTimeOfInvincibility<10){
			SetInvincibility(20);
		}
		SetTimer2(timeset);
		yield;
	}
}
function CreateItems(x,y,radius,scorenum,multipliernum,soultype,soulsize){
	let ID;
	if(scorenum>0){
		ID=0;
		while(GetCommonDataDefault("PointDrop"~IntString(ID),[-999])[0]>-999){
			ID++;
		}
		loop(scorenum){
			SetCommonData("PointDrop"~IntString(ID),[x,y,radius/10]);
			ID++;
		}
	}
	if(multipliernum>0){
		ID=0;
		while(GetCommonDataDefault("MultDrop"~IntString(ID),[-999])[0]>-999){
			ID++;
		}
		loop(multipliernum){
			SetCommonData("MultDrop"~IntString(ID),[x,y,radius/10]);
			ID++;
		}
	}

	if(soulsize>0){
		ID=0;
		while(GetCommonDataDefault("SoulDrop"~IntString(ID),[-999])[0]>-999){
			ID++;
		}
		SetCommonData("SoulDrop"~IntString(ID),[x,y,soultype,soulsize]);
	}
}
task HandleCapturing{
	yield;
	SetCommonData("ThisSpellCaptured",0);
	while(GetTimeOfPlayerInvincibility>0||OnBomb==true){yield;}
	
	SetCommonData("ThisSpellCaptured",1);
	loop{
		if(GetTimeOfPlayerInvincibility>0||OnBomb==true){SetCommonData("ThisSpellCaptured",0);}
		yield;
	}
}
function RectCollision(x1,y1,x2,y2){
	if(GetPlayerX>=x1&&GetPlayerX<=x2&&GetPlayerY>=y1&&GetPlayerY<=y2&&GetTimeOfPlayerInvincibility==0){ShootDownPlayer;}
}
function RectGraze(x1,y1,x2,y2){
	let grazed=false;
	if(GetPlayerX>=x1&&GetPlayerX<=x2&&GetPlayerY>=y1&&GetPlayerY<=y2&&GetTimeOfPlayerInvincibility==0){AddGraze(1);PlaySE("se\seGraze.wav");grazed=true;}
	return grazed;
}
function CircleGraze(x,y,radius){
	let grazed=false;
	if(distance(x,y,GetPlayerX,GetPlayerY)<radius*radius&&GetTimeOfPlayerInvincibility==0){AddGraze(1);PlaySE("se\seGraze.wav");grazed=true;}
	return grazed;
}
function CircleCollision(x,y,radius){
	let collided=false;
	if(distance(x,y,GetPlayerX,GetPlayerY)<radius*radius&&GetTimeOfPlayerInvincibility==0){collided=true;}
	return collided;
}
task Line(x1,y1,x2,y2,width,alpha,time,layer,renderstate,color){
	let obj = Obj_Create(OBJ_EFFECT);
	let midpointx=(x1+x2)/2;
	let midpointy=(y1+y2)/2;
	let angle=atan2(y2-y1,x2-x1);

	ObjEffect_SetTexture(obj,imgWhite);
	ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
	ObjEffect_SetLayer(obj,layer);
	ObjEffect_SetRenderState(obj,renderstate);
	ObjEffect_CreateVertex(obj,4);
	ObjEffect_SetVertexXY(obj,0,0,0);
	ObjEffect_SetVertexXY(obj,1,1,0);
	ObjEffect_SetVertexXY(obj,2,1,1);
	ObjEffect_SetVertexXY(obj,3,0,1);
	ObjEffect_SetVertexUV(obj, 0, 0, 0);
	ObjEffect_SetVertexUV(obj, 1, 10, 0);
	ObjEffect_SetVertexUV(obj, 2, 10, 10);
	ObjEffect_SetVertexUV(obj, 3, 0, 10);
	Obj_SetAutoDelete(obj,false);

	Obj_SetColor(obj,4,alpha,color[0],color[1],color[2]);

	ObjEffect_SetScale(obj,distance(x1,y1,x2,y2)^0.5,width);
	ObjEffect_SetAngle(obj,0,0,angle);
	Obj_SetPosition(obj,midpointx,midpointy);

	let alphaadd=alpha/time;
	loop(time){
		Obj_SetColor(obj,4,alpha,color[0],color[1],color[2]);
		alpha-=alphaadd;
		yield;
	}
	Obj_Delete(obj);
}

task SetMovePositionNew(newx,newy,time){
	let x=GetX;
	let y=GetY;
	let addx=newx-x;
	let addy=newy-y;

	let percent=0;
	let frame=0;
	loop(time){
		//percent=frame/time;
		percent=sin((frame)*(90/time));
		SetX(x+addx*percent);
		SetY(y+addy*percent);
		frame++;
		yield;
	}
}
sub VaporInit{
	BombArmor;
}
task BombArmor{
	loop{
		if(OnBomb){
			SetCommonData("BombArmor",1);
			yield;
		}else{
			SetCommonData("BombArmor",0);
			yield;
		}
	}
}
function SetCollisionA2(x,y,size){if(GetCommonDataDefault("BombArmor",0)==0){SetCollisionA(x,y,size);}}
function SetCollisionB2(x,y,size){if(GetCommonDataDefault("BombArmor",0)==0){SetCollisionB(x,y,size);}}

function ShakeScreen(intensity,time){
	SetCommonData("StartShakeScreenI",intensity);
	SetCommonData("StartShakeScreenT",time);
}
function ScreenShakeY{return GetCommonDataDefault("ScreenShakeY",0);}
function ScreenShakeX{return GetCommonDataDefault("ScreenShakeX",0);}

function LastSpellEffect{
	LastSpell2;
	Overlay(0,0,40,255,7,ADD,255,255,255);
	yield;
}
function CreateShot01Ghost(x,y,v,a,g,d){
//creates a normal shot with no interaction
	let obj=Obj_Create(OBJ_SHOT);
	Obj_SetPosition(obj,x,y);
	Obj_SetSpeed(obj,v);
	Obj_SetAngle(obj,a);
	ObjShot_SetGraphic(obj,g);
	ObjShot_SetDelay(obj,d);
	Obj_SetCollisionToPlayer(obj,false);
	return obj;
}
task WarningLaser(x,y,a,l,w,g,alpha,time,fade){
	let obj=Obj_Create(OBJ_LASER);
	Obj_SetPosition(obj,x,y);
	Obj_SetAngle(obj,a);
	Obj_SetAlpha(obj,alpha);
	ObjShot_SetGraphic(obj,g);
	ObjLaser_SetWidth(obj,w);
	ObjLaser_SetLength(obj,l);
	ObjLaser_SetSource(obj,false);
	Obj_SetCollisionToPlayer(obj,false);
	loop(time){yield;}
	let alphaadd=alpha/fade;
	loop(fade){
		if(!deleteobjects){
			alpha-=alphaadd;
			Obj_SetAlpha(obj,alpha);
			yield;
		}
	}
	Obj_Delete(obj);
}
let cyberx=[-90,-90,-90,-90,-90,-90,-90,-90,-90,-90,-90,-90];
let cybery=[0,0,0,0,0,0,0,0,0,0,0,0];
let cybera=[0,0,0,0,0,0,0,0,0,0,0,0];
let cyberv=[0,0,0,0,0,0,0,0,0,0,0,0];
let cyberg=[0,0,0,0,0,0,0,0,0,0,0,0];
let cyberframe=0;
let cybert;
function CyberDrawLogic(width,height){
	width=rand(-width,width);
	height=rand(-height,height);
	let RandDirSave=RandDir;
	if(cyberframe%3*Detail(1,2,3)==0){
		cyberx[cyberframe/3]=trunc(GetX+width);
		cybery[cyberframe/3]=trunc(GetY+height);
		cybera[cyberframe/3]=rand_int(0,3)*90;
		cyberv[cyberframe/3]=rand(1,2)*RandDirSave;
		cyberg[cyberframe/3]=rand_int(0,15);
	}

	cybert=rand_int(0,11);
	cyberx[cybert]=cyberx[cybert]+rand_int(-5,5)*2;
	cybery[cybert]=cybery[cybert]+rand_int(-5,5)*2;

	cyberframe++;
	if(cyberframe==36){cyberframe=0;}
}
sub CyberDraw{
	SetTexture(imgEnemy);
	SetColor(255,255,255);
	SetAlpha(190);
	let k=0;
	loop(Detail(12,6,4)){
		if(cyberg[k]<8){
			SetGraphicRect(cyberg[k]*16,240,cyberg[k]*16+16,256);
		}else{
			SetGraphicRect(cyberg[k]*16-128,224-16,cyberg[k]*16-112,240);
		}
		SetGraphicAngle(0,0,cybera[k]);
		cybert=(((k*3)-cyberframe+36)%36);
		SetGraphicScale((lower(cybert,5)/5)*1.1,(1-(upper(cybert,31)-31)/5)*1.1);
		if(cyberx[k]%2==0){
			DrawGraphic(cyberx[k],cybery[k]+(12-cybert)*cyberv[k]);
		}else{
			DrawGraphic(cyberx[k]+(12-cybert)*cyberv[k]*0.5,cybery[k]);
		}
		k+=Detail(1,2,3);
	}
}

task FadeInShot01(x,y,v,a,g,d){
	let obj=Obj_Create(OBJ_SHOT);Obj_SetPosition(obj,x,y);Obj_SetSpeed(obj,v);Obj_SetAngle(obj,a);ObjShot_SetGraphic(obj,g);
	Obj_SetCollisionToPlayer(obj,false);
	let alpha=0;
	loop(d){
		alpha+=255/d;Obj_SetAlpha(obj,alpha);yield;
	}
	Obj_SetCollisionToPlayer(obj,true);
}
task FadeInShot01Damage(x,y,v,a,g,d){
	let obj=Obj_Create(OBJ_SHOT);Obj_SetPosition(obj,x,y);Obj_SetSpeed(obj,v);Obj_SetAngle(obj,a);ObjShot_SetGraphic(obj,g);
	let alpha=0;
	loop(d){
		alpha+=255/d;Obj_SetAlpha(obj,alpha);yield;
	}
}
function DelaySound(delay){
	let i=0;
	let f=0;
	while(GetCommonDataDefault("Change"~IntString(i),0)>0&&i<50){
		if(GetCommonData("Change"~IntString(i))==delay){f=1;}
		i++;
	}
	if(f==0){SetCommonData("Change"~IntString(i),delay);}
}
task DelaySoundBoss(delay){
	loop(delay){yield;}
	SE("change");
}
task DelayNew(x,y,a,size1,size2,graphic,time,offset){
	let obj=Obj_Create(OBJ_LASER);
	ObjShot_SetGraphic(obj,graphic);
	Obj_SetCollisionToPlayer(obj,false);
	Obj_SetAngle(obj,a);
	ObjLaser_SetSource(obj,false);
	let offsetangle=rand(0,360);
	let xmove=(cos(offsetangle)*offset)/time;
	let ymove=(sin(offsetangle)*offset)/time;

	let xoffset=cos(a)/2;
	let yoffset=sin(a)/2;

	x-=xmove*(time);
	y-=ymove*(time);
	let alpha=0;
	let alphaadd=255/(time/2);
	let sizeadd=(size2-size1)/time;
	while(time>0&&deleteobjects==false){
		ObjLaser_SetWidth(obj,size1);
		ObjLaser_SetLength(obj,size1);
		size1+=sizeadd;
		Obj_SetAlpha(obj,lower(alpha,255));
		alpha+=alphaadd;
		Obj_SetPosition(obj,x-xoffset*size1,y-yoffset*size1);
		x+=xmove;
		y+=ymove;
		time--;
		yield;
	}
	Obj_Delete(obj);
}
function EnemyShotDelay(x,y,a,size1,size2,graphic,time,offset){
	//makes the delay effect, but cancels it if the enemy is destroyed (but the shot still appears)
	DelayNew(x,y,a,size1,size2,graphic,time,offset);
	while(deleteobjects==false&&time>0){
		time--;
		yield;
	}
	return time;
}
task CreateShot01Delay(x,y,v,a,g,d,size1,size2,offset){
	//creates the effect if positive d, else just waits that many frames
	if(d>0){
		DelayNew(x,y,a,size1,size2,g,d,offset);
	}
	d=absolute(d);
	while(deleteobjects==false&&d>0){
		d--;
		yield;
	}
	if(!deleteobjects){
		CreateShot01(x,y,v,a,g,d);
	}
}
task CreateShot01DelayFade(x,y,v,a,g,d,size1,size2,offset,fade,fadesize){
	//creates the effect if positive d, else just waits that many frames
	if(d>0){
		DelayNew(x,y,a,size1,size2,g,d,offset);
	}
	loop(absolute(d)){yield;}
	CreateShotA(0,x,y,0);
	SetShotDataA(0,0,v,a,0,0,0,g);
	SetShotKillTime(0,fade);
	FireShot(0);
	loop(fade){yield;}
	DelayEffect(x+cos(a)*v*fade,y+sin(a)*v*fade,g,fadesize);
}
task CreateShot02Delay(x,y,v,a,accel,max,g,d,size1,size2,offset){
	//creates the effect if positive d, else just waits that many frames
	if(d>0){
		DelayNew(x,y,a,size1,size2,g,d,offset);
	}
	d=absolute(d);
	while(deleteobjects==false&&d>0){
		d--;
		yield;
	}
	if(!deleteobjects){
		CreateShot02(x,y,v,a,accel,max,g,d);
	}
}
function AddShotDelay(shotnum,frame,graphic,time){
	CreateShotA(100,0,0,time);
	SetShotDataA(100,0,500,0,0,0,0,graphic);
	SetShotKillTime(100,0);
	AddShot(frame,shotnum,100,0);
}
task DamageRateScale(shot1,bomb1,shot2,bomb2,time){
	let shotadd=(shot2-shot1)/time;
	let bombadd=(bomb2-bomb1)/time;
	loop(time){
		shot1+=shotadd;
		bomb1+=bombadd;
		SetDamageRate(shot1,bomb1);
		yield;
	}
}
function MoveRandom(randx,randy, left,top,right,bottom, playerxmax, time){
	//moves the boss a random amount in each direction (randx,randy), while staying within the bounding box set
	//also stays within playerxmax x-distance of the player
	let x=GetX;
	let y=GetY;
	if(x-randx<left){x=left+randx;}
	if(x+randx>right){x=right-randx;}
	if(y-randy<top){y=top+randy;}
	if(y+randy>bottom){y=bottom-randy;}
	x+=rand(-randx,randx);
	y+=rand(-randy,randy);
	if(x<GetPlayerX-playerxmax){x=GetPlayerX-playerxmax;}
	if(x>GetPlayerX+playerxmax){x=GetPlayerX+playerxmax;}
	SetMovePositionNew(x,y,time);
}

let chargelayer=2;

task NewCharge(time,size,frequency,r,g,b){
let frame=0;
let crand=0;
loop(time){
	while(frame>=1){
		crand=rand(0.3,1);
		ChargeEffect2(GetX,GetY,size,rand(0,359),r*crand,g*crand,b*crand,rand(-1,1),1);
		frame--;
	}
	frame+=frequency;
	yield;
}
}

task NewChargeShrink(time,size,frequency,r,g,b){
let frame=0;
let crand=0;
let sizeadd=size/time;
loop(time){
	while(frame>=1){
		crand=rand(0.3,1);
		ChargeEffect2(GetX,GetY,size,rand(0,359),r*crand,g*crand,b*crand,rand(-1,1),1);
		frame--;
	}
	size-=sizeadd;
	frame+=frequency;
	yield;
}
}


task NewCharge_XY(x,y,time,size,frequency,r,g,b){
let frame=0;
let crand=0;
loop(time){
	while(frame>=1){
		crand=rand(0,1);
		ChargeEffect2(x,y,size,rand(0,359),r*crand,g*crand,b*crand,rand(-1,1),0);
		frame--;
	}
	frame+=frequency;
	yield;
}
}

task NewChargeShrink_XY(x,y,time,size,frequency,r,g,b){
let frame=0;
let crand=0;
let sizeadd=size/time;
loop(time){
	while(frame>=1){
		crand=rand(0,1);
		ChargeEffect2(x,y,size,rand(0,359),r*crand,g*crand,b*crand,rand(-1,1),0);
		frame--;
	}
	size-=sizeadd;
	frame+=frequency;
	yield;
}
}

task ChargeEffect2(x,y,size,angle,cr,cg,cb,rotation,track){
    let obj = Obj_Create(OBJ_EFFECT);
    let timer=0;
    let offset=100;
    let offset2=rand(0,offset);
    let calpha=0;
    let i=0;

    Obj_SetAngle(obj, 0);ObjEffect_SetTexture(obj,imgEnemy);
    ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
    ObjEffect_SetAngle(obj,0,0,angle+90);ObjEffect_SetLayer(obj,chargelayer);ObjEffect_SetRenderState(obj,ADD);
    ObjEffect_CreateVertex(obj,4);ObjEffect_SetVertexXY(obj,0,0-16,0-16);
    ObjEffect_SetVertexXY(obj,1,0-16,0+16);ObjEffect_SetVertexXY(obj,2,0+16,0+16);ObjEffect_SetVertexXY(obj,3,0+16,0-16);ObjEffect_SetVertexUV(obj, 0, 1, 97);ObjEffect_SetVertexUV(obj, 1, 1, 127);ObjEffect_SetVertexUV(obj, 2, 31, 127);ObjEffect_SetVertexUV(obj, 3, 31, 97);
    Obj_SetAutoDelete(obj,false);
    Obj_SetPosition(obj,x,y);

    let erand=0;
    let cosangle=cos(angle);
    let sinangle=sin(angle);
    loop(20){
	if(track==1){
		Obj_SetPosition(obj,GetX,GetY);
	}

	ObjEffect_SetAngle(obj,0,0,angle+90);

	ObjEffect_SetScale(obj,0.3,(20-timer)*size*0.2);

	angle+=rotation;

	timer++;

	if(timer<=10){calpha+=20;}
	else{calpha-=20;}
	i=0;
	loop(4){
		ObjEffect_SetVertexColor(obj, i, calpha, cr,cg,cb);
		i++;
	}

        yield;

    }
    Obj_Delete(obj);
}

task ImageCharge(image,left,top,right,bottom,scale,radius,time,frequency,r,g,b,rotation,rotation2){
let frame=0;
let crand=0;
loop(time){
	while(frame>=1){
		crand=rand(0,1);
		ImageCharge2(image,left,top,right,bottom,GetX,GetY,scale,radius,prand(0,360),r*crand,g*crand,b*crand,prand(rotation[0],rotation[1]),prand(rotation2[0],rotation2[1]),1);
		frame--;
	}
	frame+=frequency;
	yield;
}
}
task ImageCharge_XY(x,y,image,left,top,right,bottom,scale,radius,time,frequency,r,g,b,rotation,rotation2){
let frame=0;
let crand=0;
loop(time){
	while(frame>=1){
		crand=rand(0,1);
		ImageCharge2(image,left,top,right,bottom,x,y,scale,radius,prand(0,360),r*crand,g*crand,b*crand,prand(rotation[0],rotation[1]),prand(rotation2[0],rotation2[1]),0);
		frame--;
	}
	frame+=frequency;
	yield;
}
}
task ImageCharge2(image,left,top,right,bottom,x,y,scale,radius,angle,cr,cg,cb,rotation,rotation2,track){
    let obj = Obj_Create(OBJ_EFFECT);
    let timer=0;
    let calpha=0;

    let proportion=(left-right)/(top-bottom);

    let i=0;

    Obj_SetSpeed      (obj, 500);Obj_SetAngle(obj, 0);ObjEffect_SetTexture(obj,image);
    ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
    ObjEffect_SetAngle(obj,0,0,angle+90);ObjEffect_SetLayer(obj,1);ObjEffect_SetRenderState(obj,ADD);
    ObjEffect_CreateVertex(obj,4);ObjEffect_SetVertexXY(obj,0,0-16,0-16);ObjEffect_SetVertexXY(obj,1,0-16,0+16);ObjEffect_SetVertexXY(obj,2,0+16,0+16);ObjEffect_SetVertexXY(obj,3,0+16,0-16);
    ObjEffect_SetVertexUV(obj, 0, left, top);ObjEffect_SetVertexUV(obj, 1, left, bottom);ObjEffect_SetVertexUV(obj, 2, right, bottom);ObjEffect_SetVertexUV(obj, 3, right, top);
    Obj_SetAutoDelete(obj,false);
    ObjEffect_SetScale(obj,(scale/16)*proportion,scale/16);

    let erand=0;
    let offset=0;
    let objangle=0;	//individual rotation
    if(rotation2!=0){
	objangle=prand(0,360);
    }
    loop(40){
	if(track==1){x=GetX;y=GetY;}
	Obj_SetX(obj,x+cos(angle)*offset-500);
	Obj_SetY(obj,y+sin(angle)*offset);

	ObjEffect_SetAngle(obj,0,0,angle+90+objangle);

	offset=cos(timer*(90/40))*radius;
	angle+=rotation;
	objangle+=rotation2;

	timer++;

	if(timer<=20){calpha+=10;}
	else{calpha-=10;}
	erand=rand(0.5,1);
	i=0;
	loop(4){
		ObjEffect_SetVertexColor(obj, i, calpha, cr*erand,cg*erand,cb*erand);
		i++;
	}

        yield;

    }
    Obj_Delete(obj);
}

task LinkShot(obj,obj2){
	Obj_SetCollisionToPlayer(obj2,false);
	Obj_SetAutoDelete(obj2,false);
	ObjShot_ToItem(obj2,false);
	while(!Obj_BeDeleted(obj)){
		yield;
	}
	ObjShot_FadeDelete(obj2);
}
function SetTimer2(num){
	SetCommonData("SpellTimer",num);
	SetCommonData("TimerMax",num);
}
function GetTimer2{
	return GetCommonDataDefault("SpellTimer",0);
}
task LastSpell2{
	let obj2=0;
	if(GetOption(0)!=5&&GetCommonDataDefault("SpellPractice",0)==0){
		obj2=InitEffect(635,219,GPSD~"img\frame.png",4,ALPHA,8);
		ObjEffect_SetAngle(obj2,0,0,90);
		ObjEffect_SetXYRect(obj2,-25,0,0,130);
		ObjEffect_SetUVRect(obj2,-25,0,0,130);	//draw the cross
	}

	ForbidBomb(true);
	while(OnPlayerMissed){yield;}
	let maxlife=GetPlayerLife;
	let currentmisses=GetMissCount;
	let timer=0;
	let obj=0;
	let inpractice=GetCommonDataDefault("SpellPractice",0)==1;
	let noyield=false;
	while(timer<[30,1][inpractice]){
		if(OnPlayerMissed||timer>0){
			if(timer==0&&!inpractice){
				obj=InitEffect(0,0,imgWhite,4,ALPHA,8);
				ObjEffect_SetXYRect(obj,GetClipMinX,GetClipMinY,GetClipMaxX,GetClipMaxY);
				ObjEffect_SetUVRect(obj,0,0,10,10);
			}else if(inpractice){
				noyield=true;
			}
			timer++;
			if(!inpractice){
				Obj_SetColor(obj,4,190-timer*(140/30),255,0,0);
			}
			SetInvincibility(100);
		}
		if(GetPlayerLife>maxlife){maxlife=GetPlayerLife;}
		ExtendPlayer(maxlife-GetPlayerLife);
		if(!noyield){
			yield;
		}
	}
	if(!inpractice){
		ExtendPlayer(maxlife-GetPlayerLife);
		Obj_Delete(obj);
	}
	if(GetOption(0)!=5&&GetCommonDataDefault("SpellPractice",0)==0){
		Obj_Delete(obj2);
	}
	yield;
	ExtendPlayer(maxlife-GetPlayerLife);
	SetCommonData("subtractmisses",GetCommonDataDefault("subtractmisses",0)+(GetMissCount-currentmisses));	//don't add it to the score tally
	SetLife(-1);
	ForbidBomb(false);
}

let fairyangle=[];
let fairyangle2=[];
let fairyradius=[];
let fairyanglev=[];
let fairycoloro=[];
let fairyx=[];
let fairyxv=[];
let fairyy=[];
let fairyyv=[];
let fairyt=[];
let fairycolorf=[];
let fairymax=0;
let fairyf=0;let fairyk=0;let fairyeffectnumo=0;let fairyfreqo=0;let fairyeffectnumf=0;let fairyfrequency=0;let sinradius=0;

function DeathFairyInit(freqorbit,numfire,freqfire){
	loop(numfire){
		fairyx=fairyx~[-100];
		fairyy=fairyy~[-100];
		fairyxv=fairyxv~[0];
		fairyyv=fairyyv~[0];
		fairyt=fairyt~[0];
		fairycolorf=fairycolorf~[[0,0,0]];
	}
	fairyfreqo=freqorbit;
	fairyeffectnumo=ceil(60/freqorbit);
	fairyeffectnumf=numfire;
	fairyfrequency=freqfire;
	fairymax=(fairyeffectnumf*fairyfrequency);
}
function DeathFairyLogic(coloro,saturationo,colorf,saturationf){
	if(fairyf%fairyfreqo==0){
		fairyangle=fairyangle~[rand(0,360)];
		fairyangle2=fairyangle2~[[rand(0,360),rand(0,360)]];
		fairyradius=fairyradius~[0];
		fairyanglev=fairyanglev~[rand(5,10)*RandDir];
		fairycoloro=fairycoloro~[RainbowArray(coloro,saturationo,1-saturationo)];
	}
	fairyk=0;
	loop(length(fairyangle)){
		fairyradius[fairyk]=fairyradius[fairyk]+1/60;
		fairyangle[fairyk]=fairyangle[fairyk]+fairyanglev[fairyk];
		if(fairyradius[fairyk]>1){
			fairyangle=erase(fairyangle,fairyk);
			fairyangle2=erase(fairyangle2,fairyk);
			fairyanglev=erase(fairyanglev,fairyk);
			fairyradius=erase(fairyradius,fairyk);
			fairycoloro=erase(fairycoloro,fairyk);
		}else{
			fairyk++;
		}
	}
	if(fairyf%fairyfrequency==0){
		fairyk=(fairyf%fairymax)/fairyfrequency;
		fairyx[fairyk]=GetX;
		fairyy[fairyk]=GetY;
		fairyxv[fairyk]=rand(-2,2);
		fairyyv[fairyk]=rand(-1,1);
		fairyt[fairyk]=fairyeffectnumf*fairyfrequency;
		fairycolorf[fairyk]=RainbowArray(colorf,saturationf,1-saturationf);
	}
	fairyf++;
	fairyk=0;
	loop(fairyeffectnumf){
		fairyx[fairyk]=fairyx[fairyk]+fairyxv[fairyk];
		fairyy[fairyk]=fairyy[fairyk]+fairyyv[fairyk];
		fairyyv[fairyk]=fairyyv[fairyk]-(8/fairymax);
		fairyt[fairyk]=fairyt[fairyk]-1;
		fairyk++;
	}
}
function DeathFairyEffect(radius,size){
	SetTexture(imgEffects);
	SetGraphicRect(129+64,1,255,63);
	SetRenderState(ADD);
	fairyk=0;
	loop(length(fairyangle)){
		sinradius=1-cos(fairyradius[fairyk]*(90));
		sinradius=fairyradius[fairyk];
		SetColor(100*(1-sinradius)*fairycoloro[fairyk][0],100*(1-sinradius)*fairycoloro[fairyk][1],100*(1-sinradius)*fairycoloro[fairyk][2]);
		SetGraphicAngle(fairyangle2[fairyk][0],fairyangle2[fairyk][1],fairyangle[fairyk]);
		SetGraphicScale(sinradius*radius,sinradius*radius);
		DrawGraphic(GetX,GetY);
		fairyk++;
	}

	SetTexture(imgEnemy);
	SetGraphicRect(0,96,32,128);
	
	SetGraphicScale(size/32,size/32);
	SetGraphicAngle(0,0,0);
	fairyk=0;
	loop(fairyeffectnumf){
		SetColor((fairyt[fairyk]/fairymax)*255*fairycolorf[fairyk][0],(fairyt[fairyk]/fairymax)*255*fairycolorf[fairyk][1],(fairyt[fairyk]/fairymax)*255*fairycolorf[fairyk][2]);
		DrawGraphic(fairyx[fairyk],fairyy[fairyk]);
		fairyk++;
	}
	SetRenderState(ALPHA);
}