function wait(n){loop(n){yield;}}


task shotSound(obj, time, volume, delay, enemy, limit){
    ObjSound_SetVolumeRate(obj, volume);
	ObjSound_SetRestartEnable(obj, true);
	if(time<0){
		while(ObjEnemy_GetInfo(enemy, INFO_LIFE) > limit){
			ObjSound_Play(obj);
			wait(delay);
		}
	}
	else{
	    let t=0;
	    while(t<time){
		    if(ObjEnemy_GetInfo(enemy, INFO_LIFE) <= limit){return;}
		    ObjSound_Play(obj);
			wait(delay);
			t+=delay;
		}
	}
}	

	
function LoadEffect(sound, volume){
    let obj1 = ObjSound_Create();
	ObjSound_Load(obj1, sound);
	ObjSound_SetVolumeRate(obj1, volume);
	return(obj1);
}

task Spell(name, obj, objBoss){
    SpellPicture;
	SpellWarn;
	SpellName(name, obj, objBoss);
}


/*task SpellPicture{
    let im = GetCurrentScriptDirectory~ "./../img/dave.png";
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj, im);
	ObjSprite2D_SetSourceRect(obj, 204, 210, 900, 920);
	ObjSprite2D_SetDestRect(obj, 0,30, 418,448);
	Obj_SetRenderPriorityI(obj, 70);
	ObjRender_SetPosition(obj, 384, 0, 1);
	while(ObjRender_GetX(obj)>40){
	    ObjRender_SetX(obj, ObjRender_GetX(obj) -20);
		yield;
	}
	loop(90){
	    ObjRender_SetX(obj, ObjRender_GetX(obj) -1);
		yield;
	}
	loop(30){
	    ObjRender_SetX(obj, ObjRender_GetX(obj) -20);
		yield;
	}
    Obj_Delete(obj);
} */


task SpellPicture{
    let im = GetCurrentScriptDirectory~ "./../img/JamesSpell.png";
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	ObjPrim_SetTexture(obj, im);
	ObjSprite2D_SetSourceRect(obj, 120, 280, 420, 730);
	ObjSprite2D_SetDestRect(obj, 0, 60, 260, 448);
	Obj_SetRenderPriorityI(obj, 70);
	ObjRender_SetPosition(obj, 384, 0, 1);
	while(ObjRender_GetX(obj)>100){
	    ObjRender_SetX(obj, ObjRender_GetX(obj) -20);
		yield;
	}
	loop(90){
	    ObjRender_SetX(obj, ObjRender_GetX(obj) -1);
		yield;
	}
	loop(30){
	    ObjRender_SetX(obj, ObjRender_GetX(obj) -20);
		yield;
	}
    Obj_Delete(obj);
}

task SpellWarn{
	let objText = ObjText_Create();
	ObjText_SetText(objText, "THIS PARTY IS[r]GETTING CRAZY!");
	ObjText_SetFontSize(objText, 40);
	ObjText_SetFontType(objText, "MS Gothic");
	ObjText_SetFontBold(objText, true);
	ObjText_SetFontColorTop(objText, 200, 0, 0);
	ObjText_SetFontColorBottom(objText, 100, 0, 150);
	ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER);
	
	ObjText_SetMaxWidth(objText, 360);
	Obj_SetRenderPriorityI(objText, 80);
	ObjRender_SetPosition(objText, -320, 20, 1);
	loop(16){
	    ObjRender_SetX(objText, ObjRender_GetX(objText) +20);
		yield;
	}
	loop(45){
	    ObjRender_SetX(objText, ObjRender_GetX(objText) +1);
		wait(2);
	}
	loop(30){
	    ObjRender_SetX(objText, ObjRender_GetX(objText) +20);
		yield;
	}
	Obj_Delete(objText);
}


task SpellName(name, obj, objBoss){
	let objText = ObjText_Create();
	ObjText_SetText(objText, name);
	ObjText_SetFontSize(objText, 20);
	ObjText_SetFontType(objText, "MS Gothic");
	ObjText_SetFontColorTop(objText, 217, 38, 38);
	ObjText_SetFontColorBottom(objText, 217, 38, 38);
	ObjText_SetFontBold(objText, true);
    ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER);
	ObjText_SetMaxWidth(objText, 300);
	Obj_SetRenderPriorityI(objText, 80);
	
	ObjRender_SetPosition(objText, 3*384/4- 170, 300, 1);
	wait(120);
	
	ObjText_SetMaxWidth(objText, 260);
	ObjText_SetFontBold(objText, false);
	ObjText_SetHorizontalAlignment(objText, ALIGNMENT_RIGHT);
	ObjRender_SetPosition(objText, 360-260, 15, 1);
	while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){yield;}
	Obj_Delete(objText);
}


task animNon(objBoss){
    let img = GetCurrentScriptDirectory() ~ "../img/NonSpell.png";
	let i=0;
	while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){
		ObjPrim_SetTexture(objBoss, img);
		if(i%2 ==0){
			ObjSprite2D_SetSourceRect(objBoss, 316, 70, 436, 410); 
			ObjSprite2D_SetDestRect(objBoss, -25, -70, 25, 70);
		}
		else{
			ObjSprite2D_SetSourceRect(objBoss, 25, 125, 180, 420); 
			ObjSprite2D_SetDestRect(objBoss, -43, -70, 43, 70);
		}
		
		i++;
		wait(30);
	}
}


task animSpell(objBoss){
    let img = GetCurrentScriptDirectory() ~ "../img/Spell.png";
	ObjPrim_SetTexture(objBoss, img);
	let i=0;
	while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){
	    if(i%2 ==0){
			ObjSprite2D_SetSourceRect(objBoss, 45, 80, 170, 410); 
			ObjSprite2D_SetDestRect(objBoss, -28, -70, 28, 70);
		}
		else{
			ObjSprite2D_SetSourceRect(objBoss, 286, 90, 446, 380); 
			ObjSprite2D_SetDestRect(objBoss, -50, -70, 30, 70);
		}
	    i++;
		wait(30);
	}
}
	




/* x,y spawning position of bullets. 
   numBranches is number of branches in spiral (evenly distributed around circle).
   waitPerBul is the pause between the spawning of each bullet. 
   direction = +/-1 determines whether branches go clockwise or counterclockwise. 
   periodShot is the duration of a cycle, numCycles is number of cycles if required.
   pause is the delay between cycles.
   speed, accel, wvev OK. Changes to accel, wvev are made after delay frames.
   If enemy is specified, limit is when the task ends. */

   
task spiral(x, y, numBranches, angleIni, waitPerBul, direction, periodShot, numCycles, pause, speed, accel, wvev, delay, graphic, enemy, limit, dis){
    let t = 0;
	let angle;
	if(numCycles > 0){
	    let cycles = 0;
	    while(cycles< numCycles){
		    angle = angleIni;
			while(t< periodShot){
			    loop(numBranches){
				    if(ObjEnemy_GetInfo(enemy, INFO_LIFE)<= limit){return;}
				    let obj = CreateShotA1(x, y, speed, angle, graphic, 0);
					Obj_SetRenderPriorityI(obj, 70);
					ObjMove_AddPatternA2(obj, delay, NO_CHANGE, NO_CHANGE, accel, wvev, 10);
					angle+= 360/ numBranches;
					if(dis){discont(obj,2);}
				}
				angle+= direction * waitPerBul;
				t+= waitPerBul;
				wait(waitPerBul);
			}
			wait(pause);
			t=0;
			cycles++;
		}
	}
	else{
	    while(ObjEnemy_GetInfo(enemy, INFO_LIFE) > limit){
			angle = angleIni;
			while(t< periodShot){
				loop(numBranches){
				    if(ObjEnemy_GetInfo(enemy, INFO_LIFE)<= limit){return;}
					let obj = CreateShotA1(x, y, speed, angle, graphic, 0);
					Obj_SetRenderPriorityI(obj, 70);
					ObjMove_AddPatternA2(obj, delay, NO_CHANGE, NO_CHANGE, accel, wvev, 10);
					angle+= 360/ numBranches;
					if(dis){discont(obj, 2);}
				}
				angle+= direction * waitPerBul;
				t+= waitPerBul;
				wait(waitPerBul);
			}
			wait(pause);
			t=0;
		}
	}
}		


task discont(obj, phase){
    let height = 448;
    let alpha = 0;
	if (phase ==1){
		loop{
			if((ObjMove_GetY(obj)< height/4) || (ObjMove_GetY(obj)> 5*height/8)){alpha =255;}
			else{alpha = 0;}
			ObjRender_SetAlpha(obj, alpha);
			Obj_SetVisible(obj, alpha > 0);
			yield;
		}
	}
	else if(phase==2){
	    loop{
			if((ObjMove_GetY(obj)< height/4) || (ObjMove_GetY(obj)> 3*height/4)){alpha =255;}
			else{alpha = 0;}
			ObjRender_SetAlpha(obj, alpha);
			Obj_SetVisible(obj, alpha > 0);
			yield;
		}
	}
	else{
	    loop{
			if(ObjMove_GetY(obj)< height/10+40){alpha =255;}
			else if((ObjMove_GetY(obj)>3* height/10+40) && (ObjMove_GetY(obj)< 3*height/5+20)){alpha =255;}
			else if(ObjMove_GetY(obj)> 4*height/5+20){alpha = 255;}
			else{alpha = 0;}
			ObjRender_SetAlpha(obj, alpha);
			Obj_SetVisible(obj, alpha > 0);
			yield;
		}
	}
}


task moveEdge(obj, angleIni, speed, limMove1, limMove2, pause, enemy, limit){
    ObjMove_AddPatternA1(obj, 0, speed, angleIni);  
	let limMove = limMove2;
	let i = 0;
    while(ObjEnemy_GetInfo(enemy, INFO_LIFE)>limit){
		if((angleIni == 90 && i%2 == 0) || (angleIni == -90 && i%2 == 1)) {while(ObjMove_GetY(obj)<limMove){yield;}}
		else if((angleIni == 90 && i%2 == 1) || (angleIni == -90 && i%2 == 0)){while(ObjMove_GetY(obj)>limMove){yield;}}
	    else if((angleIni == 0 && i%2 == 0) || (angleIni == 180 && i%2 == 1)){while(ObjMove_GetX(obj)<limMove){yield;}}
		else{while(ObjMove_GetX(obj)>limMove){yield;}}
		ObjMove_AddPatternA1(obj, 0, 0, NO_CHANGE);
		wait(pause);
		ObjMove_AddPatternA1(obj, 0, speed, ObjMove_GetAngle(obj)+180);
		i++;
		if(i%2 ==1){limMove = limMove1;}
		else{limMove = limMove2;}
	}
}
  

task launch(obj, numBul, generalDir, maxdiff, speed, accelmin, accelmax, maxspeed1, graphic, dis, com, delay, wvel, accel2min, accel2max, maxspeed2, spellRes, enemy){
    loop(numBul){
	    if(ObjEnemy_GetInfo(enemy, INFO_LIFE)<= 0){return;}
	    let obja=CreateShotA2(ObjMove_GetX(obj), ObjMove_GetY(obj), speed, rand(generalDir-maxdiff, generalDir+maxdiff), rand(accelmin, accelmax), maxspeed1, graphic, 0);
		Obj_SetRenderPriorityI(obja, 80);
		if(dis !=0){control(obja, dis);}
		if(spellRes){ObjShot_SetSpellResist(obja,true);}
		if(com){Command(obja, delay, wvel, rand(accel2min, accel2max), maxspeed2);}
	}
}

task controlWvel(obj, wvel, timeToChange, delay, maxspeed){
    ObjRender_SetAlpha(obj, 250); let t=0;
	ascent(c in 0..truncate(delay/timeToChange)){
		ObjMove_AddPatternA2(obj, timeToChange*c, NO_CHANGE, NO_CHANGE, NO_CHANGE, wvel, maxspeed);
		wvel*= -1;
	}
	wait(delay);
	Obj_Delete(obj);
}
	

task control(obj, dis){
    discont(obj, dis);
	while(ObjMove_GetY(obj)>0){yield;}
	ObjMove_SetSpeed(obj, 0);
	ObjMove_AddPatternA2(obj, 30, 0, 90, rand(0.02, 0.04), 0, 4);
}

task DelayLaser(x, y, ang, len, wid, graph, time){ 
	let objlaser = CreateStraightLaserA1(x, y, ang, len, wid, 1, graph, time);
	ObjStLaser_SetSource(objlaser, false);
	wait(time-1);
	Obj_Delete(objlaser);
}



task move(obj, xmin, xmax, ymin, ymax, delay, enemy, limit){
    while(ObjEnemy_GetInfo(enemy, INFO_LIFE) > limit){
	    ObjMove_SetDestAtFrame(obj, rand(xmin, xmax), rand(ymin, ymax), 60);
		wait(delay);
	}
}  


//Make these more flexible.
/*	
task danmakrain(colMin, colMax, colourArray, shootTime, delay, wvel, numBul, accel, objBoss){
    let obja = ObjSound_Create;
	ObjSound_Load(obja, GetCurrentScriptDirectory~ "../SFX/ATTACK2.WAV");
    while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){
	    let i=1;
		let col = truncate(rand(colMin, colMax));
		if (colourArray[0]!=0){col = colourArray[truncate(rand(0, length(colourArray)))];}
		let time =0;
		shotSound(obja, shootTime, 65, 10, objBoss);
		while(time< shootTime){
		    if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0) {return;}
			let obj =CreateShotA2(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss)-25, rand(4,6), rand(180, 360), rand(-0.15, -0.1), 0, col, 0);
			Command(obj, wvel, accel);
			if(i%2==0){let obj =CreateShotA2(ObjMove_GetX(objBoss), ObjMove_GetY(objBoss)-25, rand(4,6), rand(180, 360), rand(-0.15, -0.1), 0, col, 0);
			    Command(obj, wvel, accel);
			}
			i++;
		    time+= 60/numBul;
			wait(60/numBul);
	    }
		wait(delay);
	}
}
*/

task failBonus{
    let objText = ObjText_Create();
	ObjText_SetText(objText, "TOO BAD![r] SPELL BONUS[r]FAILED!");
	Obj_SetRenderPriorityI(objText, 80);
	ObjText_SetFontSize(objText, 40);
	ObjText_SetFontType(objText, "MS Gothic");
	ObjText_SetFontBold(objText, true);
	ObjText_SetFontColorTop(objText, 200, 0, 0);
	ObjText_SetFontColorBottom(objText, 100, 0, 150);
	ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER);
	
	ObjText_SetMaxWidth(objText, 360);
	Obj_SetRenderPriorityI(objText, 80);
	ObjRender_SetPosition(objText, 384/2-180, 20, 1);
	wait(120);
	Obj_Delete(objText);
}

task TFinalizeSpell(scene, objBoss) {
    while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){yield;}
    Obj_Delete(objBoss);
    DeleteShotAll(TYPE_ALL, TYPE_IMMEDIATE);
	if(ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SHOOTDOWN_COUNT)      
      +ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SPELL_COUNT) == 0){
	    ObjSound_Play(LoadEffect(GetCurrentScriptDirectory ~"./../SFX/BONUS3.WAV", 100));
        AddScore(ObjEnemyBossScene_GetInfo(scene, INFO_SPELL_SCORE));
		SetPlayerLife(GetPlayerLife()+1);
    }   
	else if(ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SHOOTDOWN_COUNT)                 
      +ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SPELL_COUNT) > 0){
	      ObjSound_Play(LoadEffect(GetCurrentScriptDirectory~ "./../SFX/ATTACK3.WAV", 80));
	      failBonus;
    }
	wait(240);
    SetAutoDeleteObject(true);
    CloseScript(GetOwnScriptID());
    return;
}
	

task TFinalizeNon(objBoss) {
    while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){yield;}
	ObjSound_Play(LoadEffect(GetCurrentScriptDirectory~ "./../SFX/ATTACK3.WAV", 100));
    DeleteShotAll(TYPE_ALL, TYPE_FADE);
	wait(30);
	Obj_Delete(objBoss);
    SetAutoDeleteObject(true);
    CloseScript(GetOwnScriptID());
    return;
}

task superSaiyan(enemy){
    let sound = LoadEffect(GetCurrentScriptDirectory~"./../SFX/superSaiyan.WAV", 100);
	ObjSound_SetRestartEnable(sound, true);
	ObjSound_SetLoopEnable(sound, true);
	while(ObjEnemy_GetInfo(enemy, INFO_LIFE)>0){ObjSound_Play(sound); yield;}
}

task text(msg, time){
    let objText = ObjText_Create();
	ObjText_SetText(objText, msg);
	ObjText_SetFontSize(objText, 20);
	ObjText_SetFontType(objText, "MS Gothic");
	ObjText_SetFontColorTop(objText, 255, 165, 30);
	ObjText_SetFontColorBottom(objText, 255, 165, 30);
	ObjText_SetFontBold(objText, true);
    ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER);
	ObjText_SetMaxWidth(objText, 320);
	Obj_SetRenderPriorityI(objText, 80);
	ObjRender_SetPosition(objText, 384/2 -150, 448/2, 1);
	wait(time);
	Obj_Delete(objText);
}

task Command(obj, delay, wvel, accel, maxspeed){
    while(ObjMove_GetSpeed(obj)>0){yield;}
	let ang = ObjMove_GetAngle(obj);
	if(ang<=270){ang = 90+ (3*180-2*ang)/4; wvel= -wvel;}
	else{ang= 360-ang;}
	ObjMove_AddPatternA2(obj, delay, 0, ang, accel, wvel, maxspeed);
}



task takeDamage(enemy, scene, lifeB){
    let sound = LoadEffect(GetCurrentScriptDirectory~ "./../SFX/DamageNon.WAV", 70);
	let sound2 = LoadEffect(GetCurrentScriptDirectory~ "./../SFX/DamageSpell.WAV", 70);
    let life; let lifen;
    while(ObjEnemy_GetInfo(enemy, INFO_LIFE)>0){
	    life = ObjEnemy_GetInfo(enemy, INFO_LIFE);
		yield;
		lifen = ObjEnemy_GetInfo(enemy, INFO_LIFE);
		if(lifen< life){
			while(lifen<life){
			    if(life<lifeB/4 && life> lifeB/8){ObjSound_Play(sound);}
				if(life<lifeB/8){ObjSound_Play(sound2);}
			    life = lifen;
				wait(4);
				lifen = ObjEnemy_GetInfo(enemy,INFO_LIFE);
			}
		}
	}
}

task Indicator(obj){
    let objText = ObjText_Create();
	ObjText_SetText(objText, "Thy enemy");
	ObjText_SetFontSize(objText, 15);
	ObjText_SetFontType(objText, "MS Gothic");
	ObjText_SetFontBold(objText, true);
	ObjText_SetFontColorTop(objText, 207, 254, 80);
	ObjText_SetFontColorBottom(objText, 207, 254, 80);
		
	ObjText_SetMaxWidth(objText, 100);
	ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER);
	Obj_SetRenderPriorityI(objText, 40);
	while(ObjEnemy_GetInfo(obj, INFO_LIFE)>0){
		ObjRender_SetPosition(objText, ObjMove_GetX(obj) - 50, 430, 1);
		yield;
	}
	Obj_Delete(objText);
}
    
