#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "effects.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "aura.h"
#include "classes.h"
#include "gamerules.h"
#include "chargedattack.h"
#include "magicattack.h"
#include "explodingattack.h"
#include "player.h"
#include "beamattack.h"
#include "kiattack.h"
#include "blob.h"
#include "particletypes.h"
#define RENZOKU_PRIMARYKI_COST			50
#define RENZOKU_SECONDARYKI_COST		15
#define RENZOKU_PRIMARYDAMAGE			3
#define RENZOKU_SECONDARYDAMAGE			6
#define RENZOKU_PRIMARYSPEED			3000
#define RENZOKU_SECONDARYSPEED			2000
#define RENZOKU_SIZE					30
#define RENZOKU_TRAIL_LENGTH			250
#define RENZOKU_MAXBLOBSIZE				500
#define RENZOKU_MAXBLOBDMG				60

extern int gmsgAddEffect;
#define SHOOT_TIME 0.1

/**
* Renzoku Weapon
* @version 15-8-2001
* @author Herwin 'harSens' van Welbergen
*/
class CRenzoku:public CBasePlayerWeapon
{	
public:
	/**
	* Init function
	*/
	void Spawn( void );

	/**
	 * deploys the renzoku
	 */
	BOOL Deploy(void);

	/**
	 * Precaches sprites and sounds
	 */
	void Precache( void );

	/**
	 * charges
	 */
	void PrimaryAttack(void);

	/**
	 * Shoots a single kiblast
	 */
	void SecondaryAttack(void);	
	
	/**
	 * idle
	 */
	void WeaponIdle();

	/**
	 * Get  renzoku slot
	 * return int: the slot, is 2 for bigbang
	 */
	int iItemSlot( void ) { return 2; }

	/**
	* Get renzoku item info
	* @param ItemInfo *p: The ItemInfo gets stored here
	* @return int: Always returns 1 (why???)
	*/
	int GetItemInfo(ItemInfo *p);

	/**
	 * Holsters the renzoku
	 * @param int skiplocal: ?
	 */
	void Holster(int skiplocal);

	/**
	 * shoots multiple kiblasts
	 */
	void Shoot();

private:
	/**
	 * shoots a kiblast
	 */
	void ShootAttack();	

	/**
	 * emits the shooting sound
	 */
	void EmitShootSound();

	int m_fShootLeft;
	int m_fFiring;
	short m_sFlareA,m_sFlareB,m_sTrail;
	Vector m_vecShootAngle;
	Vector m_vecEnd;
};

LINK_ENTITY_TO_CLASS( weapon_renzoku, CRenzoku );

void CRenzoku::Spawn( void )
{	Precache();
	m_iId = WEAPON_RENZOKU;
	m_iDefaultAmmo = 0;
	m_iClip = -1;
	


	FallInit();// get ready to fall down.
}

void CRenzoku::Precache( void )
{	m_sFlareA=PRECACHE_MODEL("sprites/kiblasta.spr");
	m_sFlareB=PRECACHE_MODEL("sprites/kiblastb.spr");
	m_sTrail=PRECACHE_MODEL("sprites/kiblasttrail.spr");
	PRECACHE_SOUND("weapons/kiblast.wav");
	PRECACHE_SOUND("weapons/kiplosion.wav");
	PRECACHE_SOUND("vegeta/renzoku.wav");
}

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

BOOL CRenzoku::Deploy()
{	m_fShootLeft = false;
	m_fFiring = false;
	return DefaultDeploy( "renzoku" );	
}

void CRenzoku::Holster(int skiplocal)
{
	if(m_fFiring)
	{
		m_fFiring = false;
		UTIL_Model_RemoveAll(m_pPlayer->entindex());
		MESSAGE_BEGIN( MSG_ONE, gmsgAddEffect, NULL, m_pPlayer->edict() );
			WRITE_BYTE(LOCKCROSSHAIR);				
			WRITE_BYTE(0);				
		MESSAGE_END();	
	}
	CBasePlayerWeapon::Holster(skiplocal);
}

void CRenzoku::EmitShootSound()
{	
	/* sound for 1 shot, not a lot
	EmitClassSound("renzoku.wav");
	*/
	EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/kiblast.wav", 1.0, ATTN_NORM);
}

void CRenzoku::PrimaryAttack(void)
{	
	if(m_pPlayer->UseKi(RENZOKU_PRIMARYKI_COST))
	{
		if(!m_fFiring)
		{
			
			UTIL_Model_FixAngles(m_pPlayer->entindex());
			MESSAGE_BEGIN( MSG_ONE, gmsgAddEffect, NULL, m_pPlayer->edict() );
				WRITE_BYTE(LOCKCROSSHAIR);				
				WRITE_BYTE(1);				
			MESSAGE_END();
			m_vecShootAngle = m_pPlayer->pev->v_angle;
		}
		ShootAttack();
		m_fFiring = true;
	}
	else
	{
		if(m_fFiring)
		{
			m_fFiring = false;
			UTIL_Model_RemoveAll(m_pPlayer->entindex());
			MESSAGE_BEGIN( MSG_ONE, gmsgAddEffect, NULL, m_pPlayer->edict() );
				WRITE_BYTE(LOCKCROSSHAIR);				
				WRITE_BYTE(0);				
			MESSAGE_END();	
		}
	}

	m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + SHOOT_TIME;
}

void CRenzoku::SecondaryAttack(void)
{	
	if(!m_fFiring)
	{
		if (m_pPlayer->UseKi(RENZOKU_SECONDARYKI_COST))
		{	
			UTIL_MakeVectors( m_pPlayer->pev->v_angle );
			Vector vecSrc = (m_pPlayer->GetGunPosition() + gpGlobals->v_right * 10) + gpGlobals->v_forward.Normalize() * 5;
			Vector vecThrow = gpGlobals->v_forward * RENZOKU_SECONDARYSPEED;
			CKiAttack::ShootKiAttack( m_pPlayer->pev, vecSrc, vecThrow, RENZOKU_SECONDARYDAMAGE * GetPowerRatio(),m_sFlareA,m_sFlareB,m_sTrail);
			EmitShootSound();
			m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
		}	
	}
	m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.6;
}

void CRenzoku::WeaponIdle()
{	
	if(m_fFiring)
	{
		m_fFiring = false;
		UTIL_Model_RemoveAll(m_pPlayer->entindex());
		MESSAGE_BEGIN( MSG_ONE, gmsgAddEffect, NULL, m_pPlayer->edict() );
			WRITE_BYTE(LOCKCROSSHAIR);				
			WRITE_BYTE(0);				
		MESSAGE_END();	
		m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.6;
	}	 
}

void CRenzoku::ShootAttack()
{	//shoot it
	int dir = 0;//RANDOM_LONG(0,10);
	int up = 0;//RANDOM_LONG(-10,10);
	m_pPlayer->EmitClassSound("renzoku.wav");

	//choose shoot animation, shoot origin
	UTIL_MakeVectors(m_vecShootAngle); 

	Vector vecSrc;
	Vector vecThrow;
	if(m_fShootLeft)
	{	vecSrc = (m_pPlayer->GetGunPosition() + gpGlobals->v_right * 10) + gpGlobals->v_forward.Normalize() * 30;		
	}
	else
	{	vecSrc = (m_pPlayer->GetGunPosition() + gpGlobals->v_right * -10) + gpGlobals->v_forward.Normalize() * 30;		
	}
	
	TraceResult tr;
	if(!m_fFiring)
	{
		UTIL_TraceLine ( m_pPlayer->GetGunPosition(), m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 8192, dont_ignore_monsters, pev->owner, &tr );
		m_vecEnd = tr.vecEndPos;
	}
	Vector vecAiming = (m_vecEnd-vecSrc).Normalize();
	
	if(m_fShootLeft)
	{	vecThrow = gpGlobals->v_forward * KIBLAST_SPEED + gpGlobals->v_right * -dir + gpGlobals->v_up * up;
		m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
	}
	else
	{	vecThrow = gpGlobals->v_forward * KIBLAST_SPEED + gpGlobals->v_right * dir + gpGlobals->v_up * up;
		m_pPlayer->SetAnimation( PLAYER_ATTACK2 );
	}

	
	

	
	

	UTIL_TraceLine ( vecSrc, vecSrc + vecAiming * 8192, dont_ignore_monsters, pev->owner, &tr );

	CBaseEntity *pEnt=NULL;
	CBlob *pBlob=NULL;
	while ((pEnt = UTIL_FindEntityByClassname(pEnt, "kiblob")) != NULL)
	{
		CBlob *b = (CBlob*)pEnt;
		float flSize = b->m_iSize;
		if(flSize<BLOBATTACK_START_RADIUS)
		{
			flSize=BLOBATTACK_START_RADIUS;
		}
		if( (b->pev->origin-tr.vecEndPos).Length()<flSize)
		{
			pBlob = b;
			break;
		}
	}

	if(!pBlob)
	{	//not found, create a new blob
		pBlob = CBlob::CreateBlob(m_pPlayer,tr.vecEndPos,RENZOKU_PRIMARYDAMAGE,0,RENZOKU_MAXBLOBSIZE,RENZOKU_MAXBLOBDMG);
	}
	
	DelayedDamage *d = new DelayedDamage;
	d->pAttack = pBlob;
	d->damage = RENZOKU_PRIMARYDAMAGE;
	d->next = NULL;
	d->speed = RENZOKU_PRIMARYSPEED;
	d->flAddTime = gpGlobals->time;
	d->pOwner=m_pPlayer;
	pBlob->AddDelayedDamage(d);

	int iBend;
	if(m_fShootLeft)
	{
		iBend = BEND_LEFT;
	}
	else
	{
		iBend = BEND_RIGHT;
	}
	MESSAGE_BEGIN( MSG_ALL, gmsgAddEffect); 
		WRITE_BYTE(CLIENTBALL);
		WRITE_SHORT(m_pPlayer->entindex());
		WRITE_COORD(vecSrc.x);
		WRITE_COORD(vecSrc.y);
		WRITE_COORD(vecSrc.z);
		WRITE_COORD(tr.vecEndPos.x);
		WRITE_COORD(tr.vecEndPos.y);
		WRITE_COORD(tr.vecEndPos.z);
		WRITE_LONG(RENZOKU_PRIMARYSPEED);
		WRITE_SHORT(m_sFlareA);
		WRITE_SHORT(m_sFlareB);
		WRITE_SHORT(RENZOKU_SIZE*0.1);
		WRITE_SHORT(RENZOKU_TRAIL_LENGTH);
		WRITE_SHORT(m_sTrail);		
		WRITE_BYTE(iBend);
	MESSAGE_END();
	/*
	iEnt = READ_SHORT();
		vecOrigin.x = READ_COORD();
		vecOrigin.y = READ_COORD();
		vecOrigin.z = READ_COORD();
		vecEnd.x = READ_COORD();
		vecEnd.y = READ_COORD();
		vecEnd.z = READ_COORD();
		iSpeed = READ_LONG();
		iFlareA = READ_SHORT();
		iFlareB = READ_SHORT();	
		iWidth = READ_SHORT() * 10;
		iTrail = READ_SHORT();
	*/
	m_fShootLeft = !m_fShootLeft;
	//CKiAttack::ShootCurvedKiAttack( m_pPlayer->pev, vecSrc, vecThrow, KIBLAST_SECONDARYDAMAGE * GetPowerRatio(),m_sFlareA,m_sFlareB,m_sTrail);
}
