#include "g_local.h"
void MatrixJabAndHook(edict_t *ent);
void MatrixCharge(edict_t *ent);
void swoosh (edict_t *ent);

static void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
{
	vec3_t	_distance;

	VectorCopy (distance, _distance);
	if (client->pers.hand == LEFT_HANDED)
		_distance[1] *= -1;
	else if (client->pers.hand == CENTER_HANDED)
		_distance[1] = 0;
	G_ProjectSource (point, _distance, forward, right, result);
}

void MatrixKungfu (edict_t *ent)
{
	
	MatrixJabAndHook(ent);
	MatrixCharge(ent);
}
void MatrixJabAndHook(edict_t *ent)
{
	vec3_t	forward, right;
	vec3_t  offset, start;
    trace_t tr;
    vec3_t end;
	int damage, kick, MOD, sum;
	edict_t	*target = NULL;
	edict_t *blip = NULL;
	vec3_t	targetdir, blipdir, dir, AngleToTarget;
	vec_t	speed;
	int		dist;

	if(ent->client->ps.stats[STAT_SPECTATOR])
		return;
	//if(ent->client->weaponstate == WEAPON_FIRING)
	//	return;
	//might be cooler to be able to do kungfu and NOT wait for other shit.

	if(ent->deadflag)
		return;
	if(ent->client->next_kungfu > level.framenum)
		return;
	
	
	while ((blip = findradius(blip, ent->s.origin, 100)) != NULL)
	{
		if (!(blip->svflags & SVF_MONSTER) && !blip->client)
			continue;
		if (blip == ent)
			continue;
		if (!blip->takedamage)
			continue;
		if (blip->health <= 0)
			continue;
		VectorSubtract(blip->s.origin, ent->s.origin, blipdir);
		blipdir[2] += 16;
		if ((target == NULL) || (VectorLength(blipdir) < VectorLength(targetdir)))
		{
			target = blip;
			VectorCopy(blipdir, targetdir);
		}
	}
	sum = fabs(ent->client->v_angle[YAW] - ent->oldvangles[YAW]);

	if(sum > 180)
		sum = 360 - sum;
	
	
//	gi.cprintf (ent, PRINT_HIGH, "YAW = %i   ",sum);
//
	if (target != NULL)
	{
		VectorSubtract(target->s.origin, ent->s.origin, targetdir);
		VectorNormalize(targetdir);
		tr = gi.trace (ent->s.origin, NULL, NULL, target->s.origin, ent, MASK_MONSTERSOLID);
		MOD = MOD_KICK;
		damage = 60;
		kick = 300;
		
		if(sum> 100)//if you spin far enough, do damage
		{
			target->velocity[2] +=100;
			T_Damage (target, ent, ent, targetdir, target->s.origin, target->s.origin, damage_spinkick->value, kick, 1, MOD_SWEEP);
			ent->matrixflip = KUNGFU;
			ent->KungFuAnim = SPINKICK;
			if(level.framenum < ent->LastHit + 15)
			{
				ent->CumulativeDamage += damage_spinkick->value;
				ent->HitStreak++;
				ent->LastHit = level.framenum;
			}
			else
			{
				ent->HitStreak = 1;
				ent->CumulativeDamage = damage_spinkick->value;
				ent->LastHit = level.framenum;
			}
			ent->KungFuAnim = SPINKICK;
			swoosh (ent);//swoosh noise

			if (ent->solid != SOLID_NOT && sum> 100)
			{
				if(IsBlocking(target))
				gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
				else
				gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/kick1.wav"), 1, ATTN_NORM, 0);
				PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
		
				ent->client->next_kungfu = level.framenum + reload_spinkick->value;
		
				return;
			}
		}
		
		
		
		
	}

	   
    // don't need to check for water

	if (ent->OLDvertbuttons <= 0 && 
		ent->vertbuttons>0 && 
		!ent->groundentity && 
		!ent->oldgroundentity) //hover kick must work even if no enemy in range.
			{
				MOD = MOD_KICK;
				damage = 20;
				kick = 1;
				swoosh (ent);//swoosh noise

				if(target != NULL && tr.fraction < 1.0 && tr.ent->takedamage && !tr.ent->deadflag && !ent->deadflag)
				{
					T_Damage (target, ent, ent, targetdir, target->s.origin, target->s.origin, damage_hoverkick->value, kick, 1, MOD_HOVER);
					if(level.framenum < ent->LastHit + 15)
					{
					ent->CumulativeDamage += damage_hoverkick->value;
					ent->HitStreak++;
					ent->LastHit = level.framenum;
					}
					else
					{
					ent->HitStreak = 1;
					ent->CumulativeDamage = damage_hoverkick->value;
					ent->LastHit = level.framenum;
					}
					ent->KungFuAnim = HOVERKICK;
				
					if (ent->solid != SOLID_NOT )
					{
						if(IsBlocking(target))
						{
							gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
							
						}
						else
						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf1.wav"), 1, ATTN_NORM, 0);
						PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
					}
				
				}
				ent->client->next_kungfu = level.framenum + reload_hoverkick->value;


					if (ent->velocity[2] > 0)
						ent->velocity[2] += 100;
					else
						ent->velocity[2] += 120;
					ent->matrixflip = KUNGFU;
					ent->KungFuAnim = HOVERKICK;
			}
	
    AngleVectors (ent->client->v_angle, forward, right, NULL);
    VectorScale (forward, 0, ent->client->kick_origin);
    VectorSet(offset, 0, 0,  ent->viewheight-4);
    P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
    
    VectorMA( start, 80, forward, end );
    
    tr = gi.trace (ent->s.origin, NULL, NULL, end, ent, MASK_MONSTERSOLID);

	if (tr.fraction < 1.0 && tr.ent->takedamage && !tr.ent->deadflag && !ent->deadflag)        
    {            
        
			if(ent->forwardbuttons<0)
				return;
			
			if (ent->OLDforwardbuttons == 0 && ent->forwardbuttons>0)
			{
				MOD = MOD_KICK;
				damage = 20;
				kick = 250;
					T_Damage (tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage_hook->value, kick, 1, MOD_HOOK);
					ent->matrixflip = KUNGFU;
					ent->KungFuAnim = HOOK;
					if(level.framenum < ent->LastHit + 15)
					{
					ent->CumulativeDamage += damage_hook->value;
					ent->HitStreak++;
					ent->LastHit = level.framenum;
					}
					else
					{
					ent->HitStreak = 1;
					ent->CumulativeDamage = damage_hook->value;
					ent->LastHit = level.framenum;
					}
					VectorClear(ent->velocity);
					swoosh (ent);//swoosh noise
					if (ent->solid != SOLID_NOT )
					if(IsBlocking(tr.ent))
						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
						else
						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/kick1.wav"), 1, ATTN_NORM, 0);
					
					PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
					ent->client->next_kungfu = level.framenum + reload_hook->value;
					ent->client->kick_angles[0] = 16;
			}
			else
			if (ent->OLDstrafebuttons <= 0 && ent->strafebuttons>0 && ent->forwardbuttons == 0)
			{
				MOD = MOD_KICK;
				damage = 10;
				kick = 50;
					T_Damage (tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage_jab->value, kick, 1, MOD_JAB);
					ent->matrixflip = KUNGFU;
					ent->KungFuAnim = JAB;
					if(level.framenum < ent->LastHit + 15)
					{
					ent->CumulativeDamage += damage_jab->value;
					ent->HitStreak++;
					ent->LastHit = level.framenum;
					}
					else
					{
					ent->HitStreak = 1;
					ent->CumulativeDamage = damage_jab->value;
					ent->LastHit = level.framenum;
					}
					VectorClear(ent->velocity);
					swoosh (ent);//swoosh noise
					if (ent->solid != SOLID_NOT )
					if(IsBlocking(tr.ent))
						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
						else
						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/kick2.wav"), 1, ATTN_NORM, 0);
						
					PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
					ent->client->next_kungfu = level.framenum + reload_jab->value;
					ent->client->kick_angles[2] = -15;
			}
			else
			if (ent->OLDstrafebuttons >= 0 && ent->strafebuttons<0 && ent->forwardbuttons == 0)
			{
				MOD = MOD_KICK;
				damage = 10;
				kick = 50;
					T_Damage (tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage_jab->value, kick, 1, MOD_JAB);
					ent->matrixflip = KUNGFU;
					ent->KungFuAnim = JAB;
					if(level.framenum < ent->LastHit + 15)
					{
					ent->CumulativeDamage += damage_jab->value;
					ent->HitStreak++;
					ent->LastHit = level.framenum;
					}
					else
					{
					ent->HitStreak = 1;
					ent->CumulativeDamage = damage_jab->value;
					ent->LastHit = level.framenum;
					}
					VectorClear(ent->velocity);
					swoosh (ent);//swoosh noise
					
					if (ent->solid != SOLID_NOT )
					if(IsBlocking(tr.ent))
					gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
					else
					gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/kick.wav"), 1, ATTN_NORM, 0);
					PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
					ent->client->next_kungfu = level.framenum + reload_jab->value;
					ent->client->kick_angles[2] = 15;
			}
			else
			if (ent->OLDvertbuttons < 0 && ent->vertbuttons>=0 && ent->groundentity)
			{
				MOD = MOD_KICK;
				damage = 80;
				kick = 500;
					tr.ent->velocity[2] += 200;
					T_Damage (tr.ent, ent, ent, forward, tr.endpos, tr.plane.normal, damage_uppercut->value, kick, 1, MOD_UPPERCUT);
					ent->matrixflip = KUNGFU;
					ent->KungFuAnim = UPPERCUT;
					if(level.framenum < ent->LastHit + 15)
					{
					ent->CumulativeDamage += damage_uppercut->value;
					ent->HitStreak++;
					ent->LastHit = level.framenum;
					}
					else
					{
					ent->HitStreak = 1;
					ent->CumulativeDamage = damage_uppercut->value;
					ent->LastHit = level.framenum;
					}
					VectorClear(ent->velocity);
					swoosh (ent);//swoosh noise
					
					if (ent->solid != SOLID_NOT )
						if(IsBlocking(tr.ent))
						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf2.wav"), 1, ATTN_NORM, 0);
						else
						gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/phitf1.wav"), 1, ATTN_NORM, 0);
					
					PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
					ent->client->next_kungfu = level.framenum + reload_uppercut->value;
					ent->client->kick_angles[0] = -40;
			}
			
			
	}

	
 VectorCopy(ent->client->v_angle, ent->oldvangles);//NB i am getting pissed off by this thing - WATCH IT.       
}

void MatrixCharge(edict_t *ent) // if you go fast and run into an opponent, you push them back (no damage, just a shoulder charge)
//this was a good idea in theory, but it means that people are pushed back before you can hit them.
{
	
	/*vec3_t	forward, right;
	vec3_t  offset, start, speed;
    trace_t tr;
    vec3_t end;

	AngleVectors (ent->client->v_angle, forward, right, NULL);
    VectorScale (forward, 0, ent->client->kick_origin);
    VectorSet(offset, 0, 0,  ent->viewheight-4);
    P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
    
	VectorCopy (ent->velocity, forward);
	VectorNormalize(forward);
    VectorMA( start, 80, forward, end );
    
    tr = gi.trace (ent->s.origin, NULL, NULL, end, ent, MASK_MONSTERSOLID);
	//trace in direction of speed.

	if(tr.fraction < 1.0 && tr.ent->takedamage && !tr.ent->deadflag && !ent->deadflag 
		&& fabs(VectorLength(ent->velocity)) > 210 
		&& fabs(VectorLength(tr.ent->velocity)) < 200)   
	{
		VectorCopy(ent->velocity, speed);//temp speed
		VectorCopy(tr.ent->velocity, ent->velocity);//player takes on enemy's speed
		VectorMA(speed, 50, tr.ent->velocity, tr.ent->velocity);//player's original speed added onto enemie's
	
	}
*/

}
void swoosh (edict_t *ent)
{
	float	sound;
	sound = random() * 3;
			if (sound <= 1)
			{
				gi.sound(ent, CHAN_WEAPON, gi.soundindex("misc/throw.wav"), 1, ATTN_NORM, 0);
				PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
			}
			else if (sound <= 2)
			{
				gi.sound(ent, CHAN_WEAPON, gi.soundindex("misc/throw.wav"), 1, ATTN_NORM, 0);
				PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
			}
			else if(sound <= 3)
			{
				gi.sound(ent, CHAN_WEAPON, gi.soundindex("misc/swish.wav"), 1, ATTN_NORM, 0);
				PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
			}
}

void MatrixComboTally (edict_t *ent)
{
	char	string[1024];


	if(ent->HitStreak > 1 && ent->LastHit == level.framenum - 15)
	{
	

	// send the layout
	/*Com_sprintf (string, sizeof(string),
		"xv 160 yv 180 string2 \"%i Hit Combo\" ", 			//combo
		ent->HitStreak);

	gi.WriteByte (svc_layout);
	gi.WriteString (string);
	gi.unicast (ent, true);*/
	if(combomessage->value)
	{
	gi.cprintf (ent, PRINT_CHAT, "%i Hit Combo: %i Damage Done\n", ent->HitStreak, (ent->CumulativeDamage * (2 + ent->damagelevel))/2);
	if(ent->CumulativeDamage >= 100)
	gi.sound(ent, CHAN_VOICE, gi.soundindex("frags/combo.wav"), 1, ATTN_NORM, 0);
	}
	if(ent->LastHit == level.framenum - 15)
	ent->HitStreak  = 0;
	ent->CumulativeDamage = 0;
	}

	if(ent->HitStreak && ent->LastHit  < level.framenum - 15)
	{
		ent->HitStreak = 0;
		ent->CumulativeDamage = 0;
	}

}

int IsBlocking (edict_t *ent)
{
	if(!ent->client)
		return false;

	if(strcmp(ent->client->pers.weapon->classname, "weapon_fists") == 0  //if you're using fists or knoves you can block
	|| strcmp(ent->client->pers.weapon->classname, "weapon_knives") == 0)
		if(ent->forwardbuttons <= 0 && ent->strafebuttons == 0 && ent->client->next_kungfu <= level.framenum && ent->client->weaponstate != WEAPON_FIRING)
			return true;
	return false;


}

