/*****************************************************************************
Name            :   missile.cpp
Title           :   Missile 
C Author        :   Stel Michael
Created			:   7 July 1993

Copyright       :   1993 by VideoLogic Limited. All rights reserved.
		    No part of this software, either material or conceptual
		    may be copied or distributed, transmitted, transcribed,
		    stored in a retrieval system or translated into any
		    human or computer language in any form by any means,
		    electronic, mechanical, manual or other-wise, or
		    disclosed to third parties without the express written
		    permission of VideoLogic Limited, HomePark Estate,
		    King's Langley, Hertfordshire, WD4 8LZ, U.K.

Description     :   Functions to Create, Delete and Animate missile
Program Type    :   Microsoft Visual C++ V2
*****************************************************************************/

#define Cplusplus

#include <stdlib.h>
#include <windows.h>
#include <time.h>
#include "sgl.h"
#include "sclist.h" 
#include "actor.h"  
#include "craft.h"  
#include "ant.h"
#include "missile.h"  
#include "math.h"


extern void	sgl_simple_plane2(sgl_vector a,sgl_vector b,sgl_vector c,sgl_bool visible);

extern void	sgl_texture_plane( int texName, float a[3], float b[3], float c[3], int visible, 
					float xScale, float yScale, sgl_bool FirstPlane);

extern void	sgl_texture_plane_glow( int texName, float a[3], float b[3], float c[3], int visible, 
					float xScale, float yScale, sgl_bool FirstPlane);

extern int cpan1Tex,cpan2Tex,cpan3Tex,pan1Tex,pan3Tex,thrustTex,padTex;


int err_first,err_last;
int just_fired=FALSE;
int num_missiles=0;
int frames_since_fire=0;
 
MissileObj *baseMissile=NULL;
MissileObj *curMissile=NULL;

float missile[3] = {0.8f,1.0f,0.7f};
float LightXDir[3]={0.5f,0.5f,0.5f};
float blik[3] = {0.0f,0.0f,0.0f};

extern	int pointLight2;
extern  gi_ant *ant_ptr[MAXANTS];


/*****************************************************************
* Function Name		: Create_Missile  
* Inputs			: pos - starting position of created missile
*					  ori - starting orientation of created missile  		
*					  vel - starting velocity of created missile
* Outputs			: none
* Returns			: void 
* Description		: Adds a missile object to the missile object list	  
******************************************************************/

void Create_Missile(float pos[3], float ori[3], float vel)
{        
	float frontz=35.0f;
    float x_angle,y_angle,miss_x_off,miss_y_off,miss_z_off;                  
    float LightXDir[3]={0.5f,0.5f,0.5f};
    float LightXPos[3]={0.0f,0.0f,0.0f};
                   
	MissileObj *m_ptr;
	int i;

	if ( ( m_ptr =  (MissileObj *) malloc(sizeof(MissileObj)) ) !=NULL )
	{   
	    y_angle=ori[1];
	    
	    x_angle=ori[0];      
	          
	    miss_z_off=frontz* (float) cos(y_angle)* (float) cos(x_angle);	                          
	    miss_x_off=frontz* (float) sin(y_angle)* (float) cos(x_angle);                      
	    miss_y_off=frontz* (float) sin(x_angle);                      
	    
	    m_ptr->pos[0]=pos[0]+miss_x_off;
	    m_ptr->pos[1]=pos[1]+miss_y_off;
	    m_ptr->pos[2]=pos[2]+miss_z_off;
	                          
		for(i=0;i<3;i++)
			m_ptr->ori[i]=ori[i];
        
        m_ptr->ori[0]=-ori[0];
		m_ptr->velocity=vel;
		m_ptr->lifetime=0;	
           
		m_ptr->group = sgl_create_list(TRUE,TRUE,FALSE);
					
		 	m_ptr->id = sgl_create_transform(TRUE);      

			sgl_create_transform(FALSE);

			sgl_translate(-5.0f,0.0f,0.0f);	
			add_missile();     

			sgl_translate(10.0f,0.0f,0.0f);	
			add_missile();     

		sgl_to_parent();

		m_ptr->next=NULL;

		if (baseMissile==NULL)
		{
			m_ptr->prev=NULL;
			baseMissile=m_ptr;
			curMissile=m_ptr;
		}
		else
		{
			m_ptr->prev=curMissile;
			curMissile->next=m_ptr;
			curMissile=m_ptr;
		}
	}
}


/*****************************************************************
* Function Name		: Move_Missile  
* Inputs			: miss - pointer to missile object in object list
*					  which is to be animated
* Outputs			: none
* Returns			: void 
* Description		: traverses list of missile objects and moves 
*					  missiles to their new positions	  
******************************************************************/

void   Move_Missiles(MissileObj *miss)
{
   	if (miss!=NULL)
	{ 
		miss->pos[2] += (miss->velocity* (float) cos(miss->ori[1]));
		miss->pos[0] += (miss->velocity* (float) sin(miss->ori[1]));
		miss->pos[1] += (miss->velocity* (float) sin(-miss->ori[0]));

		sgl_modify_transform(miss->id,TRUE);     
		sgl_translate(miss->pos[0],miss->pos[1],miss->pos[2]);  
		sgl_rotate(sgl_y_axis, miss->ori[1]);
		sgl_rotate(sgl_x_axis, miss->ori[0]);
		sgl_rotate(sgl_z_axis, miss->ori[2]);
        
  		sgl_set_point_light (pointLight2,  missile, LightXDir, miss->pos, 0, 
							FALSE, FALSE);
 
		Move_Missiles(miss->next);
		miss->lifetime++;
	}
}

         
/*****************************************************************
* Function Name		: Collision_Test  
* Inputs			: miss - pointer to missile object in object list
*					  ant - ant number
* Outputs			: none
* Returns			: result of test 
* Description		: tests for collision of missile and ant	  
******************************************************************/                                            
                                             
int	Collision_Test(MissileObj *miss,int ant)
{               
	sgl_vector	diff;
	float	magnitude;

	diff[0] = miss->pos[0] - ant_ptr[ant]->pos[0];
	diff[1] = miss->pos[1] - ant_ptr[ant]->pos[1];
	diff[2] = miss->pos[2] - ant_ptr[ant]->pos[2];

    magnitude= (float) sqrt(diff[0]*diff[0]+diff[1]*diff[1]+diff[2]*diff[2]); 
     
	if ((magnitude>200.0f) || ((ant_ptr[ant]->status)==EXPLODING) || ((ant_ptr[ant]->status)==DEAD) )
    	return (0);
    else 
    {  
   		ant_ptr[ant]->status=HIT;
    	return (1);    
   	}
}	                                             
 
 
/*****************************************************************
* Function Name		: Delete_missile 
* Inputs			: miss - pointer to missile which is to be deleted 
*					  from missile list.
* Outputs			: none										  
* Returns			: void 
* Description		: deletes a missile from the missile list	  
******************************************************************/                                                                                         

void Delete_Missiles(MissileObj *miss)
{
	MissileObj  *prevobj_ptr=NULL;
	MissileObj  *next_ptr=NULL;
    int	hit0,hit1;
              
	if (miss!=NULL)
	{
		next_ptr=miss->next;
                                                                                 
        hit0 = Collision_Test(miss,0);	   
        hit1 = Collision_Test(miss,1);
                                                                                 
		if ((miss->pos[1]<-20.0f) || (miss->lifetime>MISSILE_LIFE) || (hit0) || (hit1))
		{
	        sgl_delete_list(miss->group);	
			sgl_set_point_light (pointLight2,  blik, LightXDir, miss->pos, 0, 
					FALSE, FALSE);
     
            num_missiles--;
            
			prevobj_ptr=miss->prev;

			if (prevobj_ptr!=NULL)
				prevobj_ptr->next=miss->next;
			else
				baseMissile=miss->next;

			if (miss->next!=NULL)
			   miss->next->prev=miss->prev;

			if (miss==curMissile)
				curMissile=miss->prev;

			free(miss);
		}

		Delete_Missiles(next_ptr);
	}
}


/*****************************************************************
* Function Name		: Process_Missile 
* Inputs			: rpress - boolean value indicating whether or 
*					  not the right mouse button has been pressed
*					  craft - pointer to craft object
* Outputs			: none										  
* Returns			: void 
* Description		: manages the creation, animation and deletion 
*					  of missile	  
******************************************************************/ 

void Process_Missiles(int rpress,ControlledObject *craft)
{
	float newvel;

	/* tests for the creation of new missile */
	if (rpress)
		if ((num_missiles<MAXMISSILES) && (!just_fired))
		{
			just_fired=TRUE;
			frames_since_fire=0;
			newvel= (craft->GetVel())+MISSILE_VEL;	 
			Create_Missile(craft->GetPos(),craft->GetOri(),newvel);	  
			num_missiles++;
		}

	if ((frames_since_fire>FIRE_INT) && (just_fired))
		just_fired=FALSE;

	if (just_fired)
		frames_since_fire++;
	
	/* move all active missiles	*/
	Move_Missiles(baseMissile);

	/* test to see if a missile has to be deleted */
	Delete_Missiles(baseMissile);

	sgl_to_parent();
}


/*****************************************************************
* Function Name		: add_missile 
* Inputs			: none
* Outputs			: none										  
* Returns			: void 
* Description		: adds missile to display list	  
******************************************************************/

static void add_missile()
{

	float p0[3]={0.0f,0.0f,-12.0f};
	float p1[3]={-1.0f,0.0f,-10.0f};
	float p2[3]={0.0f,0.25f,-10.0f};
	float p3[3]={1.0f,0.0f,-10.0f};  
	float p4[3]={0.0f,-0.25f,-10.0f};   
	float p5[3]={-1.0f,0.0f,10.0f};
	float p6[3]={0.0f,0.25f,10.0f};
	float p7[3]={1.0f,0.0f,10.0f};   
	float p8[3]={0.0f,-0.25f,10.0f};   
	float p9[3]={0.0f,0.0f,12.0f};
                                  
    float cocol[3]={0.1f,0.1f,0.1f};
    

	sgl_create_list(FALSE,TRUE,FALSE);

        sgl_texture_plane_glow(padTex,p2,p6,p3,FALSE,8.0f,1.0f,TRUE);
        sgl_texture_plane_glow(padTex,p6,p2,p5,FALSE,8.0f,1.0f,FALSE);
	    sgl_texture_plane_glow(padTex,p8,p4,p7,FALSE,8.0f,1.0f,FALSE);
	    sgl_texture_plane_glow(padTex,p4,p8,p1,FALSE,8.0f,1.0f,FALSE);
	    sgl_texture_plane_glow(padTex,p7,p6,p5,FALSE,1.0f,1.0f,FALSE);

		/* border planes */	
	  
	    sgl_texture_plane_glow(padTex,p0,p2,p3,FALSE,8.0f,1.0f,FALSE);
	    sgl_texture_plane_glow(padTex,p0,p3,p4,FALSE,8.0f,1.0f,FALSE);
	    sgl_texture_plane_glow(padTex,p0,p4,p1,FALSE,8.0f,1.0f,FALSE);
	    sgl_texture_plane_glow(padTex,p0,p1,p2,FALSE,8.0f,1.0f,FALSE);
                          
 	sgl_to_parent();
}

