#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 "effects.h"
#include "magicattack.h"
#include "explodingattack.h"
#include "beamattack.h"
#include "guidedattack.h"
#include "controlledbeam.h"
extern int gmsgFlare;
#define BURNINGBALL_TRAILLENGTH 25
/**
 * burning ball attack
 * @version 18-2-2006
 * @author Herwin 'harSens' van Welbergen
 */
class CBurningBall:public CBeamAttack
{	
public:
	/**
	* Create a guided magical 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: Amount of damage the attack does
	* @param char *attack: Name of the attack
	* @param float size: relative size of the attack (0..1)
	* @param int trail: the sprite for the trailing beam
	* @param int starta: the sprite for the beam flare
	* @param int startb: the sprite for the beam flare
	* @param int flarea: the sprite for the beam start
	* @param int flareb: the sprite for the beam start
	* @param int radius: the radius for the beam
	* @return *CBurningBall: The created MagicAttack 
	*/
	static CBurningBall *ShootBurningBall( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, int damage,char *attack, float size, short trail, short starta, short startb, short flarea, short flareb, int radius);

	/**
	 * explodes and blinds
	 */
	virtual void Explode();
};

CBurningBall* CBurningBall::ShootBurningBall( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, int damage,char *attack, float size, short trail, short starta, short startb, short flarea, short flareb, int radius)
{	
	CBurningBall *pMagicAttack = GetClassPtr( (CBurningBall *)NULL );
	pMagicAttack->Spawn();
	pMagicAttack->m_fRemoveAfterExplode = true;

	//pMagicAttack->pev->movetype = MOVETYPE_FLYMISSILE;
	pMagicAttack->pev->movetype = MOVETYPE_FLY;
	pMagicAttack->pev->solid = SOLID_TRIGGER;	//touches everything

	//set dummy model	
	SET_MODEL(ENT(pMagicAttack->pev), "sprites/null.spr");

	pMagicAttack->m_iRadius = radius;
	pMagicAttack->m_iExplosionColor = YELLOW_EXPLOSION;
	
	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( attack );
	
	float flAttackSize = size * GUIDEDATTACK_SIZE * 0.25;//compensate for empty space in sprites
	
	Vector vecForward = flAttackSize * vecVelocity.Normalize();
	TraceResult tr;
	UTIL_TraceLine(vecStart, vecStart + vecForward,ignore_monsters,ENT(pevOwner),&tr);
	vecStart = vecStart + vecForward * tr.flFraction;
	
	UTIL_SetOrigin(pMagicAttack->pev,vecStart);
	UTIL_SetSize(pMagicAttack->pev, Vector(-flAttackSize, -flAttackSize, -flAttackSize), Vector(flAttackSize, flAttackSize, flAttackSize));
	pMagicAttack->SetTouch( &CBurningBall::ExplodeTouch );

	
	
	pMagicAttack->SetTouch( &CBurningBall::ExplodeTouch );

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

	pMagicAttack->SetThink( &CBurningBall::NormalThink );		
	EMIT_SOUND(ENT(pMagicAttack->pev), CHAN_WEAPON, "weapons/beamhead.wav", 1.0, ATTN_NORM);	
	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;
}
void CBurningBall::Explode()
{
	entvars_t *pevOwner;
	if ( pev->owner )
		pevOwner = VARS( pev->owner );
	else
		pevOwner = NULL;
	float radius = pev->dmg * BURNINGATTACK_BLINDINGRADIUS;
	::RadiusDamage( pev->origin, pev, pevOwner, pev->dmg, radius, CLASS_NONE, DMG_BLIND);
	CExplodingAttack::Explode();
}

/**
* Class wich handles guide magic attacks
* @version 13-4-2001
* @author Herwin 'harSens' van Welbergen
*/
class CBurningBeam : public CGuidedAttack
{
public:
	/**
	* Create a burningattack 
	* @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: Amount of damage the attack does
	* @param char *attack: Name of the attack
	* @param float size: relative size of the attack (0..1)
	* @param int r:
	* @param int g:
	* @param int b:explosion color in rgb
	* @param int trail: the sprite for the trailing beam
	* @param int starta: the sprite for the beam flare
	* @param int startb: the sprite for the beam flare
	* @param int flarea: the sprite for the beam start
	* @param int flareb: the sprite for the beam start
	* @param int radius: the radius for the beam
	* @return *CGuidedAttack: The created MagicAttack 
	*/
	static CBurningBeam *ShootBurningBeam( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, int damage, char *attack, float size, int explosioncolor, short trail, short starta, short startb, short flarea, short flareb, int radius, float turn,int attachment);

	/**
	 * explodes and blinds
	 */
	virtual void Explode();
};

CBurningBeam* CBurningBeam::ShootBurningBeam( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, int damage, char *attack, float size, int explosioncolor, short trail, short starta, short startb, short flarea, short flareb, int radius, float turn, int attachment)
{
	//HACK HACK: copypaste from guidedattack, to get the exploding working
	CBurningBeam *pMagicAttack = GetClassPtr( (CBurningBeam *)NULL );
	pMagicAttack->Spawn();
	pMagicAttack->m_fRemoveAfterExplode = false;

	//pMagicAttack->pev->movetype = MOVETYPE_FLYMISSILE;
	pMagicAttack->pev->movetype = MOVETYPE_FLY;
	pMagicAttack->pev->solid = SOLID_TRIGGER;	//touches everything

	//set dummy model
	SET_MODEL(ENT(pMagicAttack->pev), "sprites/null.spr");	
	
	pMagicAttack->m_iRadius = radius;
	//init colors
	pMagicAttack->m_iExplosionColor = YELLOW_EXPLOSION;
	
	pMagicAttack->m_flRateOfTurn = turn;

	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( attack );
	
	float flAttackSize = size * GUIDEDATTACK_SIZE * 0.25;//compensate for empty space in sprites
	
	Vector vecForward = flAttackSize * vecVelocity.Normalize();
	TraceResult tr;
	UTIL_TraceLine(vecStart, vecStart + vecForward,ignore_monsters,ENT(pevOwner),&tr);
	vecStart = vecStart + vecForward * tr.flFraction;
	
	UTIL_SetOrigin(pMagicAttack->pev,vecStart);
	UTIL_SetSize(pMagicAttack->pev, Vector(-flAttackSize, -flAttackSize, -flAttackSize), Vector(flAttackSize, flAttackSize, flAttackSize));
	pMagicAttack->SetTouch( &CBurningBeam::ExplodeTouch );

	pMagicAttack->SetThink( &CBurningBeam::FollowThink );
	pMagicAttack->pev->nextthink = gpGlobals->time;

	EMIT_SOUND(ENT(pMagicAttack->pev), CHAN_WEAPON, "weapons/beamhead.wav", 1.0, ATTN_NORM);

	pMagicAttack->AddEntEntTrail( (CBaseEntity::Instance(pevOwner))->entindex(), attachment, starta, startb, flarea, flareb, trail,size * GUIDEDATTACK_SIZE, 2,vecStart);

	/*DEBUG by harSens: enable bbox	
	extern int gmsgBoundingBox;
	MESSAGE_BEGIN( MSG_ALL, gmsgBoundingBox);
		WRITE_LONG(pMagicAttack->entindex());
	MESSAGE_END();		
	*/
	
	return pMagicAttack;	
}

void CBurningBeam::Explode()
{
	entvars_t *pevOwner;
	if ( pev->owner )
		pevOwner = VARS( pev->owner );
	else
		pevOwner = NULL;
	float radius = pev->dmg * BURNINGATTACK_BLINDINGRADIUS;
	::RadiusDamage( pev->origin, pev, pevOwner, pev->dmg, radius, CLASS_NONE, DMG_BLIND);
	CGuidedAttack::Explode();
}

/**
* Burning Attack Weapon
* @version : 31-10-2001
* @author Herwin 'harSens' van Welbergen
*/
class CBurningAttack:public CControlledBeam
{	
public:
	/**
	* Init function
	*/
	void Spawn( void );

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

	/**
	* Get burningattack slot
	* return int: the slot, is 4 for burning attack
	*/
	int iItemSlot( void ) { return 4; }

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

	/**
	 * Creates a new attack
	 * @param Vector vecSrc: the source of the beam
	 * @param Vector vecThrow: the direction of the new beam
	 * @param float flSize: size of the new beam
	 */
	void CreateBeam(Vector vecSrc, Vector vecThrow, float flSize);

	void SecondaryAttack();
	void PrimaryAttack();
	void Shoot();
private:
	/**
	* Emits charge sound
	*/
	virtual void EmitChargeSound();

	/**
	* Emits shoot sound
	*/
	virtual void EmitShootSound();

	int m_fChargeBall;
};

LINK_ENTITY_TO_CLASS( weapon_burningattack, CBurningAttack );

void CBurningAttack::Spawn( void )
{	Precache();
	m_eAttackState = ATTACK_IDLE; //not firing
	m_iCharge = 0;
	m_pMagic = NULL;
	m_iId = WEAPON_BURNINGATTACK;
	m_iDefaultAmmo = 0;
	m_iClip = -1;

	m_iMaxCharge = BURNINGATTACK_MAXCHARGETIME;
	m_iSpeed = BURNINGATTACK_SPEED;
	m_iKiCost = BURNINGATTACK_KI_COST;
	m_iDamage = BURNINGATTACK_DAMAGE;
	m_iRadius = BURNINGATTACK_RADIUS;
	m_flPlayerSlowdown = BURNINGATTACK_PLAYERSLOWDOWN;
	strcpy(m_pAttackName,"burningattack");

	m_flRateOfTurn = BURNINGATTACK_ROT;

	//explosion color
	m_iExplosionColor = YELLOW_EXPLOSION;
	m_iAttachment =	1;

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

void CBurningAttack::Precache( void )
{	m_sStartA = PRECACHE_MODEL("sprites/burningattackastart.spr");
	m_sStartB = PRECACHE_MODEL("sprites/burningattackbstart.spr");
	m_sFlareA = PRECACHE_MODEL("sprites/burningattacka.spr");
	m_sFlareB = PRECACHE_MODEL("sprites/burningattackb.spr");
	
	PRECACHE_SOUND("weapons/burning_fire.wav");
	PRECACHE_SOUND("weapons/burning_charge.wav");
	PRECACHE_SOUND("trunks/burning_charge.wav");
	PRECACHE_SOUND("trunks/burning.wav");
	m_sTrail = PRECACHE_MODEL("sprites/burningattacktrail.spr");

	CControlledBeam::Precache();
}

int CBurningAttack::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 = 3;
	p->iId = m_iId = WEAPON_BURNINGATTACK;
	p->iWeight = BURNINGATTACK_WEIGHT;
	p->iFlags = 0;
	return 1;
}

void CBurningAttack::CreateBeam(Vector vecSrc, Vector vecThrow, float flSize)
{
	m_pMagic = CBurningBeam::ShootBurningBeam( m_pPlayer->pev, vecSrc, vecThrow, m_iCharge * m_iDamage * GetPowerRatio(),m_pAttackName ,flSize, m_iExplosionColor, m_sTrail, m_sStartA, m_sStartB, m_sFlareA, m_sFlareB, m_iRadius, m_flRateOfTurn,m_iAttachment);
}

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

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


void CBurningAttack::PrimaryAttack()
{	m_fChargeBall = false;
	CControlledBeam::PrimaryAttack(); 	
}

void CBurningAttack::SecondaryAttack()
{	if(m_eAttackState != ATTACK_AIM)
	{	m_fChargeBall = true;
		Charge();
		m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + CHARGETIME;
	}
	else
	{	CControlledBeam::SecondaryAttack();
	}
}

void CBurningAttack::Shoot()
{
	if(!m_fChargeBall)
	{	CControlledBeam::Shoot();
		return;
	}

	m_fChargeBall = false;
	m_pPlayer->DrawChargeBar(0); // disable charge bar
	//silence charge sounds
	SilenceWeaponSounds();		
	m_pPlayer->m_fCharging = false;	
	m_eAttackState=ATTACK_IDLE;		
	//charge to low?
	if (m_iCharge<m_iMaxCharge/3)
	{	m_pPlayer->m_flSlowDown = 1.0;
		SilenceVoice();
		return;
	}
	m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
	DisableChargeSprite();
	EmitShootSound();
	UTIL_MakeVectors( m_pPlayer->pev->v_angle );
	Vector vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_forward * 10;
	Vector vecThrow = gpGlobals->v_forward * m_iSpeed;
	float flSize = (float)m_iCharge/(float)m_iMaxCharge;	
	CBurningBall::ShootBurningBall( m_pPlayer->pev, vecSrc, vecThrow, m_iCharge * GENERICBALL_DAMAGE * GetPowerRatio(),m_pAttackName ,flSize, m_sTrail, m_sStartA, m_sStartB, m_sFlareA, m_sFlareB, m_iRadius);
}
