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

function speak(top, msg){
    let objText = ObjText_Create();
	ObjText_SetText(objText, msg);
	ObjText_SetFontSize(objText, 20);
	ObjText_SetFontType(objText, "MS Gothic");
	ObjText_SetFontColorTop(objText, 110, 200, 255);
	ObjText_SetFontColorBottom(objText, 110, 200, 255);
	ObjText_SetFontBold(objText, true);
    ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER);
	ObjText_SetMaxWidth(objText, 320);
	let y = 300; if(top){y = 140;}
	ObjRender_SetPosition(objText, 192-160, y,1);
	Obj_SetRenderPriorityI(objText, 79);
	return objText;
}

task skip(objBoss){
	let objText = ObjText_Create();
	ObjText_SetText(objText, "(Press the shot button to skip dialogue)");
	ObjText_SetFontSize(objText, 16);
	ObjText_SetFontType(objText, "Arial");
	ObjText_SetFontColorTop(objText, 255, 255, 255);
	ObjText_SetFontColorBottom(objText, 255, 255, 255);
	ObjText_SetFontBold(objText, false);
    ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER);
	ObjText_SetMaxWidth(objText, 320);
	ObjRender_SetPosition(objText, 192-160, 400,1);
	Obj_SetRenderPriorityI(objText, 79);
	while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){yield;}
	Obj_Delete(objText);
}


task Name(num, objBoss){
	let objText = ObjText_Create();
	if(num==1){ObjText_SetText(objText, "DUS Dave Wood");}
	else if(num==2){ObjText_SetText(objText, "Dr Mario Micallef");}
	else{ObjText_SetText(objText, "Prof James Robinson");}
	ObjText_SetFontSize(objText, 15);
	ObjText_SetFontType(objText, "Arial");
	ObjText_SetFontBold(objText, true);
	ObjText_SetFontColorTop(objText, 255, 255, 255);
	ObjText_SetFontColorBottom(objText, 255, 255, 255);
		
	ObjText_SetMaxWidth(objText, 150);
	Obj_SetRenderPriorityI(objText, 70);
	ObjRender_SetPosition(objText, 5, 15, 1);
    while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){yield;}
    Obj_Delete(objText);	
}
	
function LoadEffect(sound, volume){
    let obj1 = ObjSound_Create();
	ObjSound_Load(obj1, sound);
	ObjSound_SetVolumeRate(obj1, volume);
	return(obj1);
}

task TFinalize(objBoss) {   
    while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){yield;}
	Obj_Delete(objBoss);
    CloseScript(GetOwnScriptID());
    return;
}


task TFinalizeNon(scene, objBoss) {
    while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){yield;}
	ObjSound_Play(LoadEffect(GetCurrentScriptDirectory~ "./../SFX/ATTACK3.WAV", 100));
    DeleteShotAll(TYPE_ALL, TYPE_FADE);
	if(ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SHOOTDOWN_COUNT)      
      +ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SPELL_COUNT) == 0 && ObjEnemyBossScene_GetInfo(scene, INFO_TIMER)>0){
	    ObjSound_Play(LoadEffect(GetCurrentScriptDirectory ~"./../SFX/BONUS2.WAV", 100));
		SetPlayerSpell(GetPlayerSpell+1);
    }
	wait(30);
	Obj_Delete(objBoss);
    SetAutoDeleteObject(true);
    CloseScript(GetOwnScriptID());
    return;
}

task TFinalizeSpell(scene, objBoss, timeout, destroy) {
    while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > 0){yield;}
	if(destroy){
	    StartSlow(TARGET_ALL, 30);
		let a = LoadEffect(GetCurrentScriptDirectory~ "./../SFX/ATTACK3.WAV", 70);
		loop(4){ObjSound_Play(a); wait(15);}
		StopSlow(TARGET_ALL);
	}
    Obj_Delete(objBoss);
    DeleteShotAll(TYPE_ALL, TYPE_IMMEDIATE);
	if(ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SHOOTDOWN_COUNT)      
      +ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SPELL_COUNT) == 0){
	      if((!timeout && ObjEnemyBossScene_GetInfo(scene, INFO_TIMER)>0) || timeout){
			ObjSound_Play(LoadEffect(GetCurrentScriptDirectory ~"./../SFX/BONUS3.WAV", 100));
			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;
    }
	if(destroy){ObjSound_Play(LoadEffect(GetCurrentScriptDirectory~ "./../SFX/DEFEATED.WAV", 100));}
	wait(240);
    SetAutoDeleteObject(true);
    CloseScript(GetOwnScriptID());
    return;
}



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/8){
				    if(ObjEnemyBossScene_GetInfo(scene, INFO_IS_SPELL)){ObjSound_Play(sound2);}
					else{ObjSound_Play(sound);}
				}
			    life = lifen;
				wait(4);
				lifen = ObjEnemy_GetInfo(enemy,INFO_LIFE);
			}
		}
	}
}

task Indicator(obj, numBoss){
    let objText = ObjText_Create();
	if(numBoss ==1){ObjText_SetText(objText, "Dave");}
	else if(numBoss ==2){ObjText_SetText(objText, "Mario");}
	else{ObjText_SetText(objText, "James");}
	ObjText_SetFontSize(objText, 18);
	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, 90);
	while(ObjEnemy_GetInfo(obj, INFO_LIFE)>0){
		ObjRender_SetPosition(objText, ObjMove_GetX(obj) - 15, 462, 1);
		yield;
	}
	Obj_Delete(objText);
}


task failBonus{
    let objText = ObjText_Create();
	ObjText_SetText(objText, "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 launch(obj, numBul, generalDir, maxdiff, speed, accelmin, accelmax, maxspeed1, graphic, 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(spellRes){ObjShot_SetSpellResist(obja,true);}
		if(com){Command(obja, delay, wvel, rand(accel2min, accel2max), maxspeed2);}
	}
}


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 shotSound(obj, time, volume, delay, enemy, delete, limit){
    ObjSound_SetVolumeRate(obj, volume);
	ObjSound_SetRestartEnable(obj, true);
	if(time<0){
	    if(delete){
			while(!Obj_IsDeleted(enemy)){
				ObjSound_Play(obj);
				wait(delay);
			}
		}
		else{
		    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;
		}
	}
}	


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


task SpellPicture(numBoss){
    if(numBoss ==1){
		let im = GetCurrentScriptDirectory~ "./../img/dave.png";
		let obj = ObjPrim_Create(OBJ_SPRITE_2D);
		ObjPrim_SetTexture(obj, im);
		ObjSprite2D_SetSourceRect(obj, 55, 17, 500, 517);
		ObjSprite2D_SetDestRect(obj, 0,80, 330,448);
		Obj_SetRenderPriorityI(obj, 70);
		ObjRender_SetPosition(obj, 500, 0, 1);
		while(ObjRender_GetX(obj)>80){
			ObjRender_SetX(obj, ObjRender_GetX(obj) -20);
			yield;
		}
		loop(80){
			ObjRender_SetX(obj, ObjRender_GetX(obj) -1);
			yield;
		}
		loop(30){
			ObjRender_SetX(obj, ObjRender_GetX(obj) -20);
			yield;
		}
		Obj_Delete(obj);
	}
	else if(numBoss==2){
	    let im = GetCurrentScriptDirectory~ "../img/MarioSpell.png";
		let obj = ObjPrim_Create(OBJ_SPRITE_2D);
		ObjPrim_SetTexture(obj, im);
		ObjSprite2D_SetSourceRect(obj, 66, 70, 966, 980);
		ObjSprite2D_SetDestRect(obj, 0,0, 300,300);
		Obj_SetRenderPriorityI(obj, 70);
		ObjRender_SetPosition(obj, 384, 150, 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);
	}
	else{
	    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);
		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 MasterSparkSound(time, objBoss){
    let obj = LoadEffect(GetCurrentScriptDirectory~"./../SFX/MASTER SPARK.WAV", 90);
	ObjSound_Play(obj); let t=0;
	while(t<time-30){if(ObjEnemy_GetInfo(objBoss, INFO_LIFE)<=0){ObjSound_Stop(obj);} yield; t++;}
	ascent(i in 0..60) {
		ObjSound_SetVolumeRate(obj, 90- 3/2 *i);
		yield;
	}
	ObjSound_Stop(obj);
}



task SpellWarn(numBoss){
	let objText = ObjText_Create();
	if(numBoss==1){ObjText_SetText(objText, "WARNING!![r]SPELL INCOMING!");}
	else if(numBoss==3){ObjText_SetText(objText, "THIS PARTY IS[r]GETTING CRAZY!");}
	else{ObjText_SetText(objText, "PLAYTIME IS[r]OVER!");}
	ObjText_SetFontSize(objText, 40);
	ObjText_SetFontType(objText, "MS Gothic");
	ObjText_SetFontBold(objText, true);
	ObjText_SetFontColorTop(objText, 180, 0, 0);
	ObjText_SetFontColorBottom(objText, 80, 0, 120);
	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;
	}
	let n=40; if(numBoss==3){n=45;}
	loop(n){
	    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, objBoss){
	let objText = ObjText_Create();
	ObjText_SetText(objText, name);
	ObjText_SetFontSize(objText, 20);
	ObjText_SetFontType(objText, "Arial");
	ObjText_SetFontColorTop(objText, 250, 0, 0);
	ObjText_SetFontColorBottom(objText, 250, 0, 0);
	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_SetFontColorTop(objText, 250, 250, 250);
	//ObjText_SetFontColorBottom(objText, 250, 250, 250);
	ObjText_SetMaxWidth(objText, 260);
	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/NonSpellDave.png";
	let i=0;
	while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){
		ObjPrim_SetTexture(objBoss, img);
		if(i%2 ==0){
			ObjSprite2D_SetSourceRect(objBoss, 78, 85, 270, 385); 
			ObjSprite2D_SetDestRect(objBoss, -47, -70, 47, 70);
		}
		else{
			ObjSprite2D_SetSourceRect(objBoss, 78, 580, 270, 890); 
			ObjSprite2D_SetDestRect(objBoss, -47, -70, 47, 70);
		}
		
		i++;
		wait(30);
	}
}


task animSpell(objBoss, num){
    alternative(num)
	case(1){
		let img = GetCurrentScriptDirectory() ~ "../img/SpellDave.png";
		ObjPrim_SetTexture(objBoss, img);
		let i=0;
		while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){
			if(i%2 ==0){
				ObjSprite2D_SetSourceRect(objBoss, 100, 60, 290, 380); 
				ObjSprite2D_SetDestRect(objBoss, -47, -70, 47, 70);
			}
			else{
				ObjSprite2D_SetSourceRect(objBoss, 50, 520, 310, 980); 
				ObjSprite2D_SetDestRect(objBoss, -85, -95, 40, 80);
			}
			i++;
			wait(30);
		}
	}
	case(2){
	    let img = GetCurrentScriptDirectory() ~ "../img/spellMario.png";
		ObjPrim_SetTexture(objBoss, img);
		let i=0;
		while(ObjEnemy_GetInfo(objBoss, INFO_LIFE)>0){
			if(i%2 ==0){
				ObjSprite2D_SetSourceRect(objBoss, 168, 250, 350, 770); 
				ObjSprite2D_SetDestRect(objBoss, -30, -60, 30, 60);
			}
			else{
				ObjSprite2D_SetSourceRect(objBoss, 60+512, 240, 455+512, 790); 
				ObjSprite2D_SetDestRect(objBoss, -58, -65, 58, 60);
			}
			i++;
			wait(30);
		}
	}
	case(3){
	    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);
		}
	}
}
	

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 spiral(x, y, numBranches, angleIni, waitPerBul, direction, maxdiffAng, periodShot, numCycles, pause, speed, accelmin, accelmax, maxspeed, wvev, delay, graphic, enemy, limit){
    let t = 0;
	let angle; let angleShot;
	if(numCycles > 0){
	    let cycles = 0;
	    while(cycles< numCycles){
		    angle = angleIni;
			while(t< periodShot){
			    loop(numBranches){
				    if(ObjEnemy_GetInfo(enemy, INFO_LIFE)<= limit){return;}
					angleShot=angle;
					if(maxdiffAng>0){angleShot+= rand(-maxdiffAng, maxdiffAng);}
				    let obj = CreateShotA1(x, y, speed, angleShot, graphic, 0);
					Obj_SetRenderPriorityI(obj, 70);
					ObjMove_AddPatternA2(obj, delay, NO_CHANGE, NO_CHANGE, rand(accelmin, accelmax), wvev, maxspeed);
					angle+= 360/ numBranches;
				}
				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;}
					angleShot=angle;
					if(maxdiffAng>0){angleShot+= rand(-maxdiffAng, maxdiffAng);}
					let obj = CreateShotA1(x, y, speed, angleShot, graphic, 0);
					Obj_SetRenderPriorityI(obj, 70);
					ObjMove_AddPatternA2(obj, delay, NO_CHANGE, NO_CHANGE, rand(accelmin, accelmax), wvev, maxspeed);
					angle+= 360/ numBranches;
				}
				angle+= direction * waitPerBul;
				t+= waitPerBul;
				wait(waitPerBul);
			}
			wait(pause);
			t=0;
		}
	}
}	

function findAngRad(xdest, x, ydest, y){
    let rad = power((x-xdest)^2 +(y-ydest)^2, 1/2); let angle = atan((ydest-y)/(xdest-x));
	if(xdest<x){angle = angle+180;}
	return [angle, rad];
}


task rotate(obj, ang, time, dir, xcentre, ycentre, warp, an){
    let rad = findAngRad(ObjMove_GetX(obj), xcentre, ObjMove_GetY(obj), ycentre)[1];
	let angle = findAngRad(ObjMove_GetX(obj), xcentre, ObjMove_GetY(obj), ycentre)[0];
	if(warp){ascent(i in 0..time+1){ObjMove_SetDestAtFrame(obj, xcentre + rad* cos(angle+i*dir*ang/time), ycentre +rad*sin(angle+i*dir*ang/time), time);}}
	else{
	    ascent(i in 0..time+1){
			ObjMove_SetPosition(obj, xcentre + rad* cos(angle+i*dir*ang/time), ycentre +rad*sin(angle+i*dir*ang/time));
			if(an){ObjMove_SetAngle(obj, angle+i*dir*ang/time);} yield;
		}
	}
}

task move(xmin, xmax, ymin, ymax, iniDel, time, delay, objBoss, limit){
    wait(iniDel);
    while(ObjEnemy_GetInfo(objBoss, INFO_LIFE) > limit){
	    ObjMove_SetDestAtFrame(objBoss, rand(xmin, xmax), rand(ymin, ymax), time);
		wait(delay);
	}
}


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);
}