/*****************************/
/* Inside The Machine - MKS  */
/*****************************/

#include "eFish.h"
#include "../WorldManager.h"

eVSlime::eVSlime()
{
	real = true;
	stat = false;
	toDelete = false;
	sensV = true;
	//distx = FIX(distx);
	distanceY = 0;
	timer = 0;
	isJumping = false;
	vely = velx = 0;
	maxvely = 512;
	dontMoveTime = -1;
	life = 20;	
	timeKill = 0;
	alpha = 31;
	hit = false;             //Coup
	
	//Parametrage des hitboxes
	rect.x1 = 3;
	rect.y1 = 12;
	rect.x2 = 28;
	rect.y2 = 31;
	
	hitbox.xUp = 16, hitbox.yUp = 12;
	hitbox.xDown = 12, hitbox.yDown = 31;
	hitbox.xLeft = 3, hitbox.yLeft = 16;
	hitbox.xRight = 28, hitbox.yRight = 16;
	
	//Paramétrage des états
	isFalling = false;
	isOnTheFloor = false;
	isOnThePente = false;
	isWasOnThePente = false;
	isDontMove = false;
}
   	
eVSlime::~eVSlime()
{
}

void eVSlime::Load()
{
   //Chargement du spritesheet
   ulSetTransparentColor(RGB15(31, 0, 31));
	spr.assign(worldMan->resMan->LoadImage("efs:/Ennemy_VSlime.png", UL_IN_VRAM, UL_PF_PAL4));
	sprFx2.assign(worldMan->resMan->LoadImage("efs:/FX_Impact_2.png", UL_IN_VRAM, UL_PF_PAL2));
	ulDisableTransparentColor();
		
	//Paramètrage des animations
	spr.setFrameWH(32, 32);
	spr.addAnim(0, 0, 3, 7);     //Anim : Idle
	spr.animLoop(0);
	
	sprFx2.scale(32,32);
	sprFx2.setAlpha(true, 20);
}
   
void eVSlime::Draw(int layer)
{
   //On affiche le perso
   if(actif && layer == 0)
   {
      //On affiche le sprite
   	spr.setXY(x_screen, y_screen);
   	spr.setAlpha(true, alpha);
   	spr.play();
   	if(alpha > 0)
   		spr.draw();
   	if(hit)
      {
	      sprFx2.setXY(x_screen, y_screen+8);
	      sprFx2.draw();
		}
		if(dontMoveTime == 10)
			hit = false;
	}	
}
   
void eVSlime::Update()
{
   //Calcul de la position écran de l'entité
   x_screen = UNFIX(x - FIX(worldMan->curLevel->map->scrollX));
	y_screen = UNFIX(y - FIX(worldMan->curLevel->map->scrollY));
	
	//On vérifie si chuck est actif
   if(x_screen < -32 || x_screen > (256+32) || y_screen < -32 || y_screen > (192+32))
   	actif = false;
   else
   	actif = true;
   
   if(actif)
   {  
      //On fait baiser le dont move time
      if(dontMoveTime > -1)
		{
			//On arrête le mouvement du perso
			dontMoveTime--;
		}
      if(life > 0)
      {		
	      //On fait sauter le slime a intervalle régulier
	      if(isJumping == false)
	      	timer++;
	      
	      //Si le timer == 120 on démarre le sauf
	      if(timer == 120)
	      {
	         timer = 0;
	         isJumping = true;
	      } 
	   	//Calcul du saut
	   	if(isJumping == true)
	   	{
	   	   vely = -vitesse;
	 			isOnTheFloor = false;
	   	   distanceY += vitesse;
	   	   if(distanceY >= hy)
	   	   {
	   	      isJumping = false;
	   	      distanceY = 0;
	   	   }
			}			  	   	
	 	}
		else
		{
			timeKill++;
			if(timeKill > 60)
				alpha--;
			if(timeKill > 90)
				toDelete = true;   
		}			  	
		
		//On vérifie les collisions
      CheckCollisions();	   
	}
}

   
void eVSlime::CheckInteractions()
{
	//Collisions avec le personnage (on enlève de la vie)  if(worldMan->hero->dontMoveTime == -1)		  
	if(life > 0 && RectCollision(UNFIX(x), UNFIX(y), &rect, UNFIX(worldMan->hero->x), UNFIX(worldMan->hero->y), &worldMan->hero->rect) )
	{
	   if(worldMan->hero->dontHitTime == -1)
	   {
			worldMan->hero->dontHitTime = 30;
			worldMan->hero->dontMoveTime = 3;
			worldMan->hero->life -= 5;
		}			 
	}
	
	//Collision avec les fireballs du héros
	for(int k = 0; k < BULLETMAX; k++)
	{
	   if(worldMan->hero->bullets[k].actif == true)
	   {
	   	if(RectCollision(worldMan->hero->bullets[k].x, worldMan->hero->bullets[k].y, &worldMan->hero->bullets[k].rect, UNFIX(x), UNFIX(y), &rect) )
	   	{
		   	if(dontMoveTime == -1)
				{
					dontMoveTime = 20;
					//On fait perdre de la vie aussi
					life -= 5;
					hit = true;
					worldMan->hero->bullets[k].actif = false;
				}
	      }						  
	   }   
	} 
}   

void eVSlime::CheckCollisions()
{
	//1ère Etape : Prédiction de collisions avec les bords de la map
	if(x > FIX((worldMan->curLevel->lx*16) - 32))
	{
		x = FIX((worldMan->curLevel->lx*16) - 32);
	}		
	if(y < 0)
		y = 0;
	if(y > FIX((worldMan->curLevel->ly*16)) )
		y = FIX(worldMan->curLevel->ly*16);
	
	//SUB : On vérifie si il faut aprtir dans l'autre sens a cause du vide
	/*if(isOnTheFloor && uGetMapPixel(worldMar->curLevel->map_coll, UNFIX(x), UNFIX(y), NULL, NULL, NULL) == 1)
		ulDebug("vide\n");*/
	
	//2ème Etape : Prediction de collisions avec les pentes
	bool isPenteFound = false;
	isWasOnThePente = isOnThePente;
	isOnThePente = false;
	if(vely > 0)
	{
		//On déclare des variables pour le point de test des collisions
		int testx = UNFIX(x + velx) + hitbox.xDown;
		int testy = UNFIX(y + vely) + hitbox.yDown-1;
		
		//On récupère le tile qui comprends le point de test
		u16 tile = 0;
		
		//On déclare une structure temporaire
		PenteInfo val;
		
		//On teste si le prochain pixel est bleu (le pixel juste en face)
		if(uGetMapPixel(worldMan->curLevel->map_coll, testx, testy, &tile, NULL, NULL) == 3)
		{
			val.v = 0;
			val.v = worldMan->pentes[tile].v;
			//On vérifie si le tile est une pente (attention optimisation, le passage de structure par copie)
			if(val.v != 0)
				isPenteFound = true;
			
			//Si on a trouvé une pente
			if(isPenteFound)
			{
			   //Définit qu'on est sur une pente
			   isOnThePente = true;
				//On récupère la position x du personnage sur le tile (attention modulo...)
				u8 diff = testx%16;				
				//On déplace le personnage a la position maxy de la pente
				int maxy = worldMan->pentes[tile].hauteur[diff];
				//On calcule les coordonnées en haut du tile en y 
				int tpy = (testy>>4)<<4;
				y = FIX(tpy-hitbox.yDown+maxy);
				x = x + velx;
				vely = 256;
				isOnTheFloor = true;
				isFalling = false;			
			}		
		}
		else if(uGetMapPixel(worldMan->curLevel->map_coll, testx, testy-1, &tile, NULL, NULL) == 3)
		{
		   //On fait un 2ème test sur le pixel juste au dessus
		   testy = testy-1;
			//On déclare une structure temporaire
			val.v = 0;
			val.v = worldMan->pentes[tile].v;
			//On vérifie si le tile est une pente (attention optimisation, le passage de structure par copie)
			if(val.v != 0)
				isPenteFound = true;
			
			//Si on a trouvé une pente
			if(isPenteFound)
			{
			   //Définit qu'on est sur une pente
			   isOnThePente = true;
				//On récupère la position x du personnage sur le tile (attention modulo...)
				u8 diff = testx%16;
				//On déplace le personnage a la position maxy de la pente
				int maxy = worldMan->pentes[tile].hauteur[diff];
				//On calcule les coordonnées en haut du tile en y 
				int tpy = (testy>>4)<<4;
				y = FIX(tpy-hitbox.yDown+maxy);
				x = x + velx;
				vely = 256;
				isOnTheFloor = true;
				isFalling = false;			
			}	
		}
		else if(uGetMapPixel(worldMan->curLevel->map_coll, testx + 1, testy, &tile, NULL, NULL) == 3)
		{
		   //On fait un 2ème test sur le pixel juste à côté
		   testy = testy;
		   testx = testx + 1;
			//On déclare une structure temporaire
			val.v = 0;
			val.v = worldMan->pentes[tile].v;
			//On vérifie si le tile est une pente (attention optimisation, le passage de structure par copie)
			if(val.v != 0)
				isPenteFound = true;
			
			//Si on a trouvé une pente
			if(isPenteFound)
			{
			   //Définit qu'on est sur une pente
			   isOnThePente = true;
				//On récupère la position x du personnage sur le tile (attention modulo...)
				u8 diff = testx%16;
				//On déplace le personnage a la position maxy de la pente
				int maxy = worldMan->pentes[tile].hauteur[diff];
				//On calcule les coordonnées en haut du tile en y 
				int tpy = (testy>>4)<<4;
				y = FIX(tpy-hitbox.yDown+maxy);
				x = x + velx;
				vely = 256;
				isOnTheFloor = true;
				isFalling = false;			
			}	
		}
		else if(uGetMapPixel(worldMan->curLevel->map_coll, testx - 1, testy, &tile, NULL, NULL) == 3)
		{
		   //On fait un 2ème test sur le pixel juste à côté
		   testy = testy;
		   testx = testx - 1;
			//On déclare une structure temporaire
			val.v = 0;
			val.v = worldMan->pentes[tile].v;
			//On vérifie si le tile est une pente (attention optimisation, le passage de structure par copie)
			if(val.v != 0)
				isPenteFound = true;
			
			//Si on a trouvé une pente
			if(isPenteFound)
			{
			   //Définit qu'on est sur une pente
			   isOnThePente = true;
				//On récupère la position x du personnage sur le tile (attention modulo...)
				u8 diff = testx%16;
				//On déplace le personnage a la position maxy de la pente
				int maxy = worldMan->pentes[tile].hauteur[diff];
				//On calcule les coordonnées en haut du tile en y 
				int tpy = (testy>>4)<<4;
				y = FIX(tpy-hitbox.yDown+maxy);
				x = x + velx;
				vely = 256;
				isOnTheFloor = true;
				isFalling = false;			
			}	
		}
	}
	   
	//3ème Etape : Prédiction de collisions avec les côtés
	if(isPenteFound == false)
	{
		if(velx > 0)
		{
			if(uGetMapPixel(worldMan->curLevel->map_coll, UNFIX(x + velx) + hitbox.xRight, UNFIX(y) + hitbox.yRight, NULL, NULL, NULL) == 2)
			{
				x = oldx;
				sensH = !sensH;
			}			
			else
				x += velx; 
		}   
		if(velx < 0)
		{
			if(uGetMapPixel(worldMan->curLevel->map_coll, UNFIX(x + velx) + hitbox.xLeft, UNFIX(y) + hitbox.yLeft, NULL, NULL, NULL) == 2)
			{
				x = oldx;
				sensH = !sensH;
			}
			else
				x += velx; 
		}
		
		//4ème Etape : Prédiction de collisions avec le sol et le plafond
		if(vely < 0)
		{
		   if(uGetMapPixel(worldMan->curLevel->map_coll, UNFIX(x) + hitbox.xUp, UNFIX(y + vely) + hitbox.yUp, NULL, NULL, NULL) == 2)
		   {
				//y = oldy;
				vely = 0;
				isFalling = true;
				isOnTheFloor = false;
			}		
			else
			{
			   isFalling = true;
			   isOnTheFloor = false;
				y += vely;
				vely += worldMan->curLevel->vgy;
				if(vely >=maxvely)
					vely = maxvely;
			}		
		}
		else
		{
		   if(uGetMapPixel(worldMan->curLevel->map_coll, UNFIX(x) + hitbox.xDown, UNFIX(y + vely) + hitbox.yDown, NULL, NULL, NULL) == 2)
		   {
				//y = oldy;
				vely = 256;
				isFalling = false;
				isOnTheFloor = true;
				//On teste le pixel juste au dessus
				 
			}	
			else
			{
			   if(isWasOnThePente)
			   	isFalling = false;
			   else
			   	isFalling = true;
			   isOnTheFloor = false;
				y += vely;
				vely += worldMan->curLevel->vgy;
				if(vely >= maxvely)
					vely = maxvely;
			}
		}
	} 
}

void eVSlime::Destroy()
{

}
