#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 "animation.h"
#include "decals.h"
#include "effects.h"
#include "customentity.h"

#define ATTACH_LEFTEYE 2
#define ATTACH_RIGHTEYE 3
#define BURST_DELAY 2.0		//2 seconds delay after a burst
#define MAX_BURST 5			//1 second bursts
#define LASER_WIDTH 3
/**
* Piccolo's eyelaser
* @version 8-6-2001
* @author Herwin 'harSens' van Welbergen
*/
class CEyelaser:public CBasePlayerWeapon
{	
public:
	/**
	* Init function
	*/
	void Spawn( void );

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

	/**
	* Get eyelaser slot
	* return int: the slot, is 5 for eyelaser
	*/
	int iItemSlot( void ) { return 5; }

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

	/**
	* Shoots a eyelaser attack
	*/
	void PrimaryAttack( void );

	/**
	* Stops shooting the eyelaser
	*/
	void SecondaryAttack( void );

	/**
	* Called when eyelaser is selected as weapon
	*/
	BOOL Deploy( void );

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

	/**
	* Weapon idle function
	*/
	void WeaponIdle();
private:
	/**
	* Shoots a laser between begin and en position
	* @param laser: the laser beam
	* @param Vector begin: begin position for the laser
	* @param Vector end: end position for the laser
	*/
	void ShootLaser(CBeam *laser, Vector begin, Vector end);

	/**
	* Creates the laser beam
	* @param attachment:to wich attachment to add?
	*/
	CBeam *CreateLaser(int attachment);

	/**
	* Destroy a laser beam
	* @param laser:the laser to destroy
	*/
	void DestroyLaser(CBeam *laser);

	/**
	* Set red eyes instead of beam
	* @param laser:the laser to turn into red eye status
	*/
	void SetRedEye(CBeam *laser);

	/**
	* Set laser beam instead of red eyes
	* @param laser:the laser to turn into beam status
	*/
	void SetBeam(CBeam *laser);

	CBeam *m_pLeftLaser;		//eyelaser beams
	CBeam *m_pRightLaser;		//
	BOOL m_fShooting;			//true when shooting
	int m_iBurst;
	// Added by Pcjoe
	bool m_blFirstfire;			//first time the player fired the attack
};

LINK_ENTITY_TO_CLASS( weapon_eyelaser, CEyelaser );

void CEyelaser::Spawn( void )
{	Precache();
	m_iId = WEAPON_EYELASER;
	m_iDefaultAmmo = 0;
	m_iClip = -1;
	m_pLeftLaser = NULL;
	m_pRightLaser = NULL;
	m_fShooting = false;
	// added by Pcjoe
	m_blFirstfire = false;
	FallInit();// get ready to fall down.
}

void CEyelaser::Precache( void )
{	PRECACHE_MODEL("sprites/eyelaser.spr");
	PRECACHE_SOUND("weapons/melt.wav");		
	PRECACHE_SOUND("weapons/eyebeam_fire.wav");
}

int CEyelaser::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 = 4;
	p->iPosition = 2;
	p->iId = m_iId = WEAPON_EYELASER;
	p->iWeight = EYELASER_WEIGHT;
	p->iFlags = 0;
	return 1;
}

BOOL CEyelaser::Deploy( void )
{	m_pLeftLaser = CreateLaser(ATTACH_LEFTEYE);
	m_pRightLaser = CreateLaser(ATTACH_RIGHTEYE);
	
	//create beam effect between the eyes for red eye fx
	m_pLeftLaser->SetStartAttachment(ATTACH_RIGHTEYE);
	m_pRightLaser->SetStartAttachment(ATTACH_LEFTEYE);
	m_iBurst=0;

	return DefaultDeploy( "eyelaser" );	
}

void CEyelaser::WeaponIdle()
{	if (m_fShooting)
	{	//color the eyes red
		SetRedEye(m_pLeftLaser);
		SetRedEye(m_pRightLaser);
		m_fShooting = false;
		m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + BURST_DELAY * (float)m_iBurst/(float)MAX_BURST;
		m_iBurst=0;		
	}	
	// Added by Pcjoe
	if(m_blFirstfire)
		m_blFirstfire = false;
}

void CEyelaser::ShootLaser(CBeam *laser,Vector begin, Vector end)
{	//calculate real end position
	TraceResult tr;
	Vector vecAiming = end - begin;
	vecAiming.Normalize();
	
	entvars_s *pIgnoreEnt = m_pPlayer->pev;
	Vector vecStart = begin;
	Vector vecEnd = begin + vecAiming * EYELASER_RADIUS;

	//ignore aura's
	/* harSens: shouldn't be necesary*/
	do
	{
		UTIL_TraceLine (vecStart, vecEnd, dont_ignore_monsters, ENT(pIgnoreEnt), &tr );
		vecStart = tr.vecEndPos;
		pIgnoreEnt = VARS(tr.pHit);			
	}
	while(VARS(pIgnoreEnt->owner)==m_pPlayer->pev&&tr.flFraction<1.0);
	
	
	//draw laser beam
	laser->SetStartPos(tr.vecEndPos);
		
	//draw smoke clouds
	MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, tr.vecEndPos );
		WRITE_BYTE( TE_SMOKE );
		WRITE_COORD( tr.vecEndPos.x );
		WRITE_COORD( tr.vecEndPos.y );
		WRITE_COORD( tr.vecEndPos.z );
		WRITE_SHORT( g_sModelIndexSmoke );
		WRITE_BYTE( 2 ); // scale * 10
		WRITE_BYTE( 5 ); // framerate
	MESSAGE_END();

	//make holes in da ground
	UTIL_DecalTrace( &tr, DECAL_GUNSHOT1 );

	//do damage if hit a player
	CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
	// Edited by Pcjoe, reduce damage by 50% if the player is being "tossed"
	float flReduction = 1;
	if(pEntity && pEntity->IsPlayer())
	{	CBasePlayer *pPlayer = (CBasePlayer*)pEntity;
		if(pPlayer->m_Melee.InThrow())
		{	if(pPlayer->m_Melee.SpecialLaserReduction())
			{	flReduction = (2/3);
			}
			else
			{	flReduction = .5;
			}
		}
	}
	pEntity->TakeDamage(m_pPlayer->pev,m_pPlayer->pev,EYELASER_DAMAGE * GetPowerRatio() * (1-tr.flFraction) * flReduction,DMG_MAGIC);	
	// end of edit by Pcjoe

	//emit melting sound
	EMIT_SOUND(ENT(pEntity->pev), CHAN_WEAPON, "weapons/melt.wav", 1.0, ATTN_NORM);
}

void CEyelaser::SetRedEye(CBeam *laser)
{	laser->SetType( BEAM_ENTS );
	laser->RelinkBeam();
}

void CEyelaser::SetBeam(CBeam *laser)
{	laser->SetType( BEAM_ENTPOINT );
	laser->RelinkBeam();
}

CBeam *CEyelaser::CreateLaser(int attachment)
{	CBeam *pLaser = CBeam::BeamCreate("sprites/eyelaser.spr",LASER_WIDTH);
	pLaser->pev->rendermode = kRenderTransAdd;
	pLaser->SetBrightness(255);
	pLaser->SetEndEntity(m_pPlayer->entindex());
	pLaser->SetEndAttachment(attachment);
	pLaser->SetStartEntity(m_pPlayer->entindex());
	SetRedEye(pLaser);
	return pLaser;
}

void CEyelaser::DestroyLaser(CBeam *laser)
{	if ( laser )
	{	UTIL_Remove( laser );
		laser = NULL;
	}
}

void CEyelaser::Holster(int skiplocal)
{	DestroyLaser(m_pLeftLaser);
	DestroyLaser(m_pRightLaser);
	// added by Pcjoe
	m_blFirstfire = false;
}

void CEyelaser::PrimaryAttack( void )
{	// Check we have some ammo
	if (!m_pPlayer->UseKi(EYELASER_KI_COST))
	{	if (m_fShooting)
		{	//color the eyes red
			SetRedEye(m_pLeftLaser);
			SetRedEye(m_pRightLaser);
			m_fShooting = false;
		}
		return;
	}

	if (!m_fShooting)
	{	SetBeam(m_pLeftLaser);
		SetBeam(m_pRightLaser);
		m_fShooting = true;
	}

	// Added by Pcjoe, play beam sound
	if(!m_blFirstfire)
	{
		m_blFirstfire = true;
		EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/eyebeam_fire.wav", 1.0, ATTN_NORM);
	}

	//calculate eye position and eye width
	Vector vecLeftEyePos = m_pLeftLaser->GetEndPos();
	Vector vecRightEyePos = m_pRightLaser->GetEndPos();
	
	//calculate crosshair pos
	UTIL_MakeVectors(m_pPlayer->pev->v_angle);
	Vector vecAiming = gpGlobals->v_forward;
	Vector vecSrc = m_pPlayer->GetGunPosition();
	TraceResult tr;
	UTIL_TraceLine (vecSrc,vecSrc + vecAiming * 8192, dont_ignore_monsters, ENT(pev), &tr );
	Vector vecLeftLaser = tr.vecEndPos - gpGlobals->v_right * 2;
	Vector vecRightLaser = tr.vecEndPos + gpGlobals->v_right * 2;

	//shoot the 2 lasers
	ShootLaser(m_pLeftLaser,vecLeftEyePos,vecLeftLaser);
	ShootLaser(m_pRightLaser,vecRightEyePos,vecRightLaser);
	if (m_iBurst<MAX_BURST)
	{	m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + CHARGETIME;
		m_iBurst++;
	}
	else
	{	WeaponIdle();		
	}
}

void CEyelaser::SecondaryAttack()
{	//ignore pressing of secondary attack.
	WeaponIdle();
}


