/*

	Copyright (C) 2004 Michael Liebscher
	Copyright (C) 2000-2002 by DarkOne the Hacker

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "../wolfiphone.h"


/*
-----------------------------------------------------------------------------
 Function: 
 
 Parameters:
 
 Returns:
 
 Notes: 

-----------------------------------------------------------------------------
*/
PUBLIC void fire_hit( player_t *self )
{
	entity_t *closest;
	int dist, d1, n, shot_dist, damage;

	Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "lsfx/023.wav" ), 1, ATTN_NORM, 0 );

// actually fire
	dist = 0x7fffffff;
	closest = NULL;

	for( n = 0 ; n < NumGuards ; ++n )
	{
		if( Guards[ n ].flags & FL_SHOOTABLE ) // && Guards[n].flags&FL_VISABLE
		{
			shot_dist = Point2LineDist( Guards[ n ].x - (int)self->position.origin[ 0 ], Guards[ n ].y - (int)self->position.origin[ 1 ], (int)self->position.angle );
			
			if( shot_dist > (2 * TILEGLOBAL / 3) ) 
			{
				continue; // miss
			}
			
			d1 = LineLen2Point( Guards[ n ].x - (int)self->position.origin[ 0 ], Guards[ n ].y - (int)self->position.origin[ 1 ], (int)self->position.angle );
			
			if( d1 < 0 || d1 > dist ) 
			{
				continue;
			}
			
			if( ! Level_CheckLine( Guards[ n ].x, Guards[ n ].y, Player.position.origin[0], Player.position.origin[1], r_world ) )
			{
			//if( ! CheckLine( &Guards[ n ] ) ) 
				continue; // obscured
			}

			dist = d1;
			closest = &Guards[ n ];
		}
	}

	if( ! closest || dist > TILE2POS( 1 ) ) 
	{
		return; // missed if further than 1.5 tiles
	}

	damage = US_RndT() >> 4;

	A_DamageActor( closest, damage ); // hit something
}

/*
-----------------------------------------------------------------------------
 Function: 
 
 Parameters:
 
 Returns:
 
 Notes: 

-----------------------------------------------------------------------------
*/
PUBLIC void fire_lead( player_t *self )
{
	entity_t *closest;
	int damage;
	int dx, dy, dist;
	int d1, shot_dist, n;

	switch( self->weapon )
	{
		case WEAPON_PISTOL:
			Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "sfx/012.wav" ), 1, ATTN_NORM, 0 );
			break;

		case WEAPON_AUTO:
			Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "sfx/011.wav" ), 1, ATTN_NORM, 0 );
			break;

		case WEAPON_CHAIN:
			Sound_StartSound( NULL, 0, CHAN_WEAPON, Sound_RegisterSound( "sfx/013.wav" ), 1, ATTN_NORM, 0 );
			break;
	}
	self->madenoise = true;

	dist = 0x7fffffffl;
	closest = NULL;

	for( n = 0 ; n < NumGuards; ++n )
	{
		if( Guards[ n ].flags & FL_SHOOTABLE ) // && Guards[n].flags&FL_VISABLE
		{
			shot_dist = Point2LineDist( Guards[ n ].x - (int)self->position.origin[ 0 ], Guards[ n ].y - (int)self->position.origin[ 1 ], (int)self->position.angle );
			if( shot_dist > (2 * TILEGLOBAL / 3) )
			{
				continue; // miss
			}

			d1 = LineLen2Point( Guards[ n ].x - (int)self->position.origin[ 0 ], Guards[ n ].y - (int)self->position.origin[ 1 ], (int)self->position.angle );
			if( d1 < 0 || d1 > dist )
			{
				continue;
			}
			
			if( ! Level_CheckLine( Guards[ n ].x, Guards[ n ].y, Player.position.origin[0], Player.position.origin[1], r_world ) )
			{
			//if( ! CheckLine( &Guards[ n ] ) )
				continue; // obscured
			}

			dist = d1;
			closest = &Guards[ n ];
		}
	}

	if( ! closest ) // missed
	{
		r_trace_t trace;

		trace.a = NormalizeAngle( (int)self->position.angle - DEG2FINE( 2 ) + rand() % (DEG2FINE( 4 ) ) );
		trace.x = (int)self->position.origin[ 0 ];
		trace.y = (int)self->position.origin[ 1 ];
		trace.flags = TRACE_BULLET;
		trace.tile_vis = NULL;
		R_Trace( &trace, r_world );

		if( trace.flags & TRACE_HIT_DOOR )
		{
			Sound_StartSound( NULL, 0, CHAN_AUTO, Sound_RegisterSound( "lsfx/028.wav" ), 1, ATTN_NORM, 0 );
		}
		return;
	}

// hit something
	dx = ABS( closest->tilex - self->tilex );
	dy = ABS( closest->tiley - self->tiley );
	dist = max_of_2( dx, dy );

	if( dist < 2 )
	{
		damage = US_RndT() / 4;
	}
	else if( dist < 4 )
	{
		damage = US_RndT() / 6;
	}
	else
	{
		if( US_RndT() / 12 < dist ) 
		{
			return; // missed
		}

		damage = US_RndT() / 6;
	}

	A_DamageActor( closest, damage );
}
