//***************************************************************************************************
//	Construction of stage fairies, familiars and other enemy objects.
//
//	Author: Helepolis
//	Version: 1.0
//
//	Explanation:
//	Script is loaded upon stage beginning. Contains only pure obj enemy creation code. 
//	ID is returned for function in order to apply movement or shooting patterns.	
//
//***************************************************************************************************

// enum for type of fairies
let SMALL_BAL_RED = 0;
let SMALL_BAL_BLUE = 1;
let SMALL_AFRO_RED = 2;
let SMALL_AFRO_BLUE = 3;
let SMALL_RED = 4;
let SMALL_BLUE = 5;
let AURA_RED = 6;
let AURA_BLUE = 7;
let LARGE_BAL = 8;
let LARGE_AFRO = 9;
let LARGE_NORM = 10;

// enum for type yin yang balls
let YINYANG_RED = 0;
let YINYANG_GREEN = 1;
let YINYANG_BLUE = 2;
let YINYANG_PURPLE = 3;

// enum for type of familiars
let FAM_RED = 0; 
let FAM_GREEN = 1; 
let FAM_BLUE = 2;
let FAM_PURPLE = 3;
let FAM_YELLOW = 4;
let FAM_WHITE = 5;

#include "script/thdcs/functions/function_loaddata.txt"
#include "script/thdcs/system/itemsystem.txt"
#include "script/thdcs/functions/function_common.txt"
#include "script/thdcs/functions/const_sound.txt"

// Creates a ballerina small fairy
function summonFairy(x,y,life,type) {
	let obj = ObjEnemy_Create(OBJ_ENEMY); 

	ObjEnemy_Regist(obj);
	ObjPrim_SetTexture(obj,enemystage); 
	ObjRender_SetBlendType(obj,BLEND_ALPHA);
	ObjRender_SetAlpha(obj,255);
	Obj_SetRenderPriorityI(obj,30);
	ObjRender_SetScaleXYZ(obj,1,1,0);
	if(type < 6) { ObjSprite2D_SetSourceRect(obj,0,0,32,32); }
	if(type == 6 || type == 7) { ObjSprite2D_SetSourceRect(obj,0,0,64,64); }
	if(type >= 8) { ObjSprite2D_SetSourceRect(obj,0,0,64,64); }
	ObjSprite2D_SetDestCenter(obj);
	ObjEnemy_SetLife(obj,life);
	ObjMove_SetPosition(obj,x,y);
	ObjMove_SetAngle(obj,0);
	ObjMove_SetSpeed(obj,0);

	Obj_SetValue(obj,"dropID",""); 

	fairyHandler(obj,type);
	enemyScoreHandler(obj);
	hitSoundEffect(obj);

	return obj;
}

// Creates a familiar
function summonFamiliar(life,type,masterObj) {
	let obj = ObjEnemy_Create(OBJ_ENEMY); 

	ObjEnemy_Regist(obj);
	ObjPrim_SetTexture(obj,enemystage); 
	ObjRender_SetAlpha(obj,255);
	Obj_SetRenderPriorityI(obj,30);
	ObjRender_SetScaleXYZ(obj,1,1,0);
	ObjSprite2D_SetSourceRect(obj,0,0,0,0);
	ObjSprite2D_SetDestCenter(obj);
	ObjEnemy_SetLife(obj,life);
	ObjMove_SetPosition(obj,ObjMove_GetX(masterObj),ObjMove_GetY(masterObj));
	ObjMove_SetAngle(obj,0);
	ObjMove_SetSpeed(obj,0);
	
	Obj_SetValue(obj,"isFamiliar",true); 
	
	familiarHandler(obj,type,masterObj);
	enemyScoreHandler(obj);
	hitSoundEffect(obj);

	PlaySFX(SFX_OPTION);
	
	return obj;
}

// Creates a ballerina small fairy
function summonBalls(x,y,life,type) {
	let obj = ObjEnemy_Create(OBJ_ENEMY); 

	ObjEnemy_Regist(obj);
	ObjPrim_SetTexture(obj,enemyball); 
	ObjRender_SetAlpha(obj,255);
	Obj_SetRenderPriorityI(obj,30);
	ObjRender_SetScaleXYZ(obj,1,1,0);
	if(type == 0) { ObjSprite2D_SetSourceRect(obj,0,32,32,64); }
	if(type == 1) { ObjSprite2D_SetSourceRect(obj,32,32,64,64); }
	if(type == 2) { ObjSprite2D_SetSourceRect(obj,64,32,96,64); }
	if(type == 3) { ObjSprite2D_SetSourceRect(obj,96,32,128,64); }
	ObjSprite2D_SetDestCenter(obj);
	ObjEnemy_SetLife(obj,life);
	ObjMove_SetPosition(obj,x,y);
	ObjMove_SetAngle(obj,0);
	ObjMove_SetSpeed(obj,0);

	Obj_SetValue(obj,"isHidden",false); 
	Obj_SetValue(obj,"dropID","");

	ballsHandler(obj,type);
	enemyScoreHandler(obj);
	hitSoundEffect(obj);

	return obj;
}

// Creates a ballerina small fairy
function summonBallsEx(x,y,life,type) {
	let obj = ObjEnemy_Create(OBJ_ENEMY); 

	ObjEnemy_Regist(obj);
	ObjPrim_SetTexture(obj,enemyball); 
	ObjRender_SetAlpha(obj,255);
	Obj_SetRenderPriorityI(obj,30);
	ObjRender_SetScaleXYZ(obj,1,1,0);
	if(type == 0) { ObjSprite2D_SetSourceRect(obj,0,32,32,64); }
	if(type == 1) { ObjSprite2D_SetSourceRect(obj,32,32,64,64); }
	if(type == 2) { ObjSprite2D_SetSourceRect(obj,64,32,96,64); }
	if(type == 3) { ObjSprite2D_SetSourceRect(obj,96,32,128,64); }
	ObjSprite2D_SetDestCenter(obj);
	ObjEnemy_SetLife(obj,life);
	ObjMove_SetPosition(obj,x,y);
	ObjMove_SetAngle(obj,0);
	ObjMove_SetSpeed(obj,0);

	enySummonEffectEx(obj,type,x,y);
	
	return obj;
}

// Handles the getting hit sound. Below 10% of max HP it plays the 'almost dead' sound.
task hitSoundEffect(obj) {
    let hpL = ObjEnemy_GetInfo(obj, INFO_LIFE) / 100 * 5;
    while(!Obj_IsDeleted(obj)) {
		if(ObjEnemy_GetInfo(obj,INFO_SHOT_HIT_COUNT) > 0) {
			wait(3.5);
			PlaySFX(SFX_DAMAGE00);
		}
		yield;
 	}
}

// Grant an enemy or boss invulnerability for specified number of frames
task setFairyInvulnerability(obj,t) {
	let lockShotDmgRate = ObjEnemy_GetInfo(obj,INFO_DAMAGE_RATE_SHOT);
	let lockSpellDmgRate = ObjEnemy_GetInfo(obj,INFO_DAMAGE_RATE_SPELL);

	ObjEnemy_SetDamageRate(obj,0,0);

	loop(t) { yield; }

	ObjEnemy_SetDamageRate(obj,lockShotDmgRate,lockSpellDmgRate);
}

task enemyScoreHandler(obj) {
   let oldEnemyHP = truncate(ObjEnemy_GetInfo(obj, INFO_LIFE));

    while(!Obj_IsDeleted(obj)) {
        let newEnemyHP = truncate(ObjEnemy_GetInfo(obj, INFO_LIFE));

        if(oldEnemyHP > newEnemyHP) {
            AddScore((oldEnemyHP - newEnemyHP) * 10);
            oldEnemyHP = newEnemyHP;
        }
        yield;
    }
}

// Handles fairy HP, animation, death
task fairyHandler(obj,type) {
	let animF = 0;
	let animF2 = 0;
	let fairySpeed = 0;
	let fairyDir = 0; 
	let fairyCol = 0;

	// Set collision depending on type. 1-7 = small fairy (8px) and 8,9 = large (16px)
	if(type < 8) { fairyCol = 8; } 
	if(type >= 8) { fairyCol = 16; } 

	while(!Obj_IsDeleted(obj)) {
		if(ObjEnemy_GetInfo(obj,INFO_LIFE) <= 0) {
			PlaySFX(SFX_ENEP00);
			enyExplodeEffect(obj,type);
	
			if(type == 0 || type == 2 || type == 4) { 
				smallTen(ObjMove_GetX(obj),ObjMove_GetY(obj)); 
			}	
			if(type == 1 || type == 3 || type == 5) { 
				smallTen(ObjMove_GetX(obj)+8,ObjMove_GetY(obj)); 
			}	
			if(type == 6) { 
				smallTen(ObjMove_GetX(obj)+4,ObjMove_GetY(obj)-4); 
				smallFever(ObjMove_GetX(obj),ObjMove_GetY(obj)); 
				smallTen(ObjMove_GetX(obj)-4,ObjMove_GetY(obj)-4); 
			}	
			if(type == 7) { 
				smallTen(ObjMove_GetX(obj)+4,ObjMove_GetY(obj)-4); 
				smallFever(ObjMove_GetX(obj),ObjMove_GetY(obj)); 
				smallTen(ObjMove_GetX(obj)-4,ObjMove_GetY(obj)-4); 
			}	
			if(type == 8 || type == 9 || type == 10) { 
				smallTen(ObjMove_GetX(obj)-4,ObjMove_GetY(obj)-4); 	
				smallFever(ObjMove_GetX(obj)-4,ObjMove_GetY(obj)+4);
				smallFever(ObjMove_GetX(obj)-8,ObjMove_GetY(obj)+8);
				smallFever(ObjMove_GetX(obj)+4,ObjMove_GetY(obj)+4);	
				smallTen(ObjMove_GetX(obj)+4,ObjMove_GetY(obj)-4); 					
			}

			if(Obj_IsValueExists(obj,"dropID")) { 
				if(Obj_GetValue(obj,"dropID") == "extend") { plyExtend(ObjMove_GetX(obj),ObjMove_GetY(obj)-8); }
				if(Obj_GetValue(obj,"dropID") == "spell") { plySpell(ObjMove_GetX(obj),ObjMove_GetY(obj)-8); }
				if(Obj_GetValue(obj,"dropID") == "fever") { smallFever(ObjMove_GetX(obj),ObjMove_GetY(obj)-8); }
			}
			yield;
			Obj_Delete(obj);
			break;
		}
		
		// leave field == delete
		if(ObjMove_GetX(obj) < GetClipMinX-17 || ObjMove_GetX(obj) > GetClipMaxX+17 || ObjMove_GetY(obj) < GetClipMinY-17 || ObjMove_GetY(obj) > GetClipMaxY+17) { 
			Obj_Delete(obj);
			break;
		}
	
		// collision
		ObjEnemy_SetIntersectionCircleToShot(obj,ObjMove_GetX(obj),ObjMove_GetY(obj),fairyCol);
		ObjEnemy_SetIntersectionCircleToPlayer(obj,ObjMove_GetX(obj),ObjMove_GetY(obj),fairyCol);
		
		// update info
		fairySpeed = ObjMove_GetSpeed(obj);
		fairyDir = ObjMove_GetAngle(obj);
		
		// RED FAIRY
		if(type == 0 || type == 2 || type == 4) {
			if(fairySpeed == 0) { 
				ObjRender_SetAngleXYZ(obj,0,0,0);					
				if(animF < 10) { ObjSprite2D_SetSourceRect(obj,0,0,32,32); }
				if(animF >= 10 && animF < 20) { ObjSprite2D_SetSourceRect(obj,32,0,64,32); }
				if(animF >= 20 && animF < 30) { ObjSprite2D_SetSourceRect(obj,64,0,96,32); }
				if(animF >= 30) { ObjSprite2D_SetSourceRect(obj,96,0,128,32); }
				animF2 = 0;
			}
			else if(cos(fairyDir) > 0) { 
				ObjRender_SetAngleXYZ(obj,0,0,0);					
				if(animF2 < 10) { ObjSprite2D_SetSourceRect(obj,128,0,160,32); }
				if(animF2 >= 10 && animF2 < 20) { ObjSprite2D_SetSourceRect(obj,160,0,192,32); }		
				if(animF2 >= 20 && animF2 < 30) { ObjSprite2D_SetSourceRect(obj,192,0,224,32); }								
				if(animF2 >= 30) { ObjSprite2D_SetSourceRect(obj,224,0,256,32); }
				if(animF2 > 40) { animF2 = 0; } 
			}
			else if(cos(fairyDir) < 0) { 
				ObjRender_SetAngleXYZ(obj,0,180,0);					
				if(animF2 < 10) { ObjSprite2D_SetSourceRect(obj,128,0,160,32); }
				if(animF2 >= 10 && animF2 < 20) { ObjSprite2D_SetSourceRect(obj,160,0,192,32); }		
				if(animF2 >= 20 && animF2 < 30) { ObjSprite2D_SetSourceRect(obj,192,0,224,32); }								
				if(animF2 >= 30) { ObjSprite2D_SetSourceRect(obj,224,0,256,32); }
				if(animF2 > 40) { animF2 = 0; } 
			}		
		}
		// BLUE FAIRY
		if(type == 1 || type == 3 || type == 5) { 
			if(fairySpeed == 0) { 
				ObjRender_SetAngleXYZ(obj,0,0,0);					
				if(animF < 10) { ObjSprite2D_SetSourceRect(obj,0,32,32,64); }
				if(animF >= 10 && animF < 20) { ObjSprite2D_SetSourceRect(obj,32,32,64,64); }
				if(animF >= 20 && animF < 30) { ObjSprite2D_SetSourceRect(obj,64,32,96,64); }
				if(animF >= 30) { ObjSprite2D_SetSourceRect(obj,96,32,128,64); }
				animF2 = 0;
			}
			else if(cos(fairyDir) > 0) { 
				ObjRender_SetAngleXYZ(obj,0,0,0);					
				if(animF2 < 10) { ObjSprite2D_SetSourceRect(obj,128,32,160,64); }
				if(animF2 >= 10 && animF2 < 20) { ObjSprite2D_SetSourceRect(obj,160,32,192,64); }		
				if(animF2 >= 20 && animF2 < 30) { ObjSprite2D_SetSourceRect(obj,192,32,224,64); }								
				if(animF2 >= 30) { ObjSprite2D_SetSourceRect(obj,224,32,256,64); }
				if(animF2 > 40) { animF2 = 0; } 
			}
			else if(cos(fairyDir) < 0) { 
				ObjRender_SetAngleXYZ(obj,0,180,0);					
				if(animF2 < 10) { ObjSprite2D_SetSourceRect(obj,128,32,160,64); }
				if(animF2 >= 10 && animF2 < 20) { ObjSprite2D_SetSourceRect(obj,160,32,192,64); }		
				if(animF2 >= 20 && animF2 < 30) { ObjSprite2D_SetSourceRect(obj,192,32,224,64); }								
				if(animF2 >= 30) { ObjSprite2D_SetSourceRect(obj,224,32,256,64); }
				if(animF2 > 40) { animF2 = 0; } 
			}
		}
		// AURA RED
		if(type == 6) {	
			ObjSprite2D_SetSourceRect(obj,256,0,320,64);					
		}
		// AURA BLUE
		if(type == 7) {
			ObjSprite2D_SetSourceRect(obj,320,0,384,64);	
		}
		// LARGE FAIRY 
		if(type >= 8) { 
			if(fairySpeed == 0) { 
				ObjRender_SetAngleXYZ(obj,0,0,0);					
				if(animF < 10) { ObjSprite2D_SetSourceRect(obj,0,64,64,128); }
				if(animF >= 10 && animF < 20) { ObjSprite2D_SetSourceRect(obj,64,64,128,128); }
				if(animF >= 30) { ObjSprite2D_SetSourceRect(obj,128,64,192,128); }
				animF2 = 0;
			}
			else if(cos(fairyDir) > 0) { 
				ObjRender_SetAngleXYZ(obj,0,0,0);					
				if(animF2 < 10) { ObjSprite2D_SetSourceRect(obj,192,64,256,128); }							
				if(animF2 >= 10) { ObjSprite2D_SetSourceRect(obj,256,64,320,128); }
			}
			else if(cos(fairyDir) < 0) { 
				ObjRender_SetAngleXYZ(obj,0,180,0);					
				if(animF2 < 10) { ObjSprite2D_SetSourceRect(obj,192,64,256,128); }							
				if(animF2 >= 10) { ObjSprite2D_SetSourceRect(obj,256,64,320,128); }
			}
		}
		animF+=1.5;
		animF2+=1.5; 
		if(animF > 40) { animF = 0; } 
		yield;
	}
}

// Handles fairy HP, animation, death
task familiarHandler(obj,type,masterobj) {
	let animF = 0;
	let famSpeed = 0;
	let famDir = 0; 
	let famSpin = 0;
	let famScale = 0.26;
	let famHide = false;
	let famFocusDelay = 0;
	let masterHasLeftField = false;
	
	// Familiar texture essentials
	ObjPrim_SetTexture(obj,famtex); 
	ObjRender_SetBlendType(obj,BLEND_ADD_ARGB);
	ObjRender_SetAlpha(obj,255);
	Obj_SetRenderPriorityI(obj,31);
	ObjRender_SetScaleXYZ(obj,famScale,famScale,0);
	ObjSprite2D_SetSourceRect(obj,0,0,128,128);
	if(type == 0) { ObjRender_SetColor(obj,255,32,32); } 	// RED
	if(type == 1) { ObjRender_SetColor(obj,32,255,32); } 	// GREEN
	if(type == 2) { ObjRender_SetColor(obj,32,32,255); } 	// BLUE
	if(type == 3) { ObjRender_SetColor(obj,255,32,255); } 	// PURPLE	
	if(type == 4) { ObjRender_SetColor(obj,255,255,32); } 	// YELLOW
	if(type == 5) { ObjRender_SetColor(obj,255,255,255); } // WHITE
	ObjSprite2D_SetDestCenter(obj);

	// Summon handler for the glow
	familiarGlowHandler(obj,type);
	
	// As long as the fairy is alive, handle the collision, exit deletion, animation
	while(!Obj_IsDeleted(obj)) {
		// If master (fairy user) is killed.
		if(Obj_IsDeleted(masterobj)) { 
			
			if(!masterHasLeftField) {
				famExplodeEffect(obj,type);
				let checkBullets = GetShotIdInCircleA2(ObjMove_GetX(obj),ObjMove_GetY(obj),32,TARGET_ENEMY);
				if(length(checkBullets) > 0) { 
					smallFever(ObjMove_GetX(obj)-2,ObjMove_GetY(obj)-2);
					smallTen(ObjMove_GetX(obj)+2,ObjMove_GetY(obj));
				}
				DeleteShotInCircle(TYPE_SHOT,TYPE_IMMEDIATE,ObjMove_GetX(obj),ObjMove_GetY(obj),64);
				Obj_Delete(obj);
				break;
			}
			else if(masterHasLeftField) {
				famExplodeEffect(obj,type); 
				Obj_Delete(obj); 
				break; 
			}
		}
		
		// If life is depleted, delete the familiar
		if(ObjEnemy_GetInfo(obj,INFO_LIFE) <= 0) {
			PlaySFX(SFX_ENEP00);
			famExplodeEffect(obj,type);
			Obj_Delete(obj); 
			break;
		}
		
		// If master (fairy user) has left screen, tag the familiar for non removal and let it live until it leaves screen (see isDeleted)
		if(ObjMove_GetX(masterobj) < GetClipMinX-16 || ObjMove_GetX(masterobj) > GetClipMaxX+16 || ObjMove_GetY(masterobj) < GetClipMinY-16 || ObjMove_GetY(masterobj) > GetClipMaxY+16) {
			masterHasLeftField = true;
		}

		// leave field == delete
		if(ObjMove_GetX(obj) < GetClipMinX-17 || ObjMove_GetX(obj) > GetClipMaxX+17 || ObjMove_GetY(obj) < GetClipMinY-17 || ObjMove_GetY(obj) > GetClipMaxY+17) { 
			Obj_Delete(obj); 
			break;
		}		
	
		if(GetVirtualKeyState(VK_SLOWMOVE) == KEY_PUSH || GetVirtualKeyState(VK_SLOWMOVE) == KEY_HOLD) { 
			if(famFocusDelay < 15 && !famHide) { famFocusDelay++; }
			if(famFocusDelay == 14) { PlaySFX(SFX_OPHIDE); } 
			if(famFocusDelay == 15) { 
				famHide = true;
				if(famScale < 0.50) { famScale+=0.04; } 
				ObjRender_SetBlendType(obj,BLEND_ADD_ARGB);
				if(type == 0) { ObjRender_SetColor(obj,255,32,32); } 	// RED
				if(type == 1) { ObjRender_SetColor(obj,32,255,32); } 	// GREEN
				if(type == 2) { ObjRender_SetColor(obj,32,32,255); } 	// BLUE
				if(type == 3) { ObjRender_SetColor(obj,255,32,255); } 	// PURPLE	
				if(type == 4) { ObjRender_SetColor(obj,255,255,32); } 	// YELLOW
				if(type == 5) { ObjRender_SetColor(obj,255,255,255); } 	// WHITE
			} 
		}
		else { 
			if(famFocusDelay > 0 && famHide) { famFocusDelay--; } 
			if(famFocusDelay == 14) { PlaySFX(SFX_OPSHOW); } 
			if(famFocusDelay == 0) { 
				famHide = false;
				if(famScale > 0.26) { famScale-=0.04; } 
				ObjRender_SetBlendType(obj,BLEND_ADD_ARGB);
				ObjEnemy_SetIntersectionCircleToShot(obj,ObjMove_GetX(obj),ObjMove_GetY(obj),16);
				ObjEnemy_SetIntersectionCircleToPlayer(obj,ObjMove_GetX(obj),ObjMove_GetY(obj),16);					
			}
			famFocusDelay = 0;
		} 
		
		// update main info
		famSpeed = ObjMove_GetSpeed(obj);
		famDir = ObjMove_GetAngle(obj);
		ObjRender_SetPosition(obj,ObjMove_GetX(obj),ObjMove_GetY(obj),0);
				
		// Other updates
		ObjRender_SetScaleXYZ(obj,famScale,famScale,0);	
		ObjRender_SetAngleZ(obj,-famSpin);
		famSpin+=1; 
				
		yield;
	}
	Obj_DeleteValue(obj,"isFamiliar");
	Obj_Delete(obj);		
}

// Spawns the glow for the familiar every few frames
task familiarGlowHandler(obj,type) {
	while(!Obj_IsDeleted(obj)) {
		familiarGlow(obj,type);
		wait(3);
	}
} 

// Familiar glow 
task familiarGlow(obj,type) {
	let obj3 = ObjPrim_Create(OBJ_SPRITE_2D);
	let glowScale = 1.2;
	let glowAlpha = 204;
	let randGlow = rand_int(0,9);
	
	ObjPrim_SetTexture(obj3,famglowtex); 
	ObjRender_SetBlendType(obj3,BLEND_ADD_ARGB);
	ObjRender_SetAlpha(obj3,glowAlpha);
	Obj_SetRenderPriorityI(obj3,31);
	ObjRender_SetScaleXYZ(obj3,glowScale,glowScale,0);
	ObjRender_SetColor(obj3,255,255,255); 
	
	// Animation for the familiar glow					
	if(randGlow == 0) { ObjSprite2D_SetSourceRect(obj3,0,0,32,32); }
	if(randGlow == 1) { ObjSprite2D_SetSourceRect(obj3,32,0,64,32); }
	if(randGlow == 2) { ObjSprite2D_SetSourceRect(obj3,64,0,96,32); }
	if(randGlow == 3) { ObjSprite2D_SetSourceRect(obj3,96,0,128,32); }
	if(randGlow == 4) { ObjSprite2D_SetSourceRect(obj3,128,0,160,32); }
	if(randGlow == 5) { ObjSprite2D_SetSourceRect(obj3,160,0,192,32); }
	if(randGlow == 6) { ObjSprite2D_SetSourceRect(obj3,192,0,224,32); }
	if(randGlow == 7) { ObjSprite2D_SetSourceRect(obj3,224,0,256,32); }
	ObjSprite2D_SetDestCenter(obj3);
	ObjRender_SetPosition(obj3,ObjMove_GetX(obj),ObjMove_GetY(obj),0);
	
	while(!Obj_IsDeleted(obj)) {

		ObjRender_SetScaleXYZ(obj3,glowScale,glowScale,0);
		ObjRender_SetAlpha(obj3,glowAlpha);
		
		glowScale-=0.04;
		
		if(glowScale <= 0) { Obj_Delete(obj3); break; } 

		if(GetVirtualKeyState(VK_SLOWMOVE) == KEY_PUSH || GetVirtualKeyState(VK_SLOWMOVE) == KEY_HOLD) { 
			glowAlpha = 155;
			if(type == 0) { ObjRender_SetColor(obj3,64,0,0); } 		// RED
			if(type == 1) { ObjRender_SetColor(obj3,0,64,0); } 		// GREEN
			if(type == 2) { ObjRender_SetColor(obj3,0,0,64); } 		// BLUE
			if(type == 3) { ObjRender_SetColor(obj3,64,0,64); } 	// PURPLE	
			if(type == 4) { ObjRender_SetColor(obj3,64,64,0); } 	// YELLOW
			if(type == 5) { ObjRender_SetColor(obj3,64,64,64); } 	// WHITE			
		}
		else { 
			ObjRender_SetColor(obj3,255,255,255); 
			glowAlpha = 204;
		}
		yield;
	}
	Obj_Delete(obj3);
} 

// Handles fairy HP, animation, death
task ballsHandler(obj,type) {
	let obj2 = ObjPrim_Create(OBJ_SPRITE_2D);
	
	let animF = 0;
	let animF2 = 0;
	let ballsSpeed = 0;
	let ballsDir = 0; 
	let ballsCol = 16;
	
	// Balls texture essentials (spinning material)
	ObjPrim_SetTexture(obj2,enemyball); 
	ObjRender_SetBlendType(obj2,BLEND_ADD_ARGB);
	ObjRender_SetAlpha(obj2,255);
	Obj_SetRenderPriorityI(obj2,31);
	ObjRender_SetScaleXYZ(obj2,1,1,0);
	ObjSprite2D_SetSourceRect(obj2,0,0,32,32);
	if(type == 0) { ObjSprite2D_SetSourceRect(obj2,0,0,32,32); }
	if(type == 1) { ObjSprite2D_SetSourceRect(obj2,32,0,64,32); }
	if(type == 2) { ObjSprite2D_SetSourceRect(obj2,64,0,96,32); }
	if(type == 3) { ObjSprite2D_SetSourceRect(obj2,96,0,128,32); }
	ObjSprite2D_SetDestCenter(obj2);

	// As long as the fairy is alive, handle the collision, exit deletion, animation
	while(!Obj_IsDeleted(obj)) {

		// If life is depleted, delete the familiar
		if(ObjEnemy_GetInfo(obj,INFO_LIFE) <= 0) {
			PlaySFX(SFX_ENEP00);
			famExplodeEffect(obj,type);
		
			smallTen(ObjMove_GetX(obj),ObjMove_GetY(obj)); 
			
			if(Obj_IsValueExists(obj,"dropID")) { 
				if(Obj_GetValue(obj,"dropID") == "fever") { smallFever(ObjMove_GetX(obj),ObjMove_GetY(obj)-8); }
			}
			
			Obj_Delete(obj); Obj_Delete(obj2);	
			break;
		}
	
		// If master (fairy user) is gone, delete familiar
		if(Obj_IsDeleted(obj)) { 
			famExplodeEffect(obj,type);
			Obj_Delete(obj); Obj_Delete(obj2);	
			break;
			
		}

		// leave field == delete
		if(ObjMove_GetX(obj) < GetClipMinX-16 || ObjMove_GetX(obj) > GetClipMaxX+16 || ObjMove_GetY(obj) < GetClipMinY-16 || ObjMove_GetY(obj) > GetClipMaxY+16) { 
			Obj_Delete(obj); Obj_Delete(obj2);	
			break;
		}		
		
		if(!Obj_GetValue(obj,"isHidden")) {
			// collision
			ObjEnemy_SetIntersectionCircleToShot(obj,ObjMove_GetX(obj),ObjMove_GetY(obj),ballsCol);
			ObjEnemy_SetIntersectionCircleToPlayer(obj,ObjMove_GetX(obj),ObjMove_GetY(obj),ballsCol);
			ObjRender_SetColor(obj,255,255,255);
			ObjRender_SetColor(obj2,255,255,255);
		}
		else { 
			ObjRender_SetColor(obj,92,92,92);
			ObjRender_SetColor(obj2,64,64,64);
		}
		
		// update info
		ballsSpeed = ObjMove_GetSpeed(obj);
		ballsDir = ObjMove_GetAngle(obj);	
		
		ObjMove_SetPosition(obj2,ObjMove_GetX(obj),ObjMove_GetY(obj));
		ObjRender_SetPosition(obj2,ObjMove_GetX(obj),ObjMove_GetY(obj),0);			
		
		ObjRender_SetAngleZ(obj2,animF);		
		animF-=10;
		yield;		
	}
	Obj_DeleteValue(obj,"isHidden");
	Obj_Delete(obj);		
}

// Fairy / enemy / etc secondary effect (small to large) 
task enySummonEffectEx(objBall,type,x,y) {
	let obj = ObjPrim_Create(OBJ_SPRITE_2D);
	let obj2 = ObjPrim_Create(OBJ_SPRITE_2D);
	
	let dScale = 0.01;
	let dAlpha = 0.01;
	let scale = 0.2;
	let spin = 0;
	let alphaValue = 105;

	ObjPrim_SetTexture(obj,enemystage); 
	ObjPrim_SetTexture(obj2,enemystage); 
	ObjRender_SetBlendType(obj,BLEND_ALPHA);
	ObjRender_SetBlendType(obj2,BLEND_ALPHA);
	ObjRender_SetAlpha(obj,255);
	ObjRender_SetAlpha(obj2,255);
	Obj_SetRenderPriorityI(obj,60);
	Obj_SetRenderPriorityI(obj2,60);
	ObjRender_SetScaleXYZ(obj,scale,scale,0);
	ObjRender_SetScaleXYZ(obj2,scale,scale,0);
	ObjSprite2D_SetSourceRect(obj,0,0,32,32);
	ObjSprite2D_SetSourceRect(obj2,0,0,32,32);
	if(type == 0) { ObjSprite2D_SetSourceRect(obj,128,256,160,288); ObjSprite2D_SetSourceRect(obj2,128,288,160,320); }
	if(type == 1) { ObjSprite2D_SetSourceRect(obj,160,256,192,288); ObjSprite2D_SetSourceRect(obj2,160,288,192,320); }
	if(type == 2) { ObjSprite2D_SetSourceRect(obj,192,256,224,288); ObjSprite2D_SetSourceRect(obj2,192,288,224,320); }
	if(type == 3) { ObjSprite2D_SetSourceRect(obj,224,256,256,288); ObjSprite2D_SetSourceRect(obj2,224,288,256,320); }	
	ObjSprite2D_SetDestCenter(obj);
	ObjSprite2D_SetDestCenter(obj2);
	ObjRender_SetPosition(obj,x,y,0);
	ObjRender_SetPosition(obj2,x,y,0);
	
	while(scale < 1) {
		ObjRender_SetPosition(obj,x,y,0);
		ObjRender_SetPosition(obj2,x,y,0);		
		
		ObjRender_SetScaleXYZ(obj,scale,scale,1);
		ObjRender_SetScaleXYZ(obj2,scale,scale,1);
		
		if(type < 4) { 
			ObjRender_SetAngleZ(obj2,spin);
			spin-=10;
		}
		
		scale += dScale;
		alphaValue += dAlpha;
		
		yield;
	}
	ballsHandler(objBall,type);
	Obj_Delete(obj);
	Obj_Delete(obj2);
}