#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"

#define FINISHINGBUSTER_SIZE			50
#define FINISHINGBUSTER_TRAILLENGTH		80
extern int gmsgFlare;
/**
 * Finishing buster attack
 * @version 9-7-2002
 * @author Herwin 'harSens' van Welbergen
 */
class CFinishingBusterAttack:public CBeamAttack
{	
public:
	/**
	 * Create a fb attack 
	 * @param entvars_t *pevOwner: Monster/Player who shoots it
	 * @param Vector vecStart: Origin vector of the attack
	 * @param Vector vecVelocity: Velocity of the attack
	 * @param damage: the amount of damage to be done
	 * @param size: the size of the finishing buster sprite
	 */
	static CFinishingBusterAttack *ShootFinishingBuster( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, int damage, float size,short flarea,short flareb,short trail);
};

CFinishingBusterAttack* CFinishingBusterAttack::ShootFinishingBuster( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, int damage, float size,short flarea,short flareb,short trail)
{	CFinishingBusterAttack *pMagicAttack = GetClassPtr( (CFinishingBusterAttack*)NULL );
	pMagicAttack->Spawn();	
	
	pMagicAttack->pev->movetype = MOVETYPE_FLY;
	pMagicAttack->pev->solid = SOLID_TRIGGER;	//touches everything

	//set model
	SET_MODEL(ENT(pMagicAttack->pev), "sprites/null.spr");
	
	pMagicAttack->m_iExplosionColor = BLUE_EXPLOSION;
	
	pMagicAttack->m_iRadius = FINISHINGBUSTER_RADIUS;

	pMagicAttack->SetDamage(damage);
	pMagicAttack->pev->velocity=vecVelocity;
	pMagicAttack->m_flSpeed=vecVelocity.Length();
	pMagicAttack->pev->angles=UTIL_VecToAngles(pMagicAttack->pev->velocity);
	pMagicAttack->pev->owner=ENT(pevOwner);
	pMagicAttack->pev->classname = MAKE_STRING( "finishingbuster" );
		
	float flSize = FINISHINGBUSTER_SIZE * size;
	float flAttackSize = flSize * 0.25;	//compensate for empty space in sprites
	UTIL_SetOrigin(pMagicAttack->pev,vecStart + flAttackSize * vecVelocity.Normalize());
	UTIL_SetSize(pMagicAttack->pev, Vector(-flAttackSize, -flAttackSize, -flAttackSize), Vector(flAttackSize, flAttackSize, flAttackSize));
	pMagicAttack->SetTouch(&CFinishingBusterAttack::ExplodeTouch );

	UTIL_SetOrigin(pMagicAttack->pev,vecStart + flAttackSize * vecVelocity.Normalize());
	
	MESSAGE_BEGIN( MSG_ALL, gmsgFlare, NULL );
		WRITE_LONG(pMagicAttack->entindex());				//end entity
		WRITE_SHORT(flarea);								//start attachment
		WRITE_SHORT(flareb);								//start sprites
		WRITE_SHORT( flSize * 0.1);							//size in .1's
		WRITE_SHORT(trail);									//trail sprite
		WRITE_SHORT(FINISHINGBUSTER_TRAILLENGTH * size);	//trail length
		WRITE_COORD(vecStart.x);							//start pos
		WRITE_COORD(vecStart.y);
		WRITE_COORD(vecStart.z);
	MESSAGE_END();

	// make monsters/players afraid of it while in the air
	pMagicAttack->SetThink( &CFinishingBusterAttack::NormalThink );
	pMagicAttack->pev->nextthink = gpGlobals->time;

	/*DEBUG by harSens: enable bbox	
	extern int gmsgBoundingBox;
	MESSAGE_BEGIN( MSG_ALL, gmsgBoundingBox);
		WRITE_LONG(pMagicAttack->entindex());
	MESSAGE_END();		
	*/
	
	return pMagicAttack;
}
//--------------------------------------------------------------
/**
 * Finishing Buster
 * @version 15-8-2001
 * @author Herwin 'harSens' van Welbergen
 */
class CFinishingBuster:public CChargedAttack
{	
public:
	/**
	 * Init function
	 */
	void Spawn( void );

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

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

	/**
	 * Get finishingbuster item info
	 * @param ItemInfo *p: The ItemInfo gets stored here
	 * @return int: Always returns 1 (why???)
	 */
	int GetItemInfo(ItemInfo *p);
private:
	/**
	 * shoots the finishing buster
	 */
	void ShootAttack();

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

	/**
	 * emits the charging sound
	 */
	void EmitChargeSound();
	short m_sFlareA,m_sFlareB,m_sTrail;
};

LINK_ENTITY_TO_CLASS( weapon_finishingbuster, CFinishingBuster );

void CFinishingBuster::Spawn( void )
{	Precache();
	m_iId = WEAPON_FINISHINGBUSTER;
	m_iDefaultAmmo = 0;
	m_iClip = -1;

	m_iMaxCharge = FINISHINGBUSTER_MAXCHARGETIME;
	m_iKiCost = FINISHINGBUSTER_KI_COST;
	m_flPlayerSlowDown = 0.0;
	strcpy(m_pAttackName,"finishingbuster");
	FallInit();// get ready to fall down.
}

void CFinishingBuster::Precache( void )
{	m_sFlareA = PRECACHE_MODEL("sprites/finishingbustera.spr");	
	m_sFlareB = PRECACHE_MODEL("sprites/finishingbusterb.spr");
	m_sTrail = PRECACHE_MODEL("sprites/finishingbustertrail.spr");	
	PRECACHE_SOUND("weapons/buster_fire.wav");
	PRECACHE_SOUND("trunks/buster.wav");
	PRECACHE_SOUND("trunks/buster_charge.wav");
}

int CFinishingBuster::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 = 6;
	p->iId = m_iId = WEAPON_FINISHINGBUSTER;
	p->iWeight = FINISHINGBUSTER_WEIGHT;
	p->iFlags = 0;
	return 1;
}

void CFinishingBuster::EmitShootSound()
{	m_pPlayer->EmitClassSound("buster.wav");
	EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/buster_fire.wav", 1.0, ATTN_NORM);
}

void CFinishingBuster::EmitChargeSound()
{	m_pPlayer->EmitClassSound("buster_charge.wav");	
}

void CFinishingBuster::ShootAttack()	
{	//shoot the attack
	UTIL_MakeVectors( m_pPlayer->pev->v_angle );
	Vector vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_right * 10 + gpGlobals->v_forward * 10;
	Vector vecThrow = gpGlobals->v_forward * FINISHINGBUSTER_SPEED;
	CFinishingBusterAttack::ShootFinishingBuster( m_pPlayer->pev, vecSrc, vecThrow, m_iCharge * FINISHINGBUSTER_DAMAGE * GetPowerRatio() , (float)m_iCharge/(float)FINISHINGBUSTER_MAXCHARGETIME,m_sFlareA,m_sFlareB,m_sTrail);
}