#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "effects.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 "magicattack.h"
#include "explodingattack.h"
#include "beamattack.h"
#define SBC_BEAMWIDTH 20
#define SBC_ORBIT_BEAMWIDTH 15

extern int gmsgSBCTrail;
/**
 * special beam cannon attack
 * @version 30-3-2002
 * @author Herwin 'harSens' van Welbergen
 */
class CSpecialBeamCannonAttack:public CBeamAttack
{	
public:
	/**
	* Create a Sbc 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 int damage: the amount of damage the attack does
	* @param int beamsprite: the sprite for the beam
	* @return *CMagicAttack: The created MagicAttack 
	*/	
	static CSpecialBeamCannonAttack* ShootSbc( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, int damage, short trail, short flarea, short flareb,short orbittrail,short orbitflarea,short orbitflareb,int radius);	
protected:
	/**
	 * Check if this attack can vaporize a player
	 * @return 1 if this attack can vaporize a player, 0 otherwise
	 */
	virtual int CanVaporizePlayer(){return 1;}
};

CSpecialBeamCannonAttack* CSpecialBeamCannonAttack::ShootSbc( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, int damage, short trail, short flarea, short flareb,short orbittrail,short orbitflarea,short orbitflareb,int radius)
{	CSpecialBeamCannonAttack *pMagicAttack = GetClassPtr( (CSpecialBeamCannonAttack *)NULL );
	pMagicAttack->Spawn();	
	
	pMagicAttack->pev->movetype = MOVETYPE_FLY;
	pMagicAttack->pev->solid = SOLID_TRIGGER;	//touches everything

	SET_MODEL(ENT(pMagicAttack->pev), "sprites/null.spr");
	
	pMagicAttack->m_iRadius = radius;
	pMagicAttack->m_iExplosionColor = ORANGE_EXPLOSION;
	
	pMagicAttack->SetDamage(damage); 
	UTIL_SetOrigin(pMagicAttack->pev,vecStart+32*vecVelocity.Normalize());
	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("Special Beam Cannon");

	UTIL_SetSize(pMagicAttack->pev, Vector(-32, -32, -32), Vector(32, 32, 32));

	MESSAGE_BEGIN( MSG_ALL, gmsgSBCTrail, NULL );
		WRITE_BYTE( (CBaseEntity::Instance(pevOwner))->entindex());
		WRITE_LONG( pMagicAttack->entindex() );	//entity to follow
		WRITE_BYTE(1);
		WRITE_SHORT(flarea);	
		WRITE_SHORT(flareb);
		WRITE_SHORT(trail);					//trail
		WRITE_BYTE(SBC_BEAMWIDTH * 0.1);	//width (variable width later on?)

		WRITE_SHORT(orbitflarea);	
		WRITE_SHORT(orbitflareb);
		WRITE_SHORT(orbittrail);		
		WRITE_BYTE(SBC_ORBIT_BEAMWIDTH * 0.1);
	MESSAGE_END();

	pMagicAttack->SetTouch( &CSpecialBeamCannonAttack::ExplodeTouch );
	pMagicAttack->SetThink( &CSpecialBeamCannonAttack::NormalThink );
	pMagicAttack->pev->nextthink = gpGlobals->time;

	return pMagicAttack;
}

//--------------------------------------------------------------

/**
* Special Beam Cannon Weapon
* @version 17-6-2001
* @author Herwin 'harSens' van Welbergen
*/
class CSpecialBeamCannon:public CChargedAttack
{	
public:
	/**
	* Init function
	*/
	void Spawn( void );

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

	/**
	* Get specialbeamcannon slot
	* return int: the slot, is 4 for special beam cannon
	*/
	int iItemSlot( void ) { return 4; }

	/**
	* Get special beam cannon item info
	* @param ItemInfo *p: The ItemInfo gets stored here
	* @return int: Always returns 1 (why???)
	*/
	int GetItemInfo(ItemInfo *p);
private:
	/**
	* emits the shoot sound
	*/
	void EmitShootSound();

	/**
	* emits the charge sound
	*/
	void EmitChargeSound();
	
	/**
	* inits the chargesprite
	*/
	void InitChargeSprite();
	
	/**
	* removes the chargesprite
	*/
	void RemoveChargeSprite();
	
	/**
	 * grows the chargesprite
	 */
	void GrowChargeSprite();

	/**
	* enables the chargesprite
	*/
	void EnableChargeSprite();
	
	/**
	* disables the chargesprite
	*/
	void DisableChargeSprite();
	
	/**
	* shoots a sbc
	*/
	void ShootAttack();
	CSprite *m_pChargeSprite;		//the sprites wich appears after charging
	short m_sTrail,m_sOrbitTrail;	//the trail sprite
	short m_sFlareA,m_sFlareB,m_sOrbitFlareA,m_sOrbitFlareB;	
};

LINK_ENTITY_TO_CLASS( weapon_specialbeamcannon, CSpecialBeamCannon );

void CSpecialBeamCannon::Spawn( void )
{	Precache();
	m_iId = WEAPON_SPECIALBEAMCANNON;
	m_iDefaultAmmo = 0;
	m_iClip = -1;
	m_iMaxCharge = SPECIALBEAMCANNON_MAXCHARGETIME;
	m_iKiCost = SPECIALBEAMCANNON_KI_COST;
	m_flPlayerSlowDown = 0.5;
	strcpy(m_pAttackName,"specialbeamcannon");
	FallInit();// get ready to fall down.
}

void CSpecialBeamCannon::Precache( void )
{	PRECACHE_SOUND("piccolo/specialbeamcannon.wav");
	PRECACHE_SOUND("cell/specialbeamcannon.wav");
	PRECACHE_SOUND("cell2/specialbeamcannon.wav");
	PRECACHE_SOUND("weapons/sbc_fire.wav");
	PRECACHE_SOUND("weapons/sbc_charge.wav");
	PRECACHE_MODEL("sprites/sbccharge.spr");
	PRECACHE_MODEL("sprites/null.spr");
	m_sTrail = PRECACHE_MODEL("sprites/sbctrail.spr");
	m_sOrbitTrail = PRECACHE_MODEL("sprites/sbcorbittrail.spr");
	m_sFlareA = PRECACHE_MODEL("sprites/sbca.spr");
	m_sFlareB = PRECACHE_MODEL("sprites/sbcb.spr");
	m_sOrbitFlareA = PRECACHE_MODEL("sprites/sbcorbita.spr");
	m_sOrbitFlareB = PRECACHE_MODEL("sprites/sbcorbitb.spr");
}

int CSpecialBeamCannon::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 = 3;
	p->iPosition = 2;
	p->iId = m_iId = WEAPON_SPECIALBEAMCANNON;
	p->iWeight = SPECIALBEAMCANNON_WEIGHT;
	p->iFlags = 0;
	return 1;
}

void CSpecialBeamCannon::InitChargeSprite()
{	m_pChargeSprite = CSprite::SpriteCreate( "sprites/sbccharge.spr", m_pPlayer->pev->origin, true);
	m_pChargeSprite->SetAttachment(m_pPlayer->edict(),1);
	m_pChargeSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 254, kRenderFxGlowShell );
	m_pChargeSprite->SetScale(0.2);
	m_pChargeSprite->pev->framerate = 10;
	m_pChargeSprite->TurnOff();	
}

void CSpecialBeamCannon::RemoveChargeSprite()
{	UTIL_Remove(m_pChargeSprite);
}

void CSpecialBeamCannon::DisableChargeSprite()
{	m_pChargeSprite->TurnOff();
}

void CSpecialBeamCannon::GrowChargeSprite()
{	m_pChargeSprite->SetScale( (float)m_iCharge/(float)m_iMaxCharge*0.15);
}

void CSpecialBeamCannon::EnableChargeSprite()
{	m_pChargeSprite->SetScale( (float)m_iCharge/(float)m_iMaxCharge*0.15);
	m_pChargeSprite->TurnOn();
}

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

void CSpecialBeamCannon::EmitChargeSound()
{	EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/sbc_charge.wav", 1.0, ATTN_NORM);
}

void CSpecialBeamCannon::ShootAttack()	
{	//calculate startpos and speed
	UTIL_MakeVectors( m_pPlayer->pev->v_angle );
	Vector vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 10;
	Vector vecThrow = gpGlobals->v_forward * SPECIALBEAMCANNON_SPEED;
	
	//shoot the magic
	CSpecialBeamCannonAttack::ShootSbc( m_pPlayer->pev, vecSrc ,vecThrow, m_iCharge * SPECIALBEAMCANNON_DAMAGE * GetPowerRatio(),m_sTrail,m_sFlareA,m_sFlareB, m_sOrbitTrail, m_sOrbitFlareA, m_sOrbitFlareB,SPECIALBEAMCANNON_RADIUS);
}