/*
* This code is released under the GNU General Public License.  See COPYING for 
* details.  Copyright 2003 John Spray: spray_john@users.sourceforge.net
*/


#include <stdlib.h>
#include <math.h>
#include <string.h>

#include "Mine.h"
#include "Game.h"
#include "SoundCore.h"
#include "Player.h"
#include "Particle.h"
#include "Visual.h"
#include "LList.h"
#include "Missile.h"


#ifndef M_2PI
#define M_2PI 6.28318
#endif

#ifndef M_PI
#define M_PI 3.14159
#endif

Mine::Mine()
{
	s.x=s.z=0;
	s.y=3.0;
	v=0.0f;
	a=0.0f;
	alive=0;	
	soundid=-1;
	collideradius=5.0f;
	collideradius2=25.0f;
	sniffradius=250.0f;
	spawneffect=0.0f;
	hp=1.0f;
}


void Mine::Live()
{
	spawneffect=maxspawneffect=400.0f;
	alive=1;	
	soundid = game->sound->Play("mine.wav",-1,&s,&v);
}

Mine::~Mine()
{
	if(alive){
		alive=0;	
		game->sound->StopEffect(soundid);
	}
}

void Mine::Physics()
{
	if(!alive) return;

	if(spawneffect){
		spawneffect-=game->dtf;
		if(spawneffect<0.0f)
			spawneffect=0.0f;
	}

	spin+=0.001*game->dtf;
	if(spin>M_2PI)
		spin-=M_2PI;

	v+=game->dtf*a;
	v*=pow(0.99f,game->dtf);
	Collide();
	s+=v*game->dtf;
}

void Mine::Collide()
{
	Vector dist;
	dist=s-game->player->s;
	if(dist.Mag2()<collideradius2+game->player->collideradius2+game->player->collideradius*collideradius && game->player->alive){
		Die();
		game->player->Hurt(0.76f);
		return;
	}

	if(game->arena->Collision(s,s+v*game->dtf,collideradius)){
		v=game->arena->GetLastQuad()->SlideVector(v);
	}

	Vector h,d;
	LListItem<Missile>* item;
	item=game->missilelist->head;
	while(item){
		h=PerpLinePoint(item->data.s,item->data.s+item->data.v*game->dtf,s);
		d=h-s;
		if(d.Mag2()<collideradius2 && PointOnLine(item->data.s,item->data.s+item->data.v*game->dtf,h)){
			Hurt(1.1f);
			return;
		}

		d=item->data.s-s;
		if(d.Mag2()<collideradius2 && PointOnLine(item->data.s,item->data.s+item->data.v*game->dtf,h)){
			Hurt(1.1f);
			return;
		}

		d=item->data.s+item->data.v*game->dtf-s;
		if(d.Mag2()<collideradius2 && PointOnLine(item->data.s,item->data.s+item->data.v*game->dtf,h)){
			Hurt(1.1f);
			return;
		}

		item=item->next;
	}
}

//Find the closest Ufo in game->ufolist to this
//if game->ufolist->count==1 then return this
Ufo* Mine::NearestUfo()
{
	Ufo* retval;
	LListItem<Ufo> *ufoitem;
	Vector d;
	Vector temp;

	ufoitem=game->ufolist->head;
	temp=ufoitem->data.s-s;
	d=temp;
	retval=&ufoitem->data;
	ufoitem=ufoitem->next;

	while(ufoitem){
		temp=ufoitem->data.s-s;
		if(temp.Mag2()<d.Mag2()){
			d=temp;
			retval=&ufoitem->data;
		}
		ufoitem=ufoitem->next;
	}

	return retval;
}

void Mine::Die()
{
	if(!alive){//general paranoia checking
		printf("Mine::Die: (!alive) is true, aborting\n");
		return; 
	}
	Explode();
	alive=0;	
	game->sound->StopEffect(soundid);
}

void Mine::Explode()
{
	Particle newpart;
	newpart.s=s;
	newpart.rad=collideradius;
	newpart.diffuse=0.000003;
	newpart.blendmode=GL_ONE;
	strcpy(newpart.texfile,"explosion1.png");
	newpart.life=200;
	for(int i=0;i<3;i++)
		game->visual->NewParticle(&newpart);
	strcpy(newpart.texfile,"smoke1.png");
	newpart.life=1000;
	newpart.rad=collideradius*1.2;
	newpart.diffuse=0.0000005;
	newpart.res=0.999f;
	newpart.a=game->g*0.1f;
	newpart.blendmode=GL_ONE_MINUS_SRC_ALPHA;
	for(int i=0;i<8;i++)
		game->visual->NewParticle(&newpart);
	strcpy(newpart.texfile,"explosion1.png");
	newpart.life=1500.0f;
	newpart.bounce=PARTICLE_BOUNCE_ONE;
	newpart.drawmode=PARTICLE_DRAW_SIMPLE;
	newpart.rad=0.5;
	newpart.diffuse=0.000000;
	newpart.res=1.0f;
	newpart.a=game->g;
	newpart.collide=1;
	for(int i=0;i<8;i++){
		newpart.v.Randomize();
		newpart.v.y+=1.0f;
		newpart.v*=0.05f;
		game->visual->NewParticle(&newpart);
	}
	newpart.drawmode=PARTICLE_DRAW_MOTION;
	newpart.rad=0.25;
	newpart.life=400.0f;
	newpart.collide=1;
	for(int i=0;i<8;i++){
		newpart.v.Randomize();
		newpart.v*=1.0f;
		game->visual->NewParticle(&newpart);
	}

	game->sound->Play("ufodie.wav",0,s,v);
}

int Mine::Hurt(float pain)
{
	if(hp<=0) return 1;

	hp-=pain;
	if(hp<=0){
		Die();
		return 1;
	}
	else
		return 0;
}
