// Header File
// Created 6/20/2007; 11:36:13 AM

static inline void LoadConfig(FATCONFIG *fc)
{
  FILE *fsPtr;
 	SYM_ENTRY *file;
 	char stnl = 0;
  
  if ((file = GetSymEntry("doomcfg")))
 	{
 	 if (file->flags.bits.archived == 1)
 	 EM_moveSymFromExtMem (SYMSTR("doomcfg"),HS_NULL);
 	}
 	else 
 	{
 		return;
 	}
 	
 	if (!(fsPtr = fopen("doomcfg","r")))
 	PostGameCleanup(fc,ERR_UNKNOWN);
 	
 	fread(&Controls,sizeof(ControlStruct),1,fsPtr);
 	fread(&gg.Auto_Aim,sizeof(char),1,fsPtr);
 	
 	fclose(fsPtr);
 	
try_archive:
 stnl++;
 if (EM_findEmptySlot(sizeof(SymFind(SYMSTR ("doomcfg")))))
 {
 	EM_moveSymToExtMem (SYMSTR("doomcfg"),HS_NULL);
 }
 else
 {
	UnlockTexFiles();
	EM_GC(FALSE);
	LoadTextures(fc);
	FixSpriteTex(fc);
	if (stnl >= 10) PostGameCleanup(fc,ERR_UNKNOWN);
	goto try_archive;
 }
 
}

static inline void SaveConfig(FATCONFIG *fc)
{
	FILE *fsPtr;
 	SYM_ENTRY *file;
 	char stnl = 0;
 	
  if ((file = GetSymEntry("doomcfg")))
 	{
 	 if (file->flags.bits.archived == 1)
 	 EM_moveSymFromExtMem (SYMSTR("doomcfg"),HS_NULL);
 	}
 
 	if (!(fsPtr = fopen("doomcfg","w")))
 	PostGameCleanup(fc,ERR_UNKNOWN);
 	
 	fwrite(&Controls,sizeof(ControlStruct),1,fsPtr);
 	fwrite(&gg.Auto_Aim,sizeof(char),1,fsPtr);
 	
 	fclose(fsPtr);
 	
try_archive:
 stnl++;
 if (EM_findEmptySlot(sizeof(SymFind(SYMSTR ("doomcfg")))))
 {
 	EM_moveSymToExtMem (SYMSTR("doomcfg"),HS_NULL);
 }
 else
 {
	UnlockTexFiles();
	EM_GC(FALSE);
	LoadTextures(fc);
	FixSpriteTex(fc);
	if (stnl >= 10) PostGameCleanup(fc,ERR_UNKNOWN);
	goto try_archive;
 }

}

void ShowMiniMap(FATCONFIG *fc)
{
	short cam_xtile = (fc->cam_xpos)>>6;
  short cam_ytile = (fc->cam_ypos)>>6;
	register short map_xstart;
	register short map_ystart;
	register short map_xend;
	register short map_yend;
	register short x,y,x_tile,y_tile,cam_xtile_map = 0,cam_ytile_map = 0;
	register char* map_data asm("a6") = fc->map_data;

	//ClearGrayScreen();
	
	if ((cam_xtile - 10) > 0) map_xstart = (cam_xtile - 10);
	else map_xstart = 0;

	if ((cam_ytile - 10) > 0) map_ystart = (cam_ytile -10);
	else map_ystart = 0;
	
	map_xend = map_xstart + 20;
	map_yend = map_ystart + 20;
	
	for (y = map_ystart,y_tile = 0; y < map_yend; y++,y_tile++)
	{
		for (x = map_xstart,x_tile = 0; x < map_xend; x++,x_tile++)
		{
			if (y < fc->map_height && x < fc->map_width)
			{
				if ((map_data[y*fc->map_width+x] > 0) && (map_data[y*fc->map_width+x] != 127))
				{
					GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),(x_tile*4)+(display_offsetx),(y_tile*4)+(display_offsety+3),(x_tile*4+4)+(display_offsetx),(y_tile*4+4)+(display_offsety+3),COLOR_BLACK);
				}
				else if ((map_data[y*fc->map_width+x] == 0))
				{
					GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),(x_tile*4)+(display_offsetx),(y_tile*4)+(display_offsety+3),(x_tile*4+4)+(display_offsetx),(y_tile*4+4)+(display_offsety+3),COLOR_WHITE);
				}
				else if ((map_data[y*fc->map_width+x] == -127))
				{
					GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),(x_tile*4)+(display_offsetx),(y_tile*4)+(display_offsety+3),(x_tile*4+4)+(display_offsetx),(y_tile*4+4)+(display_offsety+3),COLOR_LGRAY);
				}
				else if ((map_data[y*fc->map_width+x] == -113))
				{
					GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),(x_tile*4)+(display_offsetx),(y_tile*4)+(display_offsety+3),(x_tile*4+4)+(display_offsetx),(y_tile*4+4)+(display_offsety+3),COLOR_DGRAY);
				}
				else if ((map_data[y*fc->map_width+x] == 127))
				{
					GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),(x_tile*4)+(display_offsetx),(y_tile*4)+(display_offsety+3),(x_tile*4+4)+(display_offsetx),(y_tile*4+4)+(display_offsety+3),COLOR_DGRAY);
				}
				else
				{
				  GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),(x_tile*4)+(display_offsetx),(y_tile*4)+(display_offsety+3),(x_tile*4+4)+(display_offsetx),(y_tile*4+4)+(display_offsety+3),COLOR_WHITE);
				}	
				if (x == (cam_xtile) && y == (cam_ytile))
				{
					cam_xtile_map = x_tile;
					cam_ytile_map = y_tile;
				}
			}
		}
	}
	
	do
	{
		Wait(2);
		GrayInvertRect((cam_xtile_map*4)+(display_offsetx),(cam_ytile_map*4)+(display_offsety+3),((cam_xtile_map*4)+(display_offsetx)+4),((cam_ytile_map*4)+(display_offsety+3)+4));
		if ((key = FAT_GetPadState())) break;
	}
	while(1);
	FAT_AllKeysReleased();

}

static inline void AutoAim(FATCONFIG *fc)
{
	register int target;
	register short t_angle;
	register short t_distance;
	register short t_cur_dist;
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	
	for (t_cur_dist = 0; t_cur_dist < (5*64); t_cur_dist+= 16)
	{
		for (target = 0; target < fc->nr_sprites; target++)
		{
			if (sprite[target].angle == -1)
			continue;
			
			if ((sprite_data[target].staticsprite == 0 || 
					 sprite_data[target].staticsprite == -2) && 
					 sprite_data[target].life > 0)
			{ 	
	  												
		 	 if (!RayBlocked(fc,fc->cam_xpos,fc->cam_ypos,sprite[target].xpos,sprite[target].ypos))
			 {
			 	t_distance = ReturnDistance(fc,target);
				
				t_angle = (FAT_GetArcTanYX(
						sprite[target].ypos - fc->cam_ypos  ,
						sprite[target].xpos - fc->cam_xpos));
						
	  		if ((t_distance <= (t_cur_dist)))
	  			{
	  				fc->cam_orientation = t_angle;
	  				return;
	  			}
				}
			}
		}
	}
}

static inline void PreventDoorClose(int idx)
{
	register FATSPRITE *sprite asm("4") = sprites;
    	FATDOOR* door = FAT_GetDoor((sprite[idx].xpos>>6),(sprite[idx].ypos>>6));
    	if (door->state == DOOR_CLOSING || door->state == DOOR_CLOSED) door->state = DOOR_OPENING;
}

void ShowCredits(FATCONFIG *fc)
{	
		unsigned char* pDoomFont;
		char scroll;
	  // open and lock the font file
	   pDoomFont = OpenFile("doomfont");
		ClearGrayScreen();
	  // if the font file does not exist then exit
	  if (!pDoomFont)
		return;
		
		FILE *fsPtr;
		
		if (!(fsPtr = (fopen ("doomcdts","r"))))
		PostGameCleanup(fc,ERR_TEXTFILE2);
		
		SetUserFont(pDoomFont, &fontWidth[0], 8);
		
		char buffer[2] = " \0";
		short x = 20,y = 90;
		
		while (buffer[0] != '%'  && !_keytest(RR_ESC))
		{
			buffer[0] = getc(fsPtr);
			
			if (buffer[0] != '\r' && buffer[0] != '%')
			{
				if (buffer[0] == 'I') x+=2;
				GrayUserDrawString8(x+display_offsetx,y+display_offsety,buffer);
				if (buffer[0] == 'I') x-=2;
				Wait(1);
				x+=7;
			}
			
			if (buffer[0] == '\r')
	 		{	
	 			if (display_offset == 0)
	 			{
	 				for (scroll = 0; scroll < 10; scroll++)
	 				{
 						ScrollUp160((GrayGetPlane(LIGHT_PLANE)),100);
 						ScrollUp160((GrayGetPlane(DARK_PLANE)),100);
	 				}
	 			}
	 			else
	 			{
	 				for (scroll = 0; scroll < 10; scroll++)
	 				{
 						ScrollUp240((GrayGetPlane(LIGHT_PLANE)),128);
 						ScrollUp240((GrayGetPlane(DARK_PLANE)),128);
	 				}
	 			}
	 			Wait(50);
 				x = 20;
 			}
		}
	fclose(fsPtr);
	FAT_AllKeysReleased();
	FAT_AllKeysReleased();
}

static inline void AccidentalDamage(FATCONFIG *fc)
{
  register short kx;
	register short ky;
	register short orientation = fc->cam_orientation;
	register short px = fc->cam_xpos;
  register short py = fc->cam_ypos;

			gg.health -= 15;
		
			if (gg.health > 75)
			{
				ClearFacePlane();
				UpdateFace(facepain1);
			}
	
			if (gg.health >= 50 && gg.health < 75)
			{
				ClearFacePlane();
				UpdateFace(facepain2);
			}
						
			if (gg.health < 50)
			{
				ClearFacePlane();
				UpdateFace(facepain3);
			}
						
	UpdateStats();
						
		kx = px - ((((FAT_Cos16384(orientation))>>10) * 160)>>7);
		ky = py - ((((FAT_Sin16384(orientation))>>10) * 160)>>7);
    PlayerMove2(fc,kx,ky);  			
}

// help with fireball stuff curtesy of MALCOLM SMITH ///

static inline void CalcAccidentalDamage(FATCONFIG *fc,short i)
{
		register short stsdistx = abs(fc->cam_xpos - PlrProj[i].pjspr.xpos);
		register short stsdisty = abs(fc->cam_ypos - PlrProj[i].pjspr.ypos); 
		

				if (stsdistx < 48 && stsdisty < 48)
  			{
  				AccidentalDamage(fc);
  			}
  			
}

static inline void ExplodeProjectile(FATCONFIG *fc,short i)
{
		register short tile_x = ((FAT_Cos16384(PlrProj[i].pjspr.orientation) >> 8)+PlrProj[i].pjspr.xpos)>>6;
    register short tile_y = ((FAT_Sin16384(PlrProj[i].pjspr.orientation) >> 8)+PlrProj[i].pjspr.ypos)>>6;
    register char* map_data asm("a6") = fc->map_data;
    
    			if (map_data[tile_y*fc->map_width + tile_x] == 57)
  	      	{	
  	      			map_data[tile_y*fc->map_width + tile_x] = 25;
  	      		  gg.number_computers--;
  	      	}
				
  	      	if (map_data[tile_y*fc->map_width + tile_x] == 58)
  	      	{
  	      			map_data[tile_y*fc->map_width + tile_x] = 26;
  	      		  gg.number_computers--;
  	      	}
    
        PlrProj[i].pjspr.nr_textures = 1;
				PlrProj[i].pjspr.textures = explosion;
				PlrProj[i].exploding = EXPLODING;
				PlrProj[i].src = explosion;
				UpdateStats();
}

static inline void SpawnProjectile(FATCONFIG *fc,short which)
{
	register short pj_index;
	register short fixxpos;
	register short fixypos;
		
	for (pj_index=0;pj_index<MAX_NR_PLR_PROJECTILES;pj_index++)
    {
      if (PlrProj[pj_index].in_use == SPRITE_FREE)
	break;
    }
    
  if (pj_index >= (MAX_NR_PLR_PROJECTILES))
    return;
    
    fixxpos = FAT_Cos16384(fc->cam_orientation) >> (10);
    fixypos = FAT_Sin16384(fc->cam_orientation) >> (10);
  
  PlayerProjectile *this_pj = &PlrProj[pj_index];
	FATSPRITE *spr = &this_pj->pjspr;
	FAT_InitSprite(spr);
	this_pj->in_use = SPRITE_INUSE;
	spr->drawmode = SPRITEMODE_SIZE64;
	spr->xpos = fc->cam_xpos + fixxpos;
	spr->ypos = fc->cam_ypos + fixypos;
  
  if (which == ROCKET) 
  {
  	spr->textures = rocket;
  	this_pj->src = rocket;
  	spr->nr_textures = 1;
  	this_pj->type = PROJ_ROCKET;
  }
  
  if (which == PLASMA)
  {
  	spr->textures = plasma;
  	this_pj->src = rocket;
  	spr->nr_textures = 1;
  	this_pj->type = PROJ_PLASMA;
  }

  spr->orientation = fc->cam_orientation;
  this_pj->orientation = spr->orientation;
  this_pj->exploding = PROJ_NORMAL;
  gg.num_plr_proj++;
}

void HandleProjectiles(FATCONFIG *fc)
{
	register short stepx = 0;
	register short stepy = 0;
	register short newxpos;
	register short newypos;
	register short i,a;
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	WeaponStruct *curweapon = &weapon;
	FATSPRITE *spr;
	spr = sprite + gg.num_sprites + gg.num_fireballs;
	PlayerProjectile *this_pj = PlrProj;
	short spr_index = gg.num_sprites + gg.num_fireballs;
	
	
	 for (i = 0; i<MAX_NR_PLR_PROJECTILES; i++)
  {		
  	if (PlrProj[i].exploding >= EXPLODING)
  	{
  		if (PlrProj[i].pjspr.textures < PlrProj[i].src + 2)
  		{
  			PlrProj[i].pjspr.textures ++;
  		}
  		else
  		{
  			KillProjectile(fc,i);
  		}
  		
  	}
  	
  	if (PlrProj[i].in_use == SPRITE_INUSE)
  	{
  		if (PlrProj[i].type == PROJ_ROCKET)
  		{
  			stepx = FAT_Cos16384(PlrProj[i].orientation) >> (10);
        stepy = FAT_Sin16384(PlrProj[i].orientation) >> (10);
  		}
  		if (PlrProj[i].type == PROJ_PLASMA)
  		{
  			stepx = FAT_Cos16384(PlrProj[i].orientation) >> (8);
        stepy = FAT_Sin16384(PlrProj[i].orientation) >> (8);
  		}
  		
      newxpos = (PlrProj[i].pjspr.xpos + stepx);
      newypos = (PlrProj[i].pjspr.ypos + stepy);

     for (a = 0; a<gg.num_sprites; a++)
     {
     		if ((abs(sprite[a].xpos - PlrProj[i].pjspr.xpos)<32) 
     	 && (abs(sprite[a].ypos - PlrProj[i].pjspr.ypos))<32)
     	 {
     	 		if (sprite[a].textures != (enemydeath+3) 
  	       && ((sprite[a].drawmode != SPRITEMODE_UNUSED && sprite_data[a].staticsprite < 2
  	       && sprite_data[a].staticsprite > -2) || (sprite_data[a].staticsprite == (100) 
     	 		|| sprite_data[a].staticsprite == (200))))
  	       {
  	       	if (PlrProj[i].exploding == PROJ_NORMAL)
  	       	{
  	       		sprite_data[a].life -= curweapon->damage;
  	       		CalcAccidentalDamage(fc,i);
  	       		ExplodeProjectile(fc,i);
  	       	}
  	       }
      	}
     }
     
     if (ValidMove(fc,newxpos,newypos) && PlrProj[i].exploding == PROJ_NORMAL)
      {
      	PlrProj[i].pjspr.xpos += stepx;
      	PlrProj[i].pjspr.ypos += stepy;
      }
      else if (PlrProj[i].exploding == PROJ_NORMAL)
      {
      	CalcAccidentalDamage(fc,i);
      	ExplodeProjectile(fc,i);
      }
     
  	}
  	
  }	
	
	for (i = 0;i<MAX_NR_FIREBALLS; i++, this_pj++)
    {
      if (this_pj->in_use == SPRITE_FREE)
        continue;
      // Otherwise, this projectile is in use, and needs to be added to the array of active FATSPRITEs.
      memcpy(spr,&PlrProj[i].pjspr,sizeof(FATSPRITE)); // Copy it behind all the enemy/etc sprites
      spr++;
      spr_index++;
    }
    
    sprite_data[spr_index].staticsprite = -25;
}

static inline void ExplodeFireBall(short i)
{
	 fireballs[i].fbspr.nr_textures = 1;
	 fireballs[i].fbspr.textures = explosion;
	 fireballs[i].exploding = EXPLODING;
	 fireballs[i].src = explosion;
}

static inline void SpawnFireBall(FATSPRITE *s,register short idx)
{
	register short fb_index;
	
	for (fb_index=0;fb_index<MAX_NR_FIREBALLS;fb_index++)
    {
      if (fireballs[fb_index].in_use == SPRITE_FREE)
	break;
    }
    
  if (fb_index >= MAX_NR_FIREBALLS)
    return;
    
  FireBall *this_fb = &fireballs[fb_index];
	FATSPRITE *spr = &this_fb->fbspr;
	FAT_InitSprite(spr);
	this_fb->in_use = SPRITE_INUSE;
	spr->drawmode = SPRITEMODE_SIZE64;
	spr->xpos = s->xpos;
	spr->ypos = s->ypos;
  spr->nr_textures = 8;
  spr->textures = fireball;
  spr->orientation = s->orientation;
  this_fb->orientation = spr->orientation;
  this_fb->exploding = PROJ_NORMAL;
  this_fb->src = fireball;
  this_fb->shot_by = idx;
  gg.num_fireballs++;
}



void HandleFireBalls(FATCONFIG *fc)
{
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	register short stepx;
	register short stepy;
	register short newxpos;
	register short newypos;
	register short i;
	FATSPRITE *spr;
	spr = sprite + gg.num_sprites;
	FireBall *this_fb = fireballs;
	short spr_index = gg.num_sprites;
	
	 for (i = 0; i<MAX_NR_FIREBALLS; i++)
  {
  	if (fireballs[i].exploding == EXPLODING)
  	{
  		if (fireballs[i].fbspr.textures < fireballs[i].src + 2)
  		{
  			fireballs[i].fbspr.textures ++;
  		}
  		else
  		{
  			KillFireBall(fc,i);
  		}
  		
  	}
  	
  	if (fireballs[i].in_use == SPRITE_INUSE)
  	{
  		stepx = FAT_Cos16384(fireballs[i].orientation) >> (10);
      stepy = FAT_Sin16384(fireballs[i].orientation) >> (10);
      newxpos = (fireballs[i].fbspr.xpos + stepx);
      newypos = (fireballs[i].fbspr.ypos + stepy);
      
      if (ValidMove(fc,newxpos,newypos))
      {
      	fireballs[i].fbspr.xpos += stepx;
      	fireballs[i].fbspr.ypos += stepy;
      }
      else if (fireballs[i].exploding == PROJ_NORMAL)
      {
        ExplodeFireBall(i);
      }
      
      if ((abs(fc->cam_xpos - fireballs[i].fbspr.xpos)<32) 
      && (abs(fc->cam_ypos - fireballs[i].fbspr.ypos))<32
      && fireballs[i].exploding == PROJ_NORMAL)
      {
      	UpdateDamage(fc,fireballs[i].shot_by);
      	ExplodeFireBall(i);
      }
  	}
  	
  }	
	
	for (i = 0;i<MAX_NR_FIREBALLS; i++, this_fb++)
    {
      if (this_fb->in_use == SPRITE_FREE)
        continue;
      // Otherwise, this projectile is in use, and needs to be added to the array of active FATSPRITEs.
      memcpy(spr,&fireballs[i].fbspr,sizeof(FATSPRITE)); // Copy it behind all the enemy/etc sprites
      spr++;
      spr_index++;
    }
    
 sprite_data[spr_index].staticsprite = -25;
  
}


void HandleHostages(FATCONFIG *fc,int index)
{
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
  register short orientation = 0;
  SpriteStruct *s = sprite_data;
  register short i;
  
if (sprite[index].drawmode != SPRITEMODE_UNUSED)
 { 
			PreventDoorClose(index);	
 		for (i = 0; i<MAX_NR_SPRITES; i++)
 		{
 			if (s[i].staticsprite == -12)
 			{
 				if (abs(sprite[index].xpos - sprite[i].xpos) < 96 
 				&& abs(sprite[index].ypos - sprite[i].ypos) < 96
 			  && sprite[index].drawmode != SPRITEMODE_UNUSED)
 			  {
 			  	sprite[index].drawmode = SPRITEMODE_UNUSED;
 			  	NumberHostages-=1;
 			  	if (NumberHostages <= 0)
 			  	{
 			  		gg.AETC = 0;
 			  	}
 			  }  
 			}
 		}
 
  if (!RayBlocked(fc,fc->cam_xpos,fc->cam_ypos,sprite[index].xpos,sprite[index].ypos))
  {
  	if (ReturnDistance(fc,index) <= (3*64) && ReturnDistance(fc,index) >= (64))
  	{
  		orientation = (FAT_GetArcTanYX(sprite[index].ypos - fc->cam_ypos ,sprite[index].xpos - fc->cam_xpos)+ANGLE_180);
  		
  		  sprite[index].orientation = orientation;
      	AIMove(fc,&sprite[index]);
  		
  		if (sprite[index].textures < s[index].src + 4)
  		{
  			sprite[index].textures++;
  		}
  		else
  		{
  			sprite[index].textures = s[index].src + 1;
  		}
  	}
  	else
  	{
  	  sprite[index].textures = s[index].src;
  	}  
  		
   }
  	
  }
}	


static inline void LoadPic(unsigned long* gui) {
    unsigned long* src1;
    unsigned long* src2;
    unsigned long* dest1;
    unsigned long* dest2;
    short i;

    src1 = gui;
    src2 = &gui[500];
    for (i=0;i<100;i++) {
        dest1 = (unsigned long*)(GetPlane(0)+(i<<5)-(i<<1)+display_offset);
        dest2 = (unsigned long*)(GetPlane(1)+(i<<5)-(i<<1)+display_offset);
        *dest1++=*src1++,*dest1++=*src1++,*dest1++=*src1++,*dest1++=*src1++,*dest1++=*src1++;
        *dest2++=*src2++,*dest2++=*src2++,*dest2++=*src2++,*dest2++=*src2++,*dest2++=*src2++;
    }
}

void MessageEnqueue(short message)
{
	int i = 0;
	while (message_queue[i] > 0 && i < 9)
	{
		if (message == 1 || message == 2)
		{
			if (message_queue[i] == message) return;
		}
		i++;
	}
	message_queue[i] = message;
}

void UpdateMessages()
{
	int i;
	
	if (message_counter >= 10)
	{
		if (message_queue[0] > 0)
		{
			FontSetSys(F_4x6);
			GrayFastFillRect_R(GrayGetPlane(LIGHT_PLANE),GrayGetPlane(DARK_PLANE),96+display_offsetx,94+display_offsety,160+display_offsetx,100+display_offsety,0xFFFF);
			DrawGrayStr(110+display_offsetx,94+display_offsety,messages[(message_queue[0]-1)][message_step],A_XOR);
			message_step++;
		}
		message_counter = 0;
	}
	
	message_counter++;
	
	if (message_step >= 5)
	{
		message_step = 0;
		for (i = 0; i < 9; i++)
		{
			message_queue[i] = message_queue[i+1];
		}
		message_queue[9] = 0;
	}
	
}


void UpdateHUDMovement(void)
{
	WeaponStruct *curweapon = &weapon;
	
	Time2++;
	if (Time2 == 1)
	{
		switch (curweapon->type)
		{
			case PISTOL:
			FAT_SetLowerHUD(pistolhudmove1plane1+288,pistolhudmove1plane2+288,pistolhudmove1mask+288);
			return;
			break;
			case SHOTGUN:
			FAT_SetLowerHUD(shotgunhudmove1plane1+288,shotgunhudmove1plane2+288,shotgunhudmove1mask+288);
			return;
			break;
			case RAILGUN:
			FAT_SetLowerHUD(railgunhudmove1plane1+288,railgunhudmove1plane2+288,railgunhudmove1mask+288);
			return;
			break;
			case FIST:
			return;
			break;
		}
	}
	if (Time2 == 3)
	{
		switch (curweapon->type)
		{
			case PISTOL:
			FAT_SetLowerHUD(hud1_plane1+288,hud1_plane2+288,hud1mask+288);
			return;
			break;
			case SHOTGUN:
			FAT_SetLowerHUD(shotgun_hud1_plane1+288,shotgun_hud1_plane2+288,shotgunhud1mask+288);
			return;
			break;
			case RAILGUN:
			FAT_SetLowerHUD(railgun_hud1_plane1+288,railgun_hud1_plane2+288,railgunhud1mask+288);
			return;
			break;
			case FIST:
			return;
			break;
		}			
	}
	if (Time2 == 5)
	{
		switch (curweapon->type)
		{
			case PISTOL:
			FAT_SetLowerHUD(pistolhudmove2plane1+288,pistolhudmove2plane2+288,pistolhudmove2mask+288);
			return;
			break;
			case SHOTGUN:
			FAT_SetLowerHUD(shotgunhudmove2plane1+288,shotgunhudmove2plane2+288,shotgunhudmove2mask+288);
			return;
			break;
			case RAILGUN:
			FAT_SetLowerHUD(railgunhudmove2plane1+288,railgunhudmove2plane2+288,railgunhudmove2mask+288);
			return;
			break;
			case FIST:
			return;
			break;
		}			
	}
	if (Time2 == 7)
	{
		switch (curweapon->type)
		{
			case PISTOL:
			FAT_SetLowerHUD(hud1_plane1+288,hud1_plane2+288,hud1mask+288);
			return;
			break;
			case SHOTGUN:
			FAT_SetLowerHUD(shotgun_hud1_plane1+288,shotgun_hud1_plane2+288,shotgunhud1mask+288);
			return;
			break;
			case RAILGUN:
			FAT_SetLowerHUD(railgun_hud1_plane1+288,railgun_hud1_plane2+288,railgunhud1mask+288);
			return;
			break;
			case FIST:
			return;
			break;
		}		
	}
	if (Time2 >= 9)
	{
		Time2=0;
	}
}



static inline void UpdateSwitchDoors(FATCONFIG *fc)
{
	register int i;
	register char* map_data asm("a6") = fc->map_data;
	TEXCONFIG *tex = NULL;
	FATDOOR *door;
	for (i=0; i<MAX_NR_DOORS; i+=2)
	{
		if (switchdoors1[i][0] > 0 && switchdoors1[i][0] > 0)
		{
							if (map_data[switchdoors1[i][1]*fc->map_width+(switchdoors1[i][0]-1)]>0)
            	{
            		tex = &textures[(map_data[switchdoors1[i][1]*fc->map_width+(switchdoors1[i][0]-1)])-1];
            	}
            	else if (map_data[switchdoors1[i][1]*fc->map_width+(switchdoors1[i][0]+1)]>0)
            	{
            		tex = &textures[(map_data[switchdoors1[i][1]*fc->map_width+(switchdoors1[i][0]+1)])-1];
            	}
            	else if (map_data[(switchdoors1[i][1]-1)*fc->map_width+(switchdoors1[i][0])]>0)
            	{
            		tex = &textures[(map_data[(switchdoors1[i][1]-1)*fc->map_width+(switchdoors1[i][0])])-1];
            	}
            	else if (map_data[(switchdoors1[i][1]+1)*fc->map_width+(switchdoors1[i][0])]>0)
            	{
            		tex = &textures[(map_data[(switchdoors1[i][1]+1)*fc->map_width+(switchdoors1[i][0])])-1];
            	}
            	else
            	{
            		tex = &textures[1];
            	}
			
			door = FAT_GetDoor(switchdoors1[i][0],switchdoors1[i][1]);
			if (!door)
			{
				map_data[switchdoors1[i][1]*fc->map_width+switchdoors1[i][0]] = 127;
				FAT_AddDoor(switchdoors1[i][0],switchdoors1[i][1],DOOR_HORIZONTAL,DOOR_OPENING,0,tex,tex,NULL);
			}		
		}	
	}
}

static inline void UpdateSwitchDoors2(FATCONFIG *fc)
{
	register int i;
	register char* map_data asm("a6") = fc->map_data;
	TEXCONFIG *tex = NULL; 
	FATDOOR *door;
	for (i=0; i<MAX_NR_DOORS; i+=2)
	{
		if (switchdoors2[i][0] > 0 && switchdoors2[i][0] > 0)
		{
							if (map_data[switchdoors2[i][1]*fc->map_width+(switchdoors2[i][0]-1)]>0)
            	{
            		tex = &textures[(map_data[switchdoors2[i][1]*fc->map_width+(switchdoors2[i][0]-1)])-1];
            	}
            	else if (map_data[switchdoors2[i][1]*fc->map_width+(switchdoors2[i][0]+1)]>0)
            	{
            		tex = &textures[(map_data[switchdoors2[i][1]*fc->map_width+(switchdoors2[i][0]+1)])-1];
            	}
            	else if (map_data[(switchdoors2[i][1]-1)*fc->map_width+(switchdoors2[i][0])]>0)
            	{
            		tex = &textures[(map_data[(switchdoors2[i][1]-1)*fc->map_width+(switchdoors2[i][0])])-1];
            	}
            	else if (map_data[(switchdoors2[i][1]+1)*fc->map_width+(switchdoors2[i][0])]>0)
            	{
            		tex = &textures[(map_data[(switchdoors2[i][1]+1)*fc->map_width+(switchdoors2[i][0])])-1];
            	}
            	else
            	{
            		tex = &textures[1];
            	}
			
			door = FAT_GetDoor(switchdoors2[i][0],switchdoors2[i][1]);
			if (!door)
			{
				map_data[switchdoors2[i][1]*fc->map_width+switchdoors2[i][0]] = 127;
				FAT_AddDoor(switchdoors2[i][0],switchdoors2[i][1],DOOR_HORIZONTAL,DOOR_OPENING,0,tex,tex,NULL);
			}		
		}	
	}
}


void UpdateSwitch(FATCONFIG* fc)
{
	//========================================================================================
	//COBBSWITCH1 = OFF
	//COBBSWITCH2 = ON   I know these are in a funny order, but it takes too much time to fix
	//COBBSWITCH3 = ON   so that's just a you'll have to live with it thing in the code. 
	//COBBSWITCH4 = OFF
	//SWITCHWALL1 = ON
	//SWITCHWALL2 = OFF
	//SWITCHWALL3 = OFF
	//SWITCHWALL4 = ON
	//=========================================================================================
	
	register short tile_x = ((FAT_Cos16384(fc->cam_orientation) >> 8)+fc->cam_xpos)>>6;
  register short tile_y = ((FAT_Sin16384(fc->cam_orientation) >> 8)+fc->cam_ypos)>>6;
  register char* map_data asm("a6") = fc->map_data;
	
	if (map_data[tile_y*fc->map_width+tile_x] > 0)
	{
				if (map_data[tile_y*fc->map_width+tile_x] == (TEXIDX_SWITCHWALL2+1))
				{
					map_data[tile_y*fc->map_width+tile_x] = (TEXIDX_SWITCHWALL1+1);
					if (gg.AETC < 1)
					SwitchLevel(fc,1,1);
					return;
				}
				if (map_data[tile_y*fc->map_width+tile_x] == (TEXIDX_SWITCHWALL1+1)) 
				{
					map_data[tile_y*fc->map_width+tile_x] = (TEXIDX_SWITCHWALL2+1);
					
				return;
				}
				if (map_data[tile_y*fc->map_width+tile_x] == (TEXIDX_SWITCHWALL3+1))
				{
					map_data[tile_y*fc->map_width+tile_x] = (TEXIDX_SWITCHWALL4+1);
					UpdateSwitchDoors2(fc);
					if (gg.switch_doors2 == 0) gg.switch_doors2 = 1;
					FAT_AllKeysReleased();
					MessageEnqueue(3);
					return;
				}
				if (map_data[tile_y*fc->map_width+tile_x] == (TEXIDX_SWITCHWALL4+1)) 
				{
					map_data[tile_y*fc->map_width+tile_x] = (TEXIDX_SWITCHWALL3+1);
					FAT_AllKeysReleased();
					return;
				}
				
				if (map_data[tile_y*fc->map_width+tile_x] == (TEXIDX_COBBSWITCH1+1))
				{
					
					map_data[tile_y*fc->map_width+tile_x] = (TEXIDX_COBBSWITCH2+1);
					FAT_AllKeysReleased();
					
					SetupSwitchComps(fc);
					
					if (gg.number_switches_on > 0)
					{
						SetBackgroundImage(fc,background);
			  		FAT_SetPredrawCallback(NULL);
			  		gg.darkness = 0;
					}
					
					return;
				}
				
				if (map_data[tile_y*fc->map_width+tile_x] == (TEXIDX_COBBSWITCH2+1)) 
				{
					map_data[tile_y*fc->map_width+tile_x] = (TEXIDX_COBBSWITCH1+1);
					
					SetupSwitchComps(fc);
					
					if (gg.number_switches_on <= 0)
				  {
			  		SetBlackBackground(fc);
			  		FAT_SetPredrawCallback(NULL);
			  		FAT_SetPredrawCallback((void*)Darkness);
			  		gg.darkness = 1;
			  		if (gg.AETC == TURN_OFF_SWITCHES) gg.AETC = 0;
			  	}
					
					FAT_AllKeysReleased();
					return;
				}
				if (map_data[tile_y*fc->map_width+tile_x] == (TEXIDX_COBBSWITCH4+1))
				{
					map_data[tile_y*fc->map_width+tile_x] = (TEXIDX_COBBSWITCH3+1);
					UpdateSwitchDoors(fc);
					if (gg.switch_doors1 == 0) gg.switch_doors1 = 1;
					FAT_AllKeysReleased();
					MessageEnqueue(3);
					return;
				}
				if (map_data[tile_y*fc->map_width+tile_x] == (TEXIDX_COBBSWITCH3+1)) 
				{
					map_data[tile_y*fc->map_width+tile_x] = (TEXIDX_COBBSWITCH4+1);
					FAT_AllKeysReleased();
					return;
				}
	}
	else 
	{
		return;
	}
	
}

//======================================================================================
// updates the door in front of the player CODE originally borrowed from fat tech demos.
//======================================================================================
void UpdateDoor(FATCONFIG* fc, short open) {
    short tile_x = ((FAT_Cos16384(fc->cam_orientation) >> 8)+fc->cam_xpos)>>6;
    short tile_y = ((FAT_Sin16384(fc->cam_orientation) >> 8)+fc->cam_ypos)>>6;
    if (fc->cam_xpos == tile_x || fc->cam_ypos == tile_y) return; // cannot be on same tile!
    FATDOOR* door = FAT_GetDoor(tile_x,tile_y);

		if (!door) return;
		
	  short i;
		for (i = 0; i<(MAX_NR_DOORS); i++)
		{	
		  if ((yellow_key_doors[i][0] == tile_x && yellow_key_doors[i][1] == tile_y))
		  {
		  	if (!(gg.yellow_key))
		  	{
		  		MessageEnqueue(1);
		  		return;
		  	}
		  }
		  else if ((blue_key_doors[i][0] == tile_x && blue_key_doors[i][1] == tile_y ))
		  {
		  	if (!(gg.blue_key))
		  	{
		  		MessageEnqueue(2);
		  	 	return;
		  	}
		  }
		}


		
    if (open) {
        if (door->state != DOOR_OPEN) {
            if (door->position == 64) {
                door->state = DOOR_OPEN;
                *(fc->map_data + fc->map_width * tile_y + tile_x) = -127;
            }
            else {
                door->state = DOOR_OPENING;
            }
        }
    }
    else {
        if (door->state != DOOR_CLOSED) {
            if (!door->position) {
                door->state = DOOR_CLOSED;
            }
            else {
                door->state = DOOR_CLOSING;
            }
            *(fc->map_data + fc->map_width * tile_y + tile_x) = 127;
        }
    }
}

static inline void HandleDoors(FATCONFIG* fc)
{
	register short a;
	FATDOOR *curdoor = FAT_GetDoorsArray();
		
	
	for(a=0;a<FAT_GetNrDoors(); a++)
	{
		if(curdoor->state==DOOR_OPEN)
		{
			if(doortimers[a] < MAX_DOOR_WAIT) doortimers[a]++;
			else
			{							
				if (((fc->cam_xpos/64) != curdoor->xtile && (fc->cam_ypos/64) != curdoor->ytile))
				{
					doortimers[a] = 0;
					curdoor->state = DOOR_CLOSING;
				}
			}
		}
		else
		{
        if (curdoor->state == DOOR_OPENING) {
            curdoor->position+=4;
            if (curdoor->position >= 64) {
	            	curdoor->position = 64;
                curdoor->state = DOOR_OPEN;
                *(fc->map_data + fc->map_width * curdoor->ytile
                 + curdoor->xtile) = OPEN_DOOR_TILE;
            }
        }
        else if (curdoor->state == DOOR_CLOSING) {
            curdoor->position-=4;
            if (curdoor->position <= 0) {
                curdoor->position = 0;
                curdoor->state = DOOR_CLOSED;
            }
                *(fc->map_data + fc->map_width * curdoor->ytile
                 + curdoor->xtile) = CLOSED_DOOR_TILE;
        }
		}

		++curdoor;
	}
}


//=============================================================
// CODE curtosy of Malcolm Smith, edited by me.
//=============================================================
void EnemyChase(FATCONFIG* fc,short idx, unsigned long distance)
{
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	FATSPRITE *spr = sprite+idx;
	SpriteStruct* s = sprite_data + idx;
  char *move = &s->moving;
  register short orientation;
	if(distance>(3*64) && *move==GOING) *move = COMING;
	if(distance<(2*64) && *move==COMING) *move = GOING;

	if (distance <= (112))
	{
	if(*move!=COMING)
  spr->orientation = FAT_ClampAngle(spr->orientation-ANGLE_180);
  spr->orientation += random_long((ANGLE_060) - (ANGLE_060/2));
	}
	else
	{
	spr->orientation = (FAT_GetArcTanYX(spr->ypos - fc->cam_ypos ,spr->xpos - fc->cam_xpos)) + ANGLE_180;
	}
  

	AIMove(fc,&sprite[idx]);

  if (!RayBlocked(fc,spr->xpos,spr->ypos,fc->cam_xpos,fc->cam_ypos))      
  {
  	if (s->desire == INSTANT_HIT)
  	{
  		if ((ReturnDistance(fc,idx))<= (2*64)) EnemyShotHit(fc,sprites,idx);
  	}
  	else if (s->desire == THROW_FIREBALL)
  	{
  			if ((ReturnDistance(fc,idx))>= (3*64))
  			return;
  			
  			if ((RayBlocked(fc,spr->xpos,spr->ypos,fc->cam_xpos,fc->cam_ypos)))
  			return;
  			
  			orientation = (FAT_GetArcTanYX(spr->ypos - fc->cam_ypos ,spr->xpos - fc->cam_xpos)) + ANGLE_180;
  			
  				if (gg.difficulty == 1)
  					 {
  					 		if ((spr->orientation <= orientation + 12) && (spr->orientation >= orientation - 12))
  					 		{
  					 			
  					 			if (gg.num_fireballs >= MAX_NR_FIREBALLS)
										return;
									
  					 				if (spr->textures < s->src+4)
  									spr->textures = s->src+4;	
  									SpawnFireBall(spr,idx);
  					 		}
  					 }
  					 if (gg.difficulty == 2)
  					 {
  					 		if ((spr->orientation <= orientation + ANGLE_015) && (spr->orientation >= orientation - ANGLE_015))
  					 		{
  					 		
  					 		if (gg.num_fireballs >= MAX_NR_FIREBALLS)
									return;
									
  					 			if (spr->textures < s->src+4)
  								spr->textures = s->src+4;	
  								SpawnFireBall(spr,idx);
  					 		}
  					 }
  					 if (gg.difficulty == 3)
  					 {
  					 		if ((spr->orientation <= orientation + ANGLE_030) && (spr->orientation >= orientation - ANGLE_030))
  					 		{
  					 		
  					 			if (gg.num_fireballs >= MAX_NR_FIREBALLS)
										return;
									
  					 			if (spr->textures < s->src+4)
  								spr->textures = s->src+4;	
  								SpawnFireBall(spr,idx);
  					 		}
  					 }
  					 if (gg.difficulty == 4)
  					 {
  					 		if ((spr->orientation <= orientation + ANGLE_045) && (spr->orientation >= orientation - ANGLE_045))
  					 		{
  					 		
  					 			if (gg.num_fireballs >= MAX_NR_FIREBALLS)
										return;
									
  					 			if (spr->textures < s->src+4)
  								spr->textures = s->src+4;	
  								SpawnFireBall(spr,idx);
  					 		}
  					 }
  	}
  }
  				
}

static inline void CrossHairs(FATCONFIG *fc)
{
	//+display_offsetx +display_offsety
	GraySprite8_XOR(48,48,4,crosshair,crosshair,fc->dest_plane0,fc->dest_plane1);
}

int StaticDeathAnim(FATCONFIG *fc,FATSPRITE* sprites,register int index,TEXCONFIG* barrel)
{
	register FATSPRITE *sprite asm("4") = sprites;
			
		  if (sprite[index].textures != (barrel+2)) sprite[index].textures = barrel+2;
			
			if (sprite[index].drawmode != SPRITEMODE_UNUSED)
			{
      	if((ReturnDistance(fc,index)) < 64) 
      	{
      		AccidentalDamage(fc);
      	}
			}
			
			return index;
				
}
    

int DeathAnim(FATSPRITE* sprites, int index,TEXCONFIG* enemydeath)
{
	register FATSPRITE *sprite asm("4") = sprites;
	
		  if (sprite[index].textures != (enemydeath+3)) sprite[index].textures = enemydeath;
			return index;
				
}

void HandleDeaths(int index)
{
	register FATSPRITE *sprite asm("4") = sprites;
	if (sprite[index].textures < (enemydeath+3)) 
	{
		sprite[index].textures++;
		if (sprite[index].textures == (enemydeath+3)) 
		{
		sprite[index].drawmode = SPRITEMODE_LOWER32;
		gg.number_enemies--;
		}
	}
}

static inline void FindTrackTiles(FATCONFIG *fc)
{
	register short x,y;
	register char* map_data asm("a6") = fc->map_data;
	
    for (y=0; y<=(fc->map_height-1); ++y) {
        for (x=0; x<=(fc->map_width-1); ++x) {
			if (map_data[y*fc->map_width+x] == -33)
			{
				cinematic_tile.cam_track_x = ((x*64)+32);
				cinematic_tile.cam_track_y = ((y*64)+32);
			}
			if (map_data[y*fc->map_width+x] == -36)
			{
				cinematic_tile.plr_track_x = ((x*64)+32);
				cinematic_tile.plr_track_y = ((y*64)+32);
			}
		}
	}
}

int AnimateCinematicCamera(FATCONFIG *fc)
{
	register FATSPRITE *sprite asm("4") = sprites;
	if ((ReturnSpriteToSpriteDistance(
				fc->cam_xpos,fc->cam_ypos,
				cinematic_tile.cam_track_x,cinematic_tile.cam_track_y) > 32))
				{
					sprite[i].orientation = 
					(FAT_GetArcTanYX(fc->cam_ypos - cinematic_tile.cam_track_y ,
					fc->cam_xpos - cinematic_tile.cam_track_x));
					PlayerMove(fc,0,0,0);
				}
				else
				{
					return 1;
				}
				
		return 0;
}

int AnimateCinematicSprites(FATCONFIG *fc)
{
	register short a;
	register short i;
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	for (i = 0; i < fc->nr_sprites; i++)
	{
			if (sprite_data[i].staticsprite == 17)
			{
				if (sprite[i].textures < sprite_data[i].src + 2)
				{
					a = random(2);
					if (a == 1)
					sprite[i].textures++;
				}
				else
				{
					sprite[i].textures = sprite_data[i].src;
				}
			}
			else if (sprite_data[i].staticsprite == 18 || sprite_data[i].staticsprite == 19)
			{
					
				if (sprite[i].textures < sprite_data[i].src + 3)
				{
					sprite[i].textures++;
				}
				else
				{
					sprite[i].textures = sprite_data[i].src;
				}
				//Opens the door in front of the cinematic sprite. That way, the actions take care of themselves.
						short fix_x = ((FAT_Cos16384(sprite[i].orientation) >> 8))>>6;
    				short fix_y = ((FAT_Sin16384(sprite[i].orientation) >> 8))>>6;
						short tile_x = (((FAT_Cos16384(sprite[i].orientation) >> 8)+sprite[i].xpos)>>6)+fix_x;
    				short tile_y = (((FAT_Sin16384(sprite[i].orientation) >> 8)+sprite[i].ypos)>>6)+fix_y;
   					if (FAT_GetDoor(tile_x,tile_y)) 
   					{
   					// opens door as if it were automatic.
    				FATDOOR* door = FAT_GetDoor(tile_x,tile_y);
    				door->state = DOOR_OPENING;
    				}				
    			HandleDoors(fc);
				if ((ReturnSpriteToSpriteDistance(
				sprite[i].xpos,sprite[i].ypos,
				cinematic_tile.plr_track_x,cinematic_tile.plr_track_y) > 32))
				{
					sprite[i].orientation = 
					(FAT_GetArcTanYX(sprite[i].ypos - cinematic_tile.plr_track_y ,
					sprite[i].xpos - cinematic_tile.plr_track_x)) + ANGLE_180;
					AIMove(fc,&sprite[i]);
				}
				else
				{
					return 1;
				}
			}
	}
	
	return 0;
}

static inline void NullPlayerControls(FATCONFIG *fc)
{
	SwitchLevel(fc,1,0);
	FAT_SetHUD(NULL,NULL,NULL);
	FastFillScreen_R(GrayGetPlane(LIGHT_PLANE));
  FastFillScreen_R(GrayGetPlane(DARK_PLANE));
}

void RunCinematicEnding(FATCONFIG *fc)
{

		//-------------------------------------------------------------------------
    // setup calculator type specials
    //-------------------------------------------------------------------------
    if (!(TI89)) 
    {
        // TI92p or V200
        fc->dest_plane0  += (14*4+8)/2;
        fc->dest_plane1  += (14*4+8)/2;
    }
 
	ShowScrollingText(fc,14);
	register char ReachTarget = 0;
	NullPlayerControls(fc);
	FindTrackTiles(fc);
	while (ReachTarget == 0)
	{
		FAT_Render(fc);
		ReachTarget = AnimateCinematicSprites(fc);
	}
	NullPlayerControls(fc);
	FindTrackTiles(fc);
	ReachTarget = 0;
	while (ReachTarget == 0)
	{
		FAT_Render(fc);
		ReachTarget = AnimateCinematicSprites(fc);
	}
	NullPlayerControls(fc);
	FindTrackTiles(fc);
	ReachTarget = 0;
	while (ReachTarget == 0)
	{
		FAT_Render(fc);
		AnimateCinematicSprites(fc);
		ReachTarget = AnimateCinematicCamera(fc);
	}
	ShowCredits(fc);
	PostGameCleanup(fc,ERR_NORMAL_EXIT);
}


void BossDeadAnim(FATCONFIG *fc,int idx)
{
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	FATSPRITE *spr = sprite+idx;
	SpriteStruct *s = sprite_data + idx;

		if (spr->textures < s->src+13)
		{
			spr->textures++;
		}
	else
	{
		spr->drawmode = SPRITEMODE_LOWER32;
		RunCinematicEnding(fc);
		return;
	}	
}

static inline void BossTarget(FATCONFIG *fc, int index)
{
	register FATSPRITE *sprite asm("4") = sprites;
	FATSPRITE *spr = sprite + index;
  register short orientation;
  
  orientation = FAT_GetArcTanYX(spr->ypos - fc->cam_ypos ,spr->xpos - fc->cam_xpos);
	spr->orientation = (orientation + ANGLE_180);
}

static inline void BossMove(FATCONFIG* fc,int index)
{
	register FATSPRITE *sprite asm("4") = sprites;
	FATSPRITE *spr = sprite + index;
  register short orientation;
  
  orientation = FAT_GetArcTanYX(spr->ypos - fc->cam_ypos ,spr->xpos - fc->cam_xpos);
	spr->orientation = (orientation + ANGLE_180);

  AIMove(fc,spr);
}

void HandleEnemies(FATCONFIG *fc)
{
				if (gg.number_enemies <= 0)
				gg.AETC = 0;
				register int idx;
				register FATSPRITE *sprite asm("4") = sprites;
				register SpriteStruct *sprite_data asm("a5") = sprites_extra;
				
for(idx = 0; idx < fc->nr_sprites; idx++)
		{
				SpriteStruct* s = sprite_data + idx;
				
//=====================================================================================//
//==Just some stuff to make sure we don't waste time on dead and non-moving sprites====//
//=====================================================================================//

			 if (s->staticsprite > 0) continue;
			 
			 if (s->life <= 0)
			 {
			  
			  	if (sprite[idx].textures == (enemydeath+3) && sprite[idx].drawmode != SPRITEMODE_UNUSED)
			 	 	{
			  	  if (deadtimers[idx] < 61) deadtimers[idx]++;
			  	  else 
			  	  {
			  	  	if (sprite[idx].drawmode != SPRITEMODE_UNUSED)
			  	  	{
			  	  		sprite[idx].drawmode = SPRITEMODE_UNUSED;
			  	  	}
			  	  }
			  	}	
			 
			 	 if (s->staticsprite == -2)
			 	 {
							if (sprite[idx].textures < s->src+8)
							sprite[idx].textures = s->src+8;
							
							BossDeadAnim(fc,idx);
			 	 }
			 	 else if (s->staticsprite == 0)
			 	 {
			 	 	  	if (sprite[idx].textures != (enemydeath+3)) HandleDeaths(idx);

			 	 			if (s->dead != DEAD) 
							{			
								DeathAnim(sprites,idx,enemydeath);
								s->dead = DEAD;
							}
			 		}
			 	 continue;
			 }


			 		
			 

//=======================================================================================//
//=====Now if the sprite is alive and moves, continue with the animations and such=======//
//=======================================================================================//			 
	
			if (deadtimers[idx] > 0) deadtimers[idx] = 0; //if the sprite's alive, 
																										//and his dead timer is not
																										//zero, set it to zero.
				
			if (s->staticsprite == -2)
						{
							if (s->life >0)
							{	
							
								if (s->life <= (300) && s->life > 200)
								{
									s->desire = THROW_FIREBALL;
						 		 	s->damage = 3;	
								}

								if (s->life <= 200)
								{
									s->desire = INSTANT_HIT;
									s->damage = 4;
								}
							
								if (s->life <= 100)
								{
									s->desire = THROW_FIREBALL;
						  		s->damage = 5;	
								}
							
							BossTarget(fc,idx);
							
							if ((ReturnDistance(fc,idx)) > 128)
							{
								BossMove(fc,idx);
							}
							else
							{
								if (s->desire == INSTANT_HIT)
								EnemyShotHit(fc,sprites,idx);
								
								if (gg.num_fireballs < MAX_NR_FIREBALLS)
								{
									if (s->desire == THROW_FIREBALL)
									SpawnFireBall(&sprite[idx],idx);
								}
								
							}

							if (sprite[idx].textures < s->src+4)
							{
								if (sprite[idx].textures >= (s->src+3))
								{
								  sprite[idx].textures = s->src;
								}
								if (sprite[idx].textures < s->src+5)
								{
									sprite[idx].textures++;
								}
								
							}
							else
							{
								if (sprite[idx].textures >= (s->src+7)) 
								{
									sprite[idx].textures = s->src;
								}
								
								if (sprite[idx].textures < s->src+7)
								{
									sprite[idx].textures++;
								}
							}
						}	
				}
					
		if (s->staticsprite == 0)
			{			
				if ((ReturnDistance(fc,idx)) < ((5*64)+96))
				{	
					
						if (s->life > 0)
						{
						  PreventDoorClose(idx);
						if (!(RayBlocked(fc,fc->cam_xpos,fc->cam_ypos,sprite[idx].xpos,sprite[idx].ypos)))
						{
							sprite[idx].orientation = (FAT_GetArcTanYX(sprite[idx].ypos - fc->cam_ypos ,sprite[idx].xpos - fc->cam_xpos)) + ANGLE_180;
							EnemyChase(fc,idx,(ReturnDistance(fc,idx)));
						}
							if (sprite[idx].textures < s->src+4)
							{
								if (sprite[idx].textures >= (s->src+3))
								{
								  sprite[idx].textures = s->src;
								}
								if (sprite[idx].textures < s->src+5)
								{
									sprite[idx].textures++;
								}
								
							}
							else
							{
								if (sprite[idx].textures >= (s->src+5)) 
								{
									if (s->desire == INSTANT_HIT)
									{
										if (ReturnDistance(fc,idx) > (4*64))
								 		{
											 sprite[idx].textures = s->src;
							  		}
							  		else
							   		{
							   			 sprite[idx].textures = s->src + 3;	
							   		}
									}
									if (s->desire == THROW_FIREBALL)
									{
										sprite[idx].textures = s->src;
									}
								}
								
								if (sprite[idx].textures < s->src + 5)
								{
									sprite[idx].textures++;
								}
								
								
							}
						}
					}
				}
						
		}
		
			
				
}


void HandleStaticDeaths(int index)
{
	register short i;
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	SpriteStruct *s = sprite_data + index;
	
	for (i = 0; i<gg.num_sprites; i++)
	{
		if ((sprite_data[i].staticsprite == 0 
		|| sprite_data[i].staticsprite == -2)
		 && i != index)
		{
			if (ReturnSpriteToSpriteDistance(
			sprite[i].xpos,
			sprite[index].xpos,
			sprite[i].ypos,
			sprite[index].ypos) < 64)
			{
				sprite_data[i].life -= 10;
			}
		} 
		
	}
	
	if (s->staticsprite == 1)
	{
		if (sprite[index].textures < (sprite_data[index].src+4))
		 sprite[index].textures++;
		if (sprite[index].textures >= (sprite_data[index].src+4)) 
		 sprite[index].drawmode = SPRITEMODE_UNUSED;
	}
	else
	{
		return;
	}
	//timer++;
//	if (timer == 4) timer = 0;
}

void HandleStaticSprites(FATCONFIG *fc)
{
		register int idx;
		register FATSPRITE *sprite asm("4") = sprites;
		register SpriteStruct *sprite_data asm("a5") = sprites_extra;
		for(idx = 0; idx < fc->nr_sprites; idx++)
				{
					
					SpriteStruct* s = sprite_data + idx;
					
					if (s->staticsprite == 12)
					{
						if (sprite[idx].textures >= s->src + 2)
						sprite[idx].textures = s->src;
						if (sprite[idx].textures < s->src + 2)
						sprite[idx].textures++;
						continue;
					}
				
					if (s->staticsprite == 1) 
					{ 
						if (s->life <= 0)
						{	
							if (s->life <= 0 && s->dead != DEAD) 
							{				
								StaticDeathAnim(fc,sprites,idx,barrel);
								s->dead = DEAD;
							}
							if (s->src != (barrel+4)) HandleStaticDeaths(idx);
						}
						continue;
					}
					
					if (s->staticsprite == -1) 
					{ 
						if (sprite[idx].angle != -1)
					 	{
							if (s->life <= 0)
							{	
								if (sprite[idx].textures != s->src+1)
								{
									gg.number_turbines--;
								}
								sprite[idx].textures = s->src+1;
								if (gg.number_turbines <= 0)
								{
									gg.AETC = 0;
									FAT_SetPredrawCallback(NULL);
			  					FAT_SetPredrawCallback((void*)Darkness);
									SetBlackBackground(fc);
								}
							}
						}
						continue;
					}
					
					if (s->staticsprite == -3 && sprite[idx].drawmode != SPRITEMODE_UNUSED)
					{
						if (sprite[idx].angle != -1)
						{
							if (sprite[idx].textures >= s->src + 3)
							{
								sprite[idx].textures = s->src;
							}
							else
							{
								sprite[idx].textures ++;
							}
						}
						continue;
					}
					
						if (s->staticsprite == 200)
						{
						 	if (sprite[idx].angle != -1)
						 	{
						 		if ((ReturnDistance(fc,idx)) < (3*64))
								{
								if (sprite[idx].textures < (s->src+4))
		 						sprite[idx].textures++;
								if (sprite[idx].textures >= (s->src+3))
								sprite[idx].textures = s->src;
								}
							}
							continue;	
						}
					
					if (s->staticsprite == -4)
					{
					 if (sprite[idx].angle != -1)
					 {
							if (abs(fc->cam_xpos- sprite[idx].xpos) < 32 && abs(fc->cam_ypos - sprite[idx].ypos) < 32
							&& sprite[idx].textures == s->src +4)
							{
								UpdateDamage(fc,idx);
							}
							if (s->desire == 1)
							{
								if (sprite[idx].textures < (s->src+7))
		 						sprite[idx].textures++;
								if (sprite[idx].textures >= (s->src+6))
								s->desire = 2;
							}
							if (s->desire == 2)
							{
								if (sprite[idx].textures > (s->src))
		 						sprite[idx].textures--;
								if (sprite[idx].textures <= (s->src))
								s->desire = 1;
							}
						}
						continue;
					}
					
					if (s->staticsprite == -5)
					{
					 if (sprite[idx].angle != -1)
					 {
							if (abs(fc->cam_xpos- sprite[idx].xpos) < 32 && abs(fc->cam_ypos - sprite[idx].ypos) < 32
							&& sprite[idx].textures >= s->src +3)
							{
								UpdateDamage(fc,idx);
							}
							if ((ReturnDistance(fc,idx))<= (96))
							{
								if (s->desire == 1)
								{
									if (sprite[idx].textures < (s->src+6))
		 							sprite[idx].textures++;
									if (sprite[idx].textures >= (s->src+5))
									s->desire = 2;
								}
								if (s->desire == 2)
								{
									if (sprite[idx].textures > (s->src))
		 							sprite[idx].textures--;
									if (sprite[idx].textures <= (s->src))
									s->desire = 1;
								}
							}
							else
							{
								if (sprite[idx].textures < s->src+2)
								sprite[idx].textures++;
								if (sprite[idx].textures >= s->src+2)
								sprite[idx].textures = s->src;
							}
						}
						continue;
					}
					
					if (s->staticsprite == -6)
					{
						if (sprite[idx].angle != -1)
						{
							if (abs(fc->cam_xpos- sprite[idx].xpos) < 32 && abs(fc->cam_ypos - sprite[idx].ypos) < 32
							&& sprite[idx].textures == s->src)
							{
								UpdateDamage(fc,idx);
							}
							if (s->desire == 1)
							{
								if (sprite[idx].textures < (s->src+5))
		 						sprite[idx].textures++;
								if (sprite[idx].textures >= (s->src+4))
								s->desire = 2;
							}
							if (s->desire == 2)
							{
								if (sprite[idx].textures > (s->src))
		 						sprite[idx].textures--;
								if (sprite[idx].textures <= (s->src))
								s->desire = 1;
							}
						}
						continue;
					}
					
					if (s->staticsprite == -7 || s->staticsprite == -8 || 
					    s->staticsprite == -9)
					{
							if ((ReturnDistance(fc,idx)) < 48)
							{
								sprite[idx].drawmode = SPRITEMODE_UNUSED;
							}
							else 
							{
								sprite[idx].drawmode = SPRITEMODE_SIZE64;
							}
						continue;
					}
					
					if (s->staticsprite == -11)
					{
						HandleHostages(fc,idx);
						continue;
					}
					
					if (s->staticsprite == -12)
					{
						if (sprite[idx].textures >= s->src + 2)
						sprite[idx].textures = s->src;
						if (sprite[idx].textures < s->src + 2)
						sprite[idx].textures++;
						continue;	
					}
			}
}

void HandleItems(FATCONFIG* fc)
{
	register int a;
	WeaponStruct *curweapon = &weapon;
	register int extra;
	register FATSPRITE *sprite asm("4") = sprites;
	register SpriteStruct *sprite_data asm("a5") = sprites_extra;
	
	if ((fc->cam_xpos / 64) == DarkTile.x &&
	    (fc->cam_ypos / 64) == DarkTile.y &&
	     DarkTile.darkness   == 0 )
	    {
	    	DarkTile.darkness = 1;
	    	gg.darkness = 1;
	    	SetBlackBackground(fc);
		    FAT_SetPredrawCallback(NULL);
			  FAT_SetPredrawCallback((void*)Darkness);
	    }  
	
	for (a=0; a<fc->nr_sprites; a++)
	{
		FATSPRITE *s = sprite + a;
		SpriteStruct *ss = sprite_data + a;
		register short cam_x = (fc->cam_xpos);
 		register short cam_y = (fc->cam_ypos);
 		
 		if (((ss->staticsprite < 1) && (ss->staticsprite != -3)) || s->drawmode == SPRITEMODE_UNUSED)
		continue; // if it's not an item sprite, don't waste time on it.
	
		if (abs(cam_x-s->xpos) < 48 && abs(cam_y-s->ypos) < 48 && 
		ss->staticsprite == -3 && s->drawmode != SPRITEMODE_UNUSED)
			{
				s->drawmode = SPRITEMODE_UNUSED;
				gg.number_skullboxes--;
				if (gg.number_skullboxes <= 0)
				{
					gg.AETC = 0;
				}
				MessageEnqueue(22);
			}
			
		if (abs(cam_x-s->xpos) < 48 && abs(cam_y-s->ypos) < 48 && ss->staticsprite > 1)
 		{
			if (ss->staticsprite == 2 && s->drawmode != SPRITEMODE_UNUSED) 
			{
				curweapon->type = SHOTGUN;
				curweapon->damage = 6;
				FAT_SetLowerHUD(shotgun_hud1_plane1+288,shotgun_hud1_plane2+288,shotgunhud1mask+288);
				gg.shotgun = 1;
				if (curweapon->shells + 15 < 25) 
				{
						curweapon->shells += 15;
						UpdateStats();
						s->drawmode = SPRITEMODE_UNUSED;
						MessageEnqueue(15);
				}
				else 
				{
					extra = 25 - curweapon->shells;
					if (extra != 0)
					{
							curweapon->shells += extra;
							UpdateStats();
							s->drawmode = SPRITEMODE_UNUSED;
							MessageEnqueue(15);
					}
				}
				gg.shooting = 0;
				if (gg.health > 75)
					{
						ClearFacePlane();
						UpdateFace(facegrin);
					}
				if (gg.health >= 50 && gg.health < 75)
					{
						ClearFacePlane();
						UpdateFace(facegrinhurt1);
					}
				if (gg.health < 50)
					{
						ClearFacePlane();
						UpdateFace(facegrinhurt2);
					}	
				s->drawmode = SPRITEMODE_UNUSED;
			}
			if (ss->staticsprite == 3 && s->drawmode != SPRITEMODE_UNUSED)
			{
				curweapon->type = RAILGUN;
				curweapon->damage = 1;
				FAT_SetLowerHUD(railgun_hud1_plane1+288,railgun_hud1_plane2+288,railgunhud1mask+288);
				gg.railgun = 1;
				if (curweapon->ammo + 50 < 250) 
				{
						curweapon->ammo += 50;
						UpdateStats();
						s->drawmode = SPRITEMODE_UNUSED;
						MessageEnqueue(16);
				}
				else 
				{
					extra = 250 - curweapon->ammo;
					if (extra != 0)
					{
							curweapon->ammo += extra;
							UpdateStats();
							s->drawmode = SPRITEMODE_UNUSED;
							MessageEnqueue(16);
					}
				}
				gg.shooting = 0;
				if (gg.health > 75)
					{
						ClearFacePlane();
						UpdateFace(facegrin);
					}
				if (gg.health >= 50 && gg.health < 75)
					{
						ClearFacePlane();
						UpdateFace(facegrinhurt1);
					}
				if (gg.health < 50)
					{
						ClearFacePlane();
						UpdateFace(facegrinhurt2);
					}	
				s->drawmode = SPRITEMODE_UNUSED;
			}
			if (ss->staticsprite == 4 && s->drawmode != SPRITEMODE_UNUSED)
			{
				//health large
				if (gg.health + 25 < 100) 
				{
						gg.health += 25;
						UpdateStats();
						s->drawmode = SPRITEMODE_UNUSED;
						MessageEnqueue(10);
				}
				else 
				{
					extra = 100 - gg.health;
					if (extra != 0)
					{
							gg.health += extra;
							UpdateStats();
							s->drawmode = SPRITEMODE_UNUSED;
							MessageEnqueue(10);
					}
				}
			}
			if (ss->staticsprite == 5 && s->drawmode != SPRITEMODE_UNUSED)
			{
				//health small			
				if (gg.health + 10 < 100) 
				{
						gg.health += 10;
						UpdateStats();
						s->drawmode = SPRITEMODE_UNUSED;
						MessageEnqueue(10);
				}
				else 
				{
					extra = 100 - gg.health;
					if (extra != 0)
					{
							gg.health += extra;
							UpdateStats();
							s->drawmode = SPRITEMODE_UNUSED;
							MessageEnqueue(10);
					}
				}
			}
			if (ss->staticsprite == 6 && s->drawmode != SPRITEMODE_UNUSED)
			{
				// ammo box
				if (curweapon->ammo != 250) s->drawmode = SPRITEMODE_UNUSED;
				if (curweapon->ammo + 25 < 250) 
				{
						curweapon->ammo += 25;
						MessageEnqueue(11);
						UpdateStats();
				}
				else 
				{
					extra = 250 - curweapon->ammo;
					if (extra != 0)
					{
							curweapon->ammo += extra;
							MessageEnqueue(11);
							UpdateStats();
					}
				}
			}
			if (ss->staticsprite == 7 && s->drawmode != SPRITEMODE_UNUSED)
			{
				//shotgun shells				
				if (curweapon->shells != 25) s->drawmode = SPRITEMODE_UNUSED;
				if (curweapon->shells + 5 < 25) 
				{
						curweapon->shells += 5;
						MessageEnqueue(12);
						UpdateStats();
				}
				else 
				{
					extra = 25 - curweapon->shells;
					if (extra != 0)
					{
							curweapon->shells += extra;
							MessageEnqueue(12);
							UpdateStats();
					}
				}
			}
			if (ss->type == SP_YELLOW_KEY && s->drawmode != SPRITEMODE_UNUSED)
			{
				//yellow key
				s->drawmode = SPRITEMODE_UNUSED;
				gg.yellow_key = 1;
				MessageEnqueue(19);
				
			}
			if (ss->type == SP_BLUE_KEY && s->drawmode != SPRITEMODE_UNUSED)
			{
				//blue key
				s->drawmode = SPRITEMODE_UNUSED;
				gg.blue_key = 1;
				MessageEnqueue(20);
			}
			if (ss->staticsprite == 12 && s->drawmode != SPRITEMODE_UNUSED)
			{
				//portal 
				s->drawmode = SPRITEMODE_UNUSED;
				portal_nr += 1;
				if (portal_nr == 1)
				{
					fc->cam_xpos = Portal[0].x;
					fc->cam_ypos = Portal[0].y;
				}
				else if (portal_nr == 2)
				{
					fc->cam_xpos = Portal[1].x;
					fc->cam_ypos = Portal[1].y;
				}
				else if (portal_nr == 3)
				{
					fc->cam_xpos = Portal[2].x;
					fc->cam_ypos = Portal[2].y;
				}
			}
			if (ss->staticsprite == 16 && s->drawmode != SPRITEMODE_UNUSED)
			{
				curweapon->type = PLASMA_GUN;
				curweapon->damage = 2;				
				FAT_SetHUD(plasma_hud1plane1,plasma_hud1plane2,plasma_hud1mask);
				gg.have_plasma_gun = 1;
				if (curweapon->plasma_ammo + 50 < 100) 
				{
						curweapon->plasma_ammo += 50;
						UpdateStats();
						s->drawmode = SPRITEMODE_UNUSED;
						MessageEnqueue(18);
				}
				else 
				{
					extra = 100 - curweapon->plasma_ammo;
					if (extra != 0)
					{
							curweapon->plasma_ammo += extra;
							UpdateStats();
							s->drawmode = SPRITEMODE_UNUSED;
							MessageEnqueue(18);
					}
				}
				gg.shooting = 0;
				if (gg.health > 75)
					{
						ClearFacePlane();
						UpdateFace(facegrin);
					}
				if (gg.health >= 50 && gg.health < 75)
					{
						ClearFacePlane();
						UpdateFace(facegrinhurt1);
					}
				if (gg.health < 50)
					{
						ClearFacePlane();
						UpdateFace(facegrinhurt2);
					}	
				s->drawmode = SPRITEMODE_UNUSED;
			}
			if (ss->staticsprite == 15 && s->drawmode != SPRITEMODE_UNUSED)
			{
				curweapon->type = ROCKET_LAUNCHER;
				curweapon->damage = 10;				
				FAT_SetHUD(rocket_hud1plane1,rocket_hud1plane2,rocket_hud1mask);
				gg.have_rocket_launcher = 1;
				if (curweapon->rockets + 5 < 10) 
				{
						curweapon->rockets += 5;
						UpdateStats();
						s->drawmode = SPRITEMODE_UNUSED;
						MessageEnqueue(17);
				}
				else 
				{
					extra = 10 - curweapon->rockets;
					if (extra != 0)
					{
							curweapon->rockets += extra;
							UpdateStats();
							s->drawmode = SPRITEMODE_UNUSED;
							MessageEnqueue(17);
					}
				}
				gg.shooting = 0;
				if (gg.health > 75)
					{
						ClearFacePlane();
						UpdateFace(facegrin);
					}
				if (gg.health >= 50 && gg.health < 75)
					{
						ClearFacePlane();
						UpdateFace(facegrinhurt1);
					}
				if (gg.health < 50)
					{
						ClearFacePlane();
						UpdateFace(facegrinhurt2);
					}	
				s->drawmode = SPRITEMODE_UNUSED;
			}
			if (ss->staticsprite == 13 && s->drawmode != SPRITEMODE_UNUSED)
			{
				//PLASMA AMMO
				if (curweapon->plasma_ammo != 100) s->drawmode = SPRITEMODE_UNUSED;
				if (curweapon->plasma_ammo + 25 < 100) 
				{
						curweapon->plasma_ammo += 25;
						MessageEnqueue(14);
						UpdateStats();
				}
				else 
				{
					extra = 100 - curweapon->plasma_ammo;
					if (extra != 0)
					{
							curweapon->plasma_ammo += extra;
							MessageEnqueue(14);
							UpdateStats();
					}
				}
			}
			if (ss->staticsprite == 14 && s->drawmode != SPRITEMODE_UNUSED)
			{
				//ROCKET LAUNCHER AMMO				
				if (curweapon->rockets != 10) s->drawmode = SPRITEMODE_UNUSED;
				if (curweapon->rockets + 3 < 10) 
				{
						curweapon->rockets += 3;
						MessageEnqueue(13);
						UpdateStats();
				}
				else 
				{
					extra = 10 - curweapon->rockets;
					if (extra != 0)
					{
							curweapon->rockets += extra;
							MessageEnqueue(13);
							UpdateStats();
					}
				}
			}
		}
	}
	
}

static inline void KickBack(FATCONFIG *fc)
{
	WeaponStruct *curweapon = &weapon;
	register short origx = (fc->cam_xpos);
  register short origy = (fc->cam_ypos);
	register short ky,kx;
	  
	if (curweapon->type == SHOTGUN)
	{
	kx = origx - ((((FAT_Cos16384(fc->cam_orientation))>>10) * 80)>>7);
	ky = origy - ((((FAT_Sin16384(fc->cam_orientation))>>10) * 80)>>7);
	PlayerMove2(fc,kx,ky);
	}else
	{
  kx = origx - ((((FAT_Cos16384(fc->cam_orientation))>>10) * 10)>>7);
	ky = origy - ((((FAT_Sin16384(fc->cam_orientation))>>10) * 10)>>7);
	PlayerMove2(fc,kx,ky);
	}
}

static inline void SwitchWeapon(char condition)
{
	WeaponStruct *curweapon = &weapon;
	
	condition = 0;
	
				gg.timer = 0;
        gg.shooting = 0;
        		
    		curweapon->type++;
    		if (curweapon->type >= 7)
    		curweapon->type = 1;
    		
    		if (curweapon->type == PISTOL)
        {
          if (curweapon->ammo > 0)
          {
        		FAT_SetLowerHUD(hud1_plane1+288,hud1_plane2+288,hud1mask+288);
        		curweapon->damage = 1;
        		UpdateStats();
        		condition = 1;
          }
          else condition = 0;
        }
        else if (curweapon->type == SHOTGUN)
        {
        	if (gg.shotgun == 1 && curweapon->shells > 0)
        	{
        		FAT_SetLowerHUD(shotgun_hud1_plane1+288,shotgun_hud1_plane2+288,shotgunhud1mask+288);
        		curweapon->damage = 5;
        		UpdateStats();
        		condition = 1;
          }
          else condition = 0;
        }
        else if (curweapon->type == RAILGUN) 
        {
        	if (gg.railgun == 1 && curweapon->ammo > 0)
        	{
        			FAT_SetLowerHUD(railgun_hud1_plane1+288,railgun_hud1_plane2+288,railgunhud1mask+288);
        			curweapon->damage = 1;
        			UpdateStats();
        			condition = 1;
          }
          else condition = 0;
        }
        else if (curweapon->type == FIST)
        {
        	FAT_SetLowerHUD(punch_hud1plane1+288,punch_hud1plane2+288,punch_hudmask1+288);
        	curweapon->damage = 1;
        	UpdateStats();
        	condition = 1;
        }     
        else if (curweapon->type == ROCKET_LAUNCHER)
        {
         	if (gg.have_rocket_launcher == 1 &&  curweapon->rockets > 0)
        	{
        		FAT_SetHUD(rocket_hud1plane1,rocket_hud1plane2,rocket_hud1mask);
        		curweapon->damage = 10;
        		UpdateStats();
        		condition = 1;
          }
          else condition = 0;      	
        }
        else if (curweapon->type == PLASMA_GUN)
        {
        	if (gg.have_plasma_gun == 1 && curweapon->plasma_ammo > 0)
        	{
        		FAT_SetLowerHUD(plasma_hud1plane1+288,plasma_hud1plane2+288,plasma_hud1mask+288);
        		curweapon->damage = 2;
        		UpdateStats();
        		condition = 1;
          }
          else condition = 0;
        }
        
    if (!condition)
    {
    	SwitchWeapon(condition);
    }
}


void HandleGunAnim(FATCONFIG *fc)
{
		WeaponStruct *curweapon = &weapon;
		register SpriteStruct *sprite_data asm("a5") = sprites_extra;
		
		if (gg.shooting == 1)
				{
					
					
					if (curweapon->ammo <= 0 && (curweapon->type == PISTOL || curweapon->type == RAILGUN))
					{
								gg.timer = 0;
        				gg.shooting = 0;
        				FAT_SetLowerHUD(punch_hud1plane1+288,punch_hud1plane2+288,punch_hudmask1+288);
        				curweapon->type = FIST;
        				curweapon->damage = 1;
        				UpdateStats();
					}
					if (curweapon->shells <= 0 && (curweapon->type == SHOTGUN))
					{
								gg.timer = 0;
        				gg.shooting = 0;
        				FAT_SetLowerHUD(punch_hud1plane1+288,punch_hud1plane2+288,punch_hudmask1+288);
        				curweapon->type = FIST;
        				curweapon->damage = 1;
        				UpdateStats();
					}   
					
					switch(gg.timer)
					{
						case 1:
						switch(curweapon->type)
						{
							case PISTOL:
							if (curweapon->ammo > 0)FAT_SetLowerHUD(hud1_plane1+288,hud1_plane2+288,hud1mask+288);
							break;
							
							case SHOTGUN:
							if (curweapon->shells > 0) 
							{
							FAT_SetLowerHUD(shotgun_hud1_plane1+288,shotgun_hud1_plane2+288,shotgunhud1mask+288);
							}
							break;
							
							case RAILGUN:
							if (curweapon->ammo > 0)
							{
							int index = ShotHit(fc,sprites,enemydeath,sprite_data);
							FAT_SetLowerHUD(railgun_hud2_plane1+288,railgun_hud2_plane2+288,railgunhud2mask+288);
							sprite_data[index].life -= curweapon->damage;
							curweapon->ammo--;
							UpdateStats();
							}
							break;
							
							case FIST:
									FAT_SetLowerHUD(punch_hud2plane1+288,punch_hud2plane2+288,punch_hudmask2+288);
							break;
							
							case ROCKET_LAUNCHER:
							
									if (curweapon->rockets <= 0)
									return;
									
									if (gg.num_plr_proj >= MAX_NR_PLR_PROJECTILES)
									return;
									
									curweapon->rockets --;
									
									UpdateStats();
									FAT_SetHUD(rocket_hud2plane1,rocket_hud2plane2,rocket_hud2mask);
									
							break;
							
							case PLASMA_GUN:
									
									if (curweapon->plasma_ammo <= 0)
									return;
									
									if (gg.num_plr_proj >= MAX_NR_PLR_PROJECTILES)
									return;
									
									curweapon->plasma_ammo --;
									
									UpdateStats();
									FAT_SetLowerHUD(plasma_hud1plane1+288,plasma_hud1plane2+288,plasma_hud1mask+288);
									
							break;
							
							default:
							break;
						}
		      	break;
		      
		      case 2:
						switch(curweapon->type)
						{
							case PISTOL:
							if (curweapon->ammo > 0) FAT_SetLowerHUD(hud2_plane1+288,hud2_plane2+288,hud2mask+288);
							break;
							case SHOTGUN:
								if (curweapon->shells > 0)
								{
									FAT_SetLowerHUD(shotgun_hud2_plane1+288,shotgun_hud2_plane2+288,shotgunhud2mask+288);
									KickBack(fc);
									int index = ShotHit(fc,sprites,enemydeath,sprite_data);
        					if((ReturnDistance(fc,index))>160) curweapon->damage = 1;
        					if((ReturnDistance(fc,index))>132) curweapon->damage = 2;
									if((ReturnDistance(fc,index))<96) curweapon->damage = 5;
									sprite_data[index].life -= curweapon->damage;
								 }
							break;	
							case RAILGUN:
							if (curweapon->ammo > 0)
							{
								int index = ShotHit(fc,sprites,enemydeath,sprite_data);
								FAT_SetLowerHUD(railgun_hud1_plane1+288,railgun_hud1_plane2+288,railgunhud1mask+288);
								sprite_data[index].life -= curweapon->damage;
									gg.shooting = 0;
									gg.timer = 0;
									if (curweapon->ammo > 0) curweapon->ammo--;
									UpdateStats();
									KickBack(fc);
							}
							break;
							case FIST:
							FAT_SetLowerHUD(punch_hud3plane1+288,punch_hud3plane2+288,punch_hudmask3+288);
									
									int index = ShotHit(fc,sprites,enemydeath,sprite_data);
									if (ReturnDistance(fc,index) <= 80)
									sprite_data[index].life -= curweapon->damage;					
							break;
							
							case ROCKET_LAUNCHER:
									FAT_SetHUD(rocket_hud3plane1,rocket_hud3plane2,rocket_hud3mask);
									SpawnProjectile(fc,ROCKET);
							break;
							
							case PLASMA_GUN:
									FAT_SetLowerHUD(plasma_hud2plane1+288,plasma_hud2plane2+288,plasma_hud2mask+288);
									SpawnProjectile(fc,PLASMA);
							break;
							
							default:
							break;
					}
				break;
				case 3:
					  switch(curweapon->type)
					  {
					  	case PISTOL:
					  	if (curweapon->ammo > 0)
					  	FAT_SetLowerHUD(hud3_plane1+288,hud3_plane2+288,hud3mask+288);
					  	break;
					  	case SHOTGUN:
					  	if (curweapon->shells > 0)
					  	FAT_SetLowerHUD(shotgun_hud3_plane1+288,shotgun_hud3_plane2+288,shotgunhud3mask);
					  	break;
					  	case FIST:
							FAT_SetLowerHUD(punch_hud2plane1+288,punch_hud2plane2+288,punch_hudmask2+288);
							break;
							
							case ROCKET_LAUNCHER:
							  FAT_SetHUD(rocket_hud4plane1,rocket_hud4plane2,rocket_hud4mask);
							break;
							
							case PLASMA_GUN:
								FAT_SetLowerHUD(plasma_hud3plane1+288,plasma_hud3plane2+288,plasma_hud3mask+288);
							break;
							
							default:
							break;
					  }
				break;
					 
					case 4:  
						switch(curweapon->type)
						{
							case PISTOL:
							if (curweapon->ammo > 0)
							{
							 	int index = (ShotHit(fc,sprites,enemydeath,sprite_data));
								FAT_SetLowerHUD(hud1_plane1+288,hud1_plane2+288,hud1mask+288);
								gg.shooting = 0;
								sprite_data[index].life -= curweapon->damage;
								KickBack(fc);
								curweapon->ammo--;
								UpdateStats();	
							}
							break;
							case SHOTGUN:
							if (curweapon->shells > 0)
							FAT_SetLowerHUD(shotgun_hud4_plane1+288,shotgun_hud4_plane2+288,shotgunhud4mask+288);
							break;
							case FIST:
								FAT_SetLowerHUD(punch_hud1plane1+288,punch_hud1plane2+288,punch_hudmask1+288);
								gg.shooting = 0;
							break;
							
							case ROCKET_LAUNCHER:
									FAT_SetHUD(rocket_hud1plane1,rocket_hud1plane2,rocket_hud1mask);
									gg.shooting = 0;
							break;
							
							case PLASMA_GUN:
									FAT_SetLowerHUD(plasma_hud1plane1+288,plasma_hud1plane2+288,plasma_hud1mask+288);
									gg.shooting = 0;
							break;
							
							default:
							break;
						}
         break;
         
         case 5:
          switch (curweapon->type)
          {
          	case SHOTGUN:
          	if (curweapon->shells > 0)
          	{
          	gg.shooting = 0;
						FAT_SetLowerHUD(shotgun_hud1_plane1+288,shotgun_hud1_plane2+288,shotgunhud1mask+288);
						curweapon->shells--;
						UpdateStats();
						}
						break;
						
						default:
						break;
          }
         break;
         
         default:
				 break;
				 
				}
		}
				
				gg.timer++;
				if (gg.timer >= 6) gg.timer = 0;
}


							



