/**
* Melee attack system
* @version 24-6-2001
* @author Herwin 'harSens' van Welbergen
* @redone by Joseph 'Pcjoe' Florencio
*/

#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "effects.h"
#include "aura.h"
#include "classes.h"
#include "magicattack.h"
#include "explodingattack.h"
#include "player.h"
#include "gamerules.h"
#include "chargedattack.h"
#include "melee.h"
#include "playermelee.h"

// Added by Rick
#include "../bot/bot_util.h"
#include "talkmonster.h"
#include "buddy_aura.h"
#include "buddy.h"
// End add by Rick
extern int gmsgMeleeFX;
extern cvar_t meleeallowed;

LINK_ENTITY_TO_CLASS( weapon_melee, CMelee );

void CMelee::Spawn( void )
{	Precache();
	m_iId = WEAPON_MELEE;
	m_iDefaultAmmo = 0;
	m_iClip = -1;
	FallInit();// get ready to fall down.
}

void CMelee::Precache( void )
{	PRECACHE_SOUND("weapons/swoophit.wav");
	PRECACHE_SOUND("weapons/meleeflash.wav");
	// Advanced Melee Sounds
	PRECACHE_SOUND("weapons/prepunch1.wav");
	PRECACHE_SOUND("weapons/weakpunch.wav");
	PRECACHE_SOUND("weapons/mediumpunch.wav");
	PRECACHE_SOUND("weapons/strongpunch.wav");
	PRECACHE_SOUND("weapons/weakkick.wav");
	PRECACHE_SOUND("weapons/mediumkick.wav");
	PRECACHE_SOUND("weapons/strongkick.wav");
	PRECACHE_SOUND("weapons/meleemiss1.wav");
	PRECACHE_SOUND("weapons/meleemiss2.wav");
	PRECACHE_SOUND("weapons/meleemiss3.wav");
	PRECACHE_SOUND("weapons/chainswoop.wav");
	PRECACHE_SOUND("weapons/throw.wav");
	PRECACHE_SOUND("weapons/spin.wav");
	PRECACHE_SOUND("weapons/meleestruggleinit.wav");
	PRECACHE_SOUND("weapons/meleestruggletie.wav");
	PRECACHE_SOUND("weapons/swordkill.wav");
	PRECACHE_SOUND("weapons/recoverjump.wav");
}

int CMelee::GetItemInfo(ItemInfo *p)
{	p->pszName = STRING(pev->classname);
	p->pszAmmo1 = "ki";	//no ki required
	p->iMaxAmmo1 = -1;	//max ammo is weapon independent
	p->pszAmmo2 = NULL;
	p->iMaxAmmo2 = -1;
	p->iMaxClip = WEAPON_NOCLIP;
	p->iSlot = 0;
	p->iPosition = 0;
	p->iId = m_iId = WEAPON_MELEE;
	p->iWeight = MELEE_WEIGHT;
	p->iFlags = 0;
	return 1;
}

BOOL CMelee::Deploy( void )
{	return DefaultDeploy( "melee" );
}

// Holster...
void CMelee::Holster(int skiplocal=0)
{
}

BOOL CMelee::CanDeploy( void )
{	if(meleeallowed.value)
	{	return TRUE;
	}
	else
	{	return FALSE;
	}
}

// Weapon idle
void CMelee::WeaponIdle( void )
{
}

void CMelee::PrimaryAttack( void )
{	m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.1;
}

void CMelee::SecondaryAttack( void )
{	
	// Modified by Rick: let us be able to (simple) melee enemy buddies aswell

	// Get enemy buddy to melee
	CBuddy *pBuddy = m_pPlayer->m_Melee.GetBuddyEnemyPrepunch(NULL);
	// Get enemy player to melee
	CBasePlayer *pPlayer = m_pPlayer->m_Melee.GetEnemyPrepunch(NULL);

	if (!pBuddy && !pPlayer)
		return;

	// See which is the closest and 'use' that one
	if (pBuddy && pPlayer)
	{
		float flBudDist = (pBuddy->pev->origin - m_pPlayer->pev->origin).Length();
		float flPlayDist = (pPlayer->pev->origin - m_pPlayer->pev->origin).Length();

		if ((flBudDist < flPlayDist) && m_pPlayer->CanMelee(pBuddy))
			pPlayer = NULL; // So we take the buddy
		else if (m_pPlayer->CanMelee(pPlayer))
			pBuddy = NULL; // So we take the player
	}

	// Simple Melee
	if(m_pPlayer->m_Melee.m_fSimpleMelee)
	{
		// Get enemy buddy to melee
		CBuddy *pBuddy = m_pPlayer->m_Melee.GetBuddyEnemyPrepunch(NULL);
		// Get enemy player to melee
		CBasePlayer *pPlayer = m_pPlayer->m_Melee.GetEnemyPrepunch(NULL);

		if (m_pPlayer->UseKi(BLOW_KICK_KI_COST))
		{
			Vector vecDirection = m_pPlayer->m_Swoop.GetCurrentDirection();
			int iDirection = m_pPlayer->m_Swoop.m_iSwoopDirection;

			if (pBuddy)
				m_pPlayer->m_Melee.SimpleMeleePowerhit( pBuddy, vecDirection, iDirection );
			else
				m_pPlayer->m_Melee.SimpleMeleePowerhit( pPlayer, vecDirection, iDirection );
		
			m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.9;
		}
		else
		{
			// Set minimum next attack time
			m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.1;
		}
	}
	// Advanced Melee
	else
	{
		BOOL fBlocked = FALSE;

		// Are we dealing with a player?
		if (pPlayer)
		{
			// their melee attack
			if(pPlayer->m_Swoop.m_fSwoop && (m_pPlayer == pPlayer->m_Melee.GetEnemyPrepunch(NULL)) &&
				(pPlayer->m_pActiveItem ? (pPlayer->m_pActiveItem->m_iId == WEAPON_MELEE ||
				pPlayer->m_pActiveItem->m_iId == WEAPON_SWORD) : false))
			{	// Call their swoop function to enable their melee hit
				if(pPlayer->m_Melee.GetEnemyPrepunch( m_pPlayer ))
				{	pPlayer->Swoop();
					return;
				}
			}
			else if((pPlayer->m_Melee.m_iConsecutiveHits < CONSECUTIVE_MELEEHITS) &&
					m_pPlayer->UseKi(BLOW_KICK_KI_COST))
			{	Vector vecDirection = m_pPlayer->m_Swoop.GetCurrentDirection();
				int iDirection = m_pPlayer->m_Swoop.m_iSwoopDirection;
				// Super punch
				fBlocked = m_pPlayer->m_Melee.Powerhit( pPlayer, vecDirection, iDirection );
			}
			else
			{
				// Set minimum next attack time
				m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.1;
			}
		}
		else // we are dealing with an enemy buddy
		{
			// their melee attack
			if(pBuddy->m_Swoop.bActive && (m_pPlayer == pBuddy->m_Melee.GetNearestPlayerToMelee(NULL)))
			{
				if(pBuddy->m_Melee.GetNearestPlayerToMelee( m_pPlayer ))
				{	
					pBuddy->m_Melee.HandleHeadOn(m_pPlayer);
					return;
				}
			}
			else if((pBuddy->m_Melee.m_iConsecutiveHits < CONSECUTIVE_MELEEHITS) &&
					m_pPlayer->UseKi(BLOW_KICK_KI_COST))
			{	Vector vecDirection = m_pPlayer->m_Swoop.GetCurrentDirection();
				int iDirection = m_pPlayer->m_Swoop.m_iSwoopDirection;
				// Super punch
				fBlocked = m_pPlayer->m_Melee.Powerhit( pBuddy, vecDirection, iDirection );
			}
		}

		if(fBlocked)
			m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.9;
		else
			m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.65;
	}
}
