let imgItems=GPSD~"img\items.png";

let PointOfCollection=120;

let soulamount=[0,0,0,0,0];
let soulmaximum=[30,50,70,50];
let nextbombpoint=200;
let lastvalue=0;	//value of the last soul spawned

task SpawnPointItem(x,y,initialangle,speed,acceltime){
    let collected=0;
    let homing=0;

    let v1=-2;
    let v2=2;
    let xvinitial=cos(initialangle)*speed;
    let yvinitial=sin(initialangle)*speed;
    let speedphase=1;
    let speedadd=1/acceltime;

    let obj = Obj_Create(OBJ_EFFECT);
    Obj_SetPosition   (obj, trunc(x),trunc(y));

    SetItemGFX(obj,100,10);

    let addv=(v2-v1)/acceltime;
    let dist=0;
    let angle=0;
    let speed=8;
    let PoCed=0;

    let frame=0;
    while(collected==0&&y<480){
	if(v1<v2){
		v1+=addv;
		speedphase-=speedadd;
	}
	if(!timefrozen){
		if(homing==0||OnPlayerMissed){
			x+=xvinitial*speedphase;
			y+=v1+yvinitial*speedphase;
			homing=0;
		}else{
			angle=atan2(GetPlayerY-y,GetPlayerX-x);
			x+=cos(angle)*speed;
			y+=sin(angle)*speed;
			speed+=0.05;
		}
	}

	Obj_SetPosition(obj,round(x),round(y));

	if(frame%3==0){
		dist=distance(GetPlayerX,GetPlayerY,x,y);
		if(dist<12*12&&!OnPlayerMissed){
			collected=1;
		}
		if(dist<60*60&&!OnPlayerMissed){
			homing=1;
		}
	}
	if(GetCommonDataDefault("AutoCollectItems",0)==1){
		homing=1;
		PoCed=1;	//give full value from PoC even if you move down
	}
	yield;
    }
    let maxpoints=5000+GetCommonDataDefault("MaxPoint",0);
    let minpoints=(5000+GetCommonDataDefault("MaxPoint",0))/10;
    if(PoCed==1){minpoints=maxpoints;}
    if(collected==1){
	let position=lower((upper(GetPlayerY,PointOfCollection))-PointOfCollection,325);	// 0 (PoC) to 325 (bottom)
	let percentage=(325-position)/325;	//0 (bottom) to 1 (PoC)
	let score=trunc(((1-percentage)*minpoints)+(percentage*maxpoints));
	AddScore(score);
	SE("item");
	ShowNumberPointThingy(GetPlayerX,GetPlayerY,score,0);

	AddPoint(1);
	if(GetPoint>=nextbombpoint){
		IncrementBombPoint;
	}
    }
    Obj_Delete(obj);
}


task SpawnMultiplierItem(x,y,initialangle,speed,acceltime){
    let collected=0;
    let homing=0;

    let v1=-2;
    let v2=2;
    let xvinitial=cos(initialangle)*speed;
    let yvinitial=sin(initialangle)*speed;
    let speedphase=1;
    let speedadd=1/acceltime;

    let obj = Obj_Create(OBJ_EFFECT);
    Obj_SetPosition   (obj, trunc(x),trunc(y));

    SetItemGFX(obj,142,10);

    let addv=(v2-v1)/acceltime;
    let dist=0;
    let angle=0;
    let speed=8;
    let PoCed=0;

    let frame=0;
    while(collected==0&&y<480){
	if(v1<v2){
		v1+=addv;
		speedphase-=speedadd;
	}
	if(!timefrozen){
		if(homing==0||OnPlayerMissed){
			x+=xvinitial*speedphase;
			y+=v1+yvinitial*speedphase;
			homing=0;
		}else{
			angle=atan2(GetPlayerY-y,GetPlayerX-x);
			x+=cos(angle)*speed;
			y+=sin(angle)*speed;
			speed+=0.05;
		}
	}

	Obj_SetPosition(obj,round(x),round(y));

	if(frame%3==0){
		dist=distance(GetPlayerX,GetPlayerY,x,y);
		if(dist<12*12&&!OnPlayerMissed){
			collected=1;
		}
		if(dist<60*60&&!OnPlayerMissed){
			homing=1;
		}
	}
	if(GetCommonDataDefault("AutoCollectItems",0)==1){
		homing=1;
		PoCed=1;	//give full value from PoC even if you move down
	}
	yield;
    }
    if(collected==1){
//	let position=lower((upper(GetPlayerY,PointOfCollection))-PointOfCollection,325);	// 0 (PoC) to 325 (bottom)
//	let percentage=(325-position)/325;	//0 (bottom) to 1 (PoC)
//	let score=trunc(((1-percentage)*minpoints)+(percentage*maxpoints));
//	AddScore(score);
	SetCommonData("MaxPoint",GetCommonDataDefault("MaxPoint",0)+50);
	SE("item");
	ShowNumberPointThingy(GetPlayerX,GetPlayerY,50,1);

	AddPoint(1);
	if(GetPoint>=nextbombpoint){
		IncrementBombPoint;
	}
    }
    Obj_Delete(obj);
}

sub IncrementBombPoint{
	if(nextbombpoint<=400){
		BombUp(2);
	}else{
		BombUp(3);
	}
	nextbombpoint+=lower(round((nextbombpoint)/5)*5,400);
}



task SpawnBombItem(x,y,v1,v2,acceltime){
    let collected=0;
    let homing=0;

    let obj = Obj_Create(OBJ_EFFECT);
    Obj_SetPosition   (obj, trunc(x),trunc(y));

    SetItemGFX(obj,110,16);

    let addv=(v2-v1)/acceltime;
    let dist=0;
    let angle=0;
    let speed=8;
    while(collected==0&&y<480){
	if(v1<v2){
		v1+=addv*2;
	}
	if(!timefrozen){
		if(homing==0||OnPlayerMissed){
			y+=v1*2;
			homing=0;
		}else{
			angle=atan2(GetPlayerY-y,GetPlayerX-x);
			x+=cos(angle)*speed*2;
			y+=sin(angle)*speed*2;
			speed+=0.02;
		}
	}
	Obj_SetPosition(obj,round(x),round(y));
	dist=distance(GetPlayerX,GetPlayerY,x,y);
	if(dist<12*12&&!OnPlayerMissed){
		collected=1;
	}
	if((dist<70*70||GetCommonDataDefault("AutoCollectItems",0)==1)&&!OnPlayerMissed){
		homing=1;
	}
	yield;
	yield;
    }
    if(collected==1){
//	if(GetPlayerBomb<7){
//		AddBomb(1);
//	}
	BombUp(0);
    }
    Obj_Delete(obj);
}


task SpawnLifeItem(x,y,v1,v2,acceltime){
    let collected=0;
    let homing=0;

    let obj = Obj_Create(OBJ_EFFECT);
    Obj_SetPosition   (obj, trunc(x),trunc(y));

    SetItemGFX(obj,126,16);

    let addv=(v2-v1)/acceltime;
    let dist=0;
    let angle=0;
    let speed=8;
    while(collected==0&&y<480){
	if(v1<v2){
		v1+=addv*2;
	}
	if(!timefrozen){
		if(homing==0||OnPlayerMissed){
			y+=v1*2;
			homing=0;
		}else{
			angle=atan2(GetPlayerY-y,GetPlayerX-x);
			x+=cos(angle)*speed*2;
			y+=sin(angle)*speed*2;
			speed+=0.02;
		}
	}
	Obj_SetPosition(obj,round(x),round(y));
	dist=distance(GetPlayerX,GetPlayerY,x,y);
	if(dist<12*12&&!OnPlayerMissed){
		collected=1;
	}
	if((dist<70*70||GetCommonDataDefault("AutoCollectItems",0)==1)&&!OnPlayerMissed){
		homing=1;
	}
	yield;
	yield;
    }
    if(collected==1){
	LifeUp(0);
    }
    Obj_Delete(obj);
}






let totalscoredisplays=[-1,-1,-1,-1,-1,-1];
let totalscoreoffset=[-1,-1,-1,-1,-1,-1];

task ShowNumberPointThingy(x,y,num,color){
//num: number to display
//color: 0 = normal, 1 = multiplier, 2-5 = soul

	y=trunc(y);
	let yadd=-1;


	let ii=0;
	loop(6){	//search for this color in the list and set the Y offset if it already exists
		if(totalscoreoffset[ii]==color){
			yadd=ii*10;
		}
		ii++;
	}
	if(yadd==-1){	//otherwise find the first free slot and fill it
		ii=0;
		while(totalscoreoffset[ii]!=-1){
			ii++;
		}
		yadd=ii*10;
		totalscoreoffset[ii]=color;
	}

	let width=10;
	if(totalscoredisplays[color]==-1){
		num++;
	}
	totalscoredisplays[color]=totalscoredisplays[color]+num;
	num=totalscoredisplays[color];
	let numsave=num;

	let numbers=[];
	let digits=0;
	if(color>=2){
		numbers=[color+13.2];
		digits++;
	}
	ii=0;
	while(num>0||ii<1){
		char=num%10;
		//if(num==0&&ii!=digits-1){char=-width;}
		if(num>0){digits++;}
		num=trunc(num/10);

		numbers=numbers~[char];
		ii++;
	}
	if(color>=2){
		numbers=numbers~[color+13.2];
		digits++;
	}

	num=numsave;

	let obj=Obj_Create(OBJ_EFFECT);
	Obj_SetSpeed(obj, 0);
	Obj_SetAngle(obj, 0);
	ObjEffect_SetTexture(obj,imgItems);
	ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLESTRIP);
	ObjEffect_SetScale(obj,1,1);
	ObjEffect_SetAngle(obj,0,0,0);
	ObjEffect_SetLayer(obj,3);
	ObjEffect_CreateVertex(obj,6*(digits));
	ObjEffect_SetRenderState(obj,ALPHA);
	Obj_SetAutoDelete(obj,false);
	Obj_SetPosition(obj,trunc(x-digits*(width*1.5)),y);

	Score_SetAlpha(obj,digits,200,color);

	ii=digits-1;
	let minx=digits*width;
	let char=-1;
	loop(digits){
		if(numbers[ii]<12){
			char=trunc(numbers[ii])*width;	//truncate if it's a number
		}else{
			char=trunc(numbers[ii]*width);	//but leave the decimal for the symbols, since they aren't perfectly lined up
		}

		if(ii==0&&color>=2){
			minx+=4;
		}

		ObjEffect_SetVertexUV(obj,(ii*6)  ,char+0 ,0);
		ObjEffect_SetVertexUV(obj,(ii*6)+1,char+0 ,0);
		ObjEffect_SetVertexUV(obj,(ii*6)+2,char+width,0);
		ObjEffect_SetVertexUV(obj,(ii*6)+3,char+0 ,11);
		ObjEffect_SetVertexUV(obj,(ii*6)+4,char+width,11);
		ObjEffect_SetVertexUV(obj,(ii*6)+5,char+width,11);

		ObjEffect_SetVertexXY(obj,(ii*6)  ,minx,-5);
		ObjEffect_SetVertexXY(obj,(ii*6)+1,minx,-5);
		ObjEffect_SetVertexXY(obj,(ii*6)+2,minx+width,-5);
		ObjEffect_SetVertexXY(obj,(ii*6)+3,minx,6);
		ObjEffect_SetVertexXY(obj,(ii*6)+4,minx+width,6);
		ObjEffect_SetVertexXY(obj,(ii*6)+5,minx+width,6);


		ii--;
		minx+=9;
	}

	minx=0;
	let frame=0;
	while(frame<50&&totalscoredisplays[color]==num){
		Obj_SetPosition(obj,trunc(GetPlayerX-digits*(width*1.5))+minx,GetPlayerY-30-yadd);
//		Obj_SetY(obj,trunc(y)-30);
		frame++;
		yield;
	}
	let alpha=200;
	let alphaminus=200/30;
	if(totalscoredisplays[color]==num){
		totalscoredisplays[color]=-1;
		totalscoreoffset[yadd/10]=-1;
		ii=digits*6;
		loop(digits){
			ObjEffect_ResizeVertexCount(obj,ii);
			ii-=6;
			loop(3){
				Obj_SetPosition(obj,trunc(GetPlayerX-digits*(width*1.5))+minx,GetPlayerY-30-yadd);
				yield;
			}
		}

	}
	Obj_Delete(obj);
}


let scorecolortable=[
	[255,255,255],
	[96,255,96],
	[96,255,255]
];
function Score_SetAlpha(obj,digits,alpha,color){
	color=lower(color,2);
	let kk=0;
	if(color==2){
		digits-=2;
		kk+=6;
	}
	loop(6*digits){
		ObjEffect_SetVertexColor(obj,kk,alpha,scorecolortable[color][0],scorecolortable[color][1],scorecolortable[color][2]);
		kk++;
	}
}


function SetItemGFX(obj,x,size){
    Obj_SetSpeed      (obj, 0);
    Obj_SetAngle(obj, 0);
    ObjEffect_SetTexture(obj,imgItems);
    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);
    Obj_SetAutoDelete(obj,false);

    let size2=size/2;
    ObjEffect_SetVertexXY(obj,0,-size2,-size2);
    ObjEffect_SetVertexXY(obj,1, size2,-size2);
    ObjEffect_SetVertexXY(obj,2, size2, size2);
    ObjEffect_SetVertexXY(obj,3,-size2, size2);
    ObjEffect_SetVertexUV(obj,0,x, 0);
    ObjEffect_SetVertexUV(obj,1,x+size, 0);
    ObjEffect_SetVertexUV(obj,2,x+size,size);
    ObjEffect_SetVertexUV(obj,3,x,size);
}
function distance2(x1,y1,x2,y2){
	return ((x2-x1)^2+(y2-y1)^2)^0.5;
}












//life, bomb, autocollect, cancel
//purple,green,blue,yellow

let soulo=[];
let soult=[];
let souls=[];


task SpawnSoul(type,x,y,size){
    lastvalue=size;

    size*=8;

    SE("soul"~IntString(type+1));

    let collected=0;
    let homing=0;
    let speed=8;
    let dist=0;
    let angle=rand(0,360);


    let obj=Obj_Create(OBJ_EFFECT);
    Obj_SetSpeed      (obj, 0);
    Obj_SetAngle(obj, 0);
    Obj_SetAutoDelete(obj,false);
    Obj_SetPosition   (obj, x,y);


    SoulFollower(obj,-1,size*1.2,0.8,-1,-1);
    SoulFollower(obj,type,size,    0.7,1.5, 1);
    SoulSymbol(obj,type,size);

    loop(15){
	yield;
    }

    let kk=0;
    let exitloop=0;
    while(kk<length(soulo)&&exitloop==0){
	if(soult[kk]==type&&(size<15*8&&souls[kk]<15*8)&&!Obj_BeDeleted(soulo[kk])){
		dist=distance2(x,y,Obj_GetX(soulo[kk]),Obj_GetY(soulo[kk]));

		if(dist<120){
			let diffangle=atan2(Obj_GetY(soulo[kk])-y,Obj_GetX(soulo[kk])-x);
			Obj_Delete(soulo[kk]);
			Obj_Delete(obj);
			size+=souls[kk]+1*8;
			let excesssize=0;
			if(size>15*8){
				excesssize=size-15*8;
				size=15*8;
			}
			if(excesssize==0){
				SpawnSoul(type,x+cos(diffangle)*dist/2,y+sin(diffangle)*dist/2,size/8);
			}else{
				SpawnSoul(type,x,y,size/8);
				SpawnSoul(type,x+cos(diffangle)*dist,y+sin(diffangle)*dist,excesssize/8-1);
			}
			exitloop=1;
		}
	}
	kk++;
    }


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


	soulo=soulo~[obj];
	soult=soult~[type];
	souls=souls~[size];



	let yspeed=0;
	while(collected==0&&y<480+size&&!Obj_BeDeleted(obj)){
		if(!timefrozen){
			if(homing==0||OnPlayerMissed){
				yspeed+=0.005;
				y+=yspeed;
				if(type==0){
					if(x<GetPlayerX-10){x+=0.18;}else if(x>GetPlayerX+10){x-=0.18;}
				}else{
					if(x<GetPlayerX-10){x+=0.08;}else if(x>GetPlayerX+10){x-=0.08;}
				}
				homing=0;
			}else{
				angle=atan2(GetPlayerY-y,GetPlayerX-x);
				x+=cos(angle)*speed;
				y+=sin(angle)*speed;
				speed+=0.01;
			}
		}
		Obj_SetPosition   (obj, x,y);

		dist=distance(GetPlayerX,GetPlayerY,x,y);
		if(dist<(size/2+16)*(size/2+16)&&!OnPlayerMissed){
			collected=1;
		}
		if((GetCommonDataDefault("AutoCollectSouls",0)>=1)&&!OnPlayerMissed){
			homing=1;
		}
		yield;
	    }

	let id=GetID(obj);
	soulo=erase(soulo,id);
	soult=erase(soult,id);
	souls=erase(souls,id);

	if(collected==1){
		SE("soul"~IntString(type+1));
		soulamount[type]=soulamount[type]+size/8;
		if(soulamount[type]>=soulmaximum[type]){
			soulamount[type]=soulamount[type]-soulmaximum[type];
			FullSoul(type);
		}
		soulamount[4]=soulamount[4]+size/8;
		if(soulamount[4]>=GetCommonDataDefault("SoulMax",500)){
			Soul_SetColor(soulmet[4],255,5);
		}else{
			Soul_SetColor(soulmet[4],255,4);
		}

		ShowNumberPointThingy(GetPlayerX,GetPlayerY,((size/8)/soulmaximum[type])*100,2+type);
	
		UpdateSoulCounter(type);
	}
    }else{	//if fake
	while(GetCommonDataDefault("FakeSouls",false)){
		yield;
	}
    }
    Obj_Delete(obj);
}




task SoulFollower(obj2,type,size,opacity,rotdir,flip){
	size+=16;
	let obj=Obj_Create(OBJ_EFFECT);
	Obj_SetSpeed(obj, 0);
	Obj_SetAngle(obj, 0);
	ObjEffect_SetTexture(obj,imgItems);
	ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
	ObjEffect_SetAngle(obj,0,0,0);
	ObjEffect_SetLayer(obj,2);
	ObjEffect_CreateVertex(obj,4);
	ObjEffect_SetRenderState(obj,ALPHA);
	Obj_SetAutoDelete(obj,false);

	ObjEffect_SetVertexXY(obj,0,-size,-size);
	ObjEffect_SetVertexXY(obj,1, size,-size);
	ObjEffect_SetVertexXY(obj,2, size, size);
	ObjEffect_SetVertexXY(obj,3,-size, size);
	ObjEffect_SetVertexUV(obj,0,-64,0);
	ObjEffect_SetVertexUV(obj,1,  0,0);
	ObjEffect_SetVertexUV(obj,2,  0,64);
	ObjEffect_SetVertexUV(obj,3,-64,64);

	let scale=3.5;
	let alpha=0;
	let angle=rand(0,360);
	loop(15){
		scale-=1/6;
		ObjEffect_SetScale(obj,scale*flip,scale);
	
		angle+=scale*4*rotdir;
		ObjEffect_SetAngle(obj,0,0,angle);
	
		alpha+=255/15;

		Soul_SetColor(obj,alpha*opacity,type);

		Obj_SetPosition(obj,Obj_GetX(obj2),Obj_GetY(obj2));
		yield;
	}
	Soul_SetColor(obj,255*opacity,type);

	while(!Obj_BeDeleted(obj2)){
		angle+=4*rotdir;
		ObjEffect_SetAngle(obj,0,0,angle);
		Obj_SetPosition(obj,Obj_GetX(obj2),Obj_GetY(obj2));
		yield;
		while(timefrozen){yield;}
	}
	if(Obj_GetY(obj2)<480+size){
		loop(15){
			scale+=1/24;
			ObjEffect_SetScale(obj,scale*flip,scale);
		
			angle+=scale*4*rotdir;
			ObjEffect_SetAngle(obj,0,0,angle);
		
			alpha-=255/15;
			Soul_SetColor(obj,alpha*opacity,type);
		
			yield;
		}
	}

	Obj_Delete(obj);
}
task SoulSymbol(obj2,type,size){
	type*=48;
	let sizeold=size;
	let flashing=false;

	size=center(12,size/1.5,48);
	let obj=Obj_Create(OBJ_EFFECT);
	Obj_SetSpeed(obj, 0);
	Obj_SetAngle(obj, 0);
	ObjEffect_SetTexture(obj,imgItems);
	ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
	ObjEffect_SetAngle(obj,0,0,0);
	ObjEffect_SetLayer(obj,2);
	ObjEffect_CreateVertex(obj,4);
	ObjEffect_SetRenderState(obj,ALPHA);
	Obj_SetAutoDelete(obj,false);

	ObjEffect_SetVertexXY(obj,0,-size,-size+1);
	ObjEffect_SetVertexXY(obj,1, size,-size+1);
	ObjEffect_SetVertexXY(obj,2, size, size-1);
	ObjEffect_SetVertexXY(obj,3,-size, size-1);
	ObjEffect_SetVertexUV(obj,0,type   ,17);
	ObjEffect_SetVertexUV(obj,1,type+48,17);
	ObjEffect_SetVertexUV(obj,2,type+48,63);
	ObjEffect_SetVertexUV(obj,3,type   ,63);

	let scale=3.5;
	let alpha=0;
	let frame=0;
	loop(15){
		scale-=1/6;
		ObjEffect_SetScale(obj,scale,scale);
	
		alpha+=255/15;
		if(soulamount[type/48]+sizeold/8>=soulmaximum[type/48]){
			Soul_SetColor(obj,alpha*((cos(frame*20)/4)+0.75),4);
			flashing=true;
		}else{
			Soul_SetColor(obj,alpha,4);
		}
		Obj_SetPosition(obj,Obj_GetX(obj2),Obj_GetY(obj2));
		frame++;
		yield;
	}
	Soul_SetColor(obj,255,4);

	while(!Obj_BeDeleted(obj2)){
		if(soulamount[type/48]+sizeold/8>=soulmaximum[type/48]){
			Soul_SetColor(obj,alpha*((cos(frame*20)/4)+0.75),4);
			flashing=true;
		}else if(flashing){
			Soul_SetColor(obj,alpha,4);
			flashing=false;
		}
		Obj_SetPosition(obj,Obj_GetX(obj2),Obj_GetY(obj2));
		frame++;
		yield;
		while(timefrozen){yield;}
	}

	if(Obj_GetY(obj2)<480+size){
		loop(15){
			scale+=1/24;
			ObjEffect_SetScale(obj,scale,scale);
		
			alpha-=255/15;
			Soul_SetColor(obj,alpha,4);
		
			yield;
		}
	}

	Obj_Delete(obj);
}


let scolorindex=[
	[1,1,1],
	[1,0,0.8],
	[0,1,0],
	[0,0.5,1],
	[1,1,0],
	[1,1,1],
	[1,0,0]
];


function Soul_SetColor(obj,alpha,type){
	alpha=alpha*0.88;
	let kk=0;
	loop(4){
		ObjEffect_SetVertexColor(obj,kk,alpha,scolorindex[type+1][0]*200+55,scolorindex[type+1][1]*200+55,scolorindex[type+1][2]*200+55);
		kk++;
	}
}
function GetID(obj){
	let id=0;
	while(id<length(soulo)&&soulo[id]!=obj){
		id++;
	}
	return id;
}
task FullSoul(type){

	loop(2){
		SoulShine(type);
	}
	if(type==0){
		LifeUp(0);
		let alpha=255;
		loop(60){
			ImageCircle(stgwhite,0,0,50,50,GetPlayerX,GetPlayerY,100 ,2,3,-alpha*0.8,   2,alpha,ADD,255,128,128);
			ImageCircle(stgwhite,0,0,50,50,GetPlayerX,GetPlayerY,100 ,2,3,-alpha*0.8+60,2,alpha,ADD,255,128,255);
			alpha-=255/60;
			yield;
		}
	}
	if(type==1){
		BombUp(0);
		let alpha=255;
		loop(60){
			ImageCircle(stgwhite,0,0,50,50,GetPlayerX,GetPlayerY,100 ,2,3,alpha*0.8,   2,alpha,ADD,128,255,128);
			ImageCircle(stgwhite,0,0,50,50,GetPlayerX,GetPlayerY,100 ,2,3,alpha*0.8+60,2,alpha,ADD,0,255,0);
			alpha-=255/60;
			yield;
		}
	}
	if(type==2){
		BonusMessage(2,0);
		CollectAllItems(600);
		loop(9){
			BlueStar;
			Wait(60);
			yield;
		}
	}
	if(type==3){
		BonusMessage(3,0);
		let circlesize=0;
		loop(30){
			circlesize+=20;
			DeleteEnemyShotImmediatelyInCircle(SHOT,GetPlayerX,GetPlayerY,circlesize);
			ImageCircle(stgwhite,0,0,50,50,GetPlayerX,GetPlayerY,circlesize,25,48,0,2,50,ADD,255,255,0);
			ImageCircle(stgwhite,0,0,50,50,GetPlayerX,GetPlayerY,circlesize,15,48,0,2,100,ADD,255,255,128);
			ImageCircle(stgwhite,0,0,50,50,GetPlayerX,GetPlayerY,circlesize,5,48,0,2,150,ADD,255,255,255);
			yield;
		}
	}
}
task BlueStar{
	let rotation=prand(0,360);
	let loops=0;
	let size=100;
	loop(180){
		ImageCircle(stgwhite,0,0,50,50,GetPlayerX,GetPlayerY,size*2 ,2,4,rotation,   2,sin(loops)*70,ADD,128,128,255);
		ImageCircle(stgwhite,0,0,50,50,GetPlayerX,GetPlayerY,size*2 ,2,4,rotation+45,2,sin(loops)*70,ADD,128,128,255);
		rotation++;
		loops++;
		size-=10/18;
		yield;
	}
}
task SoulShine(type){
	let obj=Obj_Create(OBJ_EFFECT);
	ObjEffect_SetTexture(obj,imgItems);
	ObjEffect_SetPrimitiveType(obj,PRIMITIVE_TRIANGLEFAN);
	ObjEffect_SetScale(obj,1,1);
	ObjEffect_SetAngle(obj,0,0,0);
	ObjEffect_SetLayer(obj,8);
	ObjEffect_CreateVertex(obj,4);
	ObjEffect_SetRenderState(obj,ALPHA);
	Obj_SetAutoDelete(obj,false);
	Obj_SetPosition(obj,451+type*40,193-29);

	ObjEffect_SetVertexXY(obj,0,-30,-29);
	ObjEffect_SetVertexXY(obj,1, 30,-29);
	ObjEffect_SetVertexXY(obj,2, 30, 29);
	ObjEffect_SetVertexXY(obj,3,-30, 29);
	ObjEffect_SetVertexUV(obj,0,type*48   ,-47);
	ObjEffect_SetVertexUV(obj,1,type*48+48,-47);
	ObjEffect_SetVertexUV(obj,2,type*48+48,-1);
	ObjEffect_SetVertexUV(obj,3,type*48   ,-1);

	let size=1;
	let alpha=255;
	loop(90){
		Soul_SetColor(obj,alpha,4);
		ObjEffect_SetScale(obj,size,size);
		alpha-=255/90;
		size+=0.15;
		yield;
	}
	Obj_Delete(obj);
}
let bonusmessages=[false,false,false,false,false];
task BonusMessage(type,extra){
	extra--;
	let y=0;
	if(GetPlayerY<GetCenterY){
		y=1;
	}
	let yoffset=0;
	let bonusindex=0;
	loop(4){
		if(bonusmessages[bonusindex]){
			bonusindex++;
		}
	}
	if(bonusindex==5){bonusindex=0;}
	bonusmessages[bonusindex]=true;
	yoffset=bonusindex*28;
	let obj=InitEffect(GetCenterX,[150,340][y]+yoffset,imgBorder,4,ALPHA,2);
	let objb=InitEffect(540,260+yoffset,imgBorder,4,ALPHA,8);
	let obj2=0;
	let obj2b=0;
	BonusMessageTrans(obj);
	BonusMessageTrans(objb);
	if(extra>=0){
		obj2=InitEffect(GetCenterX,[150,340][y]+20+yoffset,imgBorder,4,ALPHA,2);
		obj2b=InitEffect(540,260+20+yoffset,imgBorder,4,ALPHA,8);
		BonusMessageTrans(obj2);
		BonusMessageTrans(obj2b);
	}
	let i=0;
	loop(16){
		i++;
		ObjEffect_SetXYRect(obj,-128,0,-128+i*16,35);
		ObjEffect_SetUVRect(obj,0,260+35*type,i*16,260+35*type+35);
		ObjEffect_SetXYRect(objb,-128,0,-128+i*16,35);
		ObjEffect_SetUVRect(objb,0,260+35*type,i*16,260+35*type+35);
		if(extra>=0){
			ObjEffect_SetXYRect(obj2,-128,0,-128+i*16,20);
			ObjEffect_SetUVRect(obj2,0,435+20*extra,i*16,435+20*extra+20);
			ObjEffect_SetXYRect(obj2b,-128,0,-128+i*16,20);
			ObjEffect_SetUVRect(obj2b,0,435+20*extra,i*16,435+20*extra+20);
		}
		yield;
	}
	Wait(70);
	bonusmessages[bonusindex]=false;
	i=0;
	loop(16){
		i++;
		ObjEffect_SetXYRect(obj,-128+i*16,0,128,35);
		ObjEffect_SetUVRect(obj,i*16,260+35*type,256,260+35*type+35);
		ObjEffect_SetXYRect(objb,-128+i*16,0,128,35);
		ObjEffect_SetUVRect(objb,i*16,260+35*type,256,260+35*type+35);
		if(extra>=0){
			ObjEffect_SetXYRect(obj2,-128+i*16,0,128,20);
			ObjEffect_SetUVRect(obj2,i*16,435+20*extra,256,435+20*extra+20);
			ObjEffect_SetXYRect(obj2b,-128+i*16,0,128,20);
			ObjEffect_SetUVRect(obj2b,i*16,435+20*extra,256,435+20*extra+20);
		}

		yield;
	}
	Obj_Delete(obj);
	Obj_Delete(objb);
	if(extra>=0){
		Obj_Delete(obj2);
		Obj_Delete(obj2b);
	}
}
task BonusMessageTrans(obj){
	let frame=0;
	while(!Obj_BeDeleted(obj)){
		Obj_SetColor(obj,4,225+sin(frame*32)*30,255,255,255);
		frame++;
		yield;
	}
}

task CollectAllItems(frames){
	SetCommonData("AutoCollectItems",GetCommonDataDefault("AutoCollectItems",0)+1);
	Wait(frames);
	SetCommonData("AutoCollectItems",GetCommonDataDefault("AutoCollectItems",1)-1);
}
task CollectAllSouls(frames){
	SetCommonData("AutoCollectSouls",GetCommonDataDefault("AutoCollectSouls",0)+1);
	Wait(frames);
	SetCommonData("AutoCollectSouls",GetCommonDataDefault("AutoCollectSouls",1)-1);
}

function SetSoulReq(stage){
	soulamount[4]=0;
	SetCommonData("SoulMax",[100,330,400,170][stage]);
	UpdateSoulCounter(0);
}
function IsFullSoul{
	return soulamount[4]+lastvalue>=GetCommonDataDefault("SoulMax",500);
}

task LifeUp(extramessage){
	BonusMessage(0,extramessage);
	SE("extend");
	if(GetPlayerLife<108){
		ExtendPlayer(1);
	}
	if(GetOption(0)==5){
		totallives++;
	}
	if(GetCommonDataDefault("NhimorTargetColor",-1)==-1){
		SetCommonData("NhimorTargetColor",1);
		Wait(120);
		if(GetCommonDataDefault("NhimorTargetColor",-1)==1){
			DeleteCommonData("NhimorTargetColor");
		}
	}
}
function BombUp(extramessage){
	BonusMessage(1,extramessage);
	SE("bomb");
	if(GetPlayerBomb<7){
		AddBomb(1);
	}
}