#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 "magicattack.h"
#include "explodingattack.h"
#include "player.h"
#include "gamerules.h"
#include "../common/particletypes.h"
extern int gmsgAddEffect;

class CAttachedBodyPart:public CBaseMonster
{

};

/**
* Body part attack
* @version 10-9-2002
* @author Herwin 'harSens' van Welbergen
*/
class CBodyPartAttack:public CMagicAttack
{	
public:
	/**
	 * Create a bodypart
	 * @param entvars_t *pevOwner: Monster/Player who shoots it
	 * @param Vector vecStart: Origin vector of the attack
	 * @param Vector vecVelocity: Velocity of the attack
	 */
	static CBodyPartAttack *ShootBodyPart( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity);

	/**
	 * the bodypart is touched by another entity
	 * @param CBaseEntity *pOther: the one touching the bodypart
	 */
	void EXPORT StickyTouch(CBaseEntity *pOther);

	/**
	 * Strangle a player
	 */
	void EXPORT StrangleThink();

	/**
	 * spawn
	 */
	void Spawn();
private:
	CBasePlayer *m_pVictim;
};

void CBodyPartAttack::Spawn( void )
{	Precache();	
	pev->globalname = MAKE_STRING("magic_attack");	
}

void CBodyPartAttack::StrangleThink()
{
	if (!m_pVictim->m_fStrangled)
	{	m_pVictim->m_fStrangled = true;			
		m_pVictim->SetAnimation(PLAYER_WRAP);		
		pev->gaitsequence = 0;
		pev->frame = 0;
		pev->sequence = LookupSequence( "struggle" );
		ResetSequenceInfo ( );		
		m_pVictim->m_flSlowDown = 0.0;
	}
			
	if(m_pVictim->pev->fuser4>750)
	{
		ALERT(at_console,"unstrangled\n");
		if(m_pVictim->m_fStrangled)
		{
			m_pVictim->m_fStrangled = false;
			m_pVictim->m_flSlowDown = 1.0;
		}
		MESSAGE_BEGIN( MSG_ALL, gmsgAddEffect);
			WRITE_BYTE(BODYPARTSPLASH);
			WRITE_SHORT(m_pVictim->entindex());			
		MESSAGE_END();	

		//cheap gibs
		
		Remove();
	}
	else if (!m_pVictim->IsAlive())
	{	Remove();
	}
	else
	{
		m_pVictim->TakeDamage(pev,VARS(pev->owner),BODYPART_DAMAGE,DMG_MAGIC);				
	}
	pev->nextthink=gpGlobals->time+0.2;
}

void CBodyPartAttack::StickyTouch(CBaseEntity *pOther)
{
	//find who's the owner
	entvars_t *pevOwner;
	if (pev->owner)
	{	pevOwner = VARS(pev->owner);
	}
	else
	{	pevOwner=NULL;
	}	
	//don't hit your owner
	if (pevOwner == pOther->pev)
	{	//return;
	}

	if(pOther->IsPlayer())
	{
		ALERT(at_console,"You have been strangled\n");
		CBasePlayer *pPlayer = (CBasePlayer*)pOther;
		if(!pPlayer->m_fBlock && !pPlayer->m_fPowerStruggling && !pPlayer->m_fBlockStruggling && !pPlayer->m_fStrangled)
		{
			//SET_MODEL(ENT(pev), "models/bodypart_medium.mdl");
			SET_MODEL(ENT(pev), "models/bodypart_large.mdl");
			pev->solid = SOLID_NOT;
			pev->origin = pPlayer->pev->origin;
			UTIL_SetOrigin(pev,pev->origin);
			pev->aiment = pPlayer->edict();
			pev->movetype = MOVETYPE_FOLLOW;
			//pev->owner = pPlayer->edict();
			
			m_pVictim = pPlayer;
			SetTouch(NULL);
			
			pev->gaitsequence = 0;
			pev->frame = 0;
			pev->sequence = LookupSequence( "wrap" );
			ResetSequenceInfo ( );
			SetThink(&CBodyPartAttack::StrangleThink);
			pev->nextthink=gpGlobals->time+GetAnimTime(pev->sequence);						
		}
	}
	else
	{
		pev->gaitsequence = 0;
		pev->frame = 0;
		pev->sequence = 0;//LookupSequence( "bodypart_fly" );
		ResetSequenceInfo ( );
		pev->velocity = Vector(0,0,0);
		pev->avelocity = Vector(0,0,0);
		SUB_StartFadeOut();
	}
}

CBodyPartAttack* CBodyPartAttack::ShootBodyPart( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity)
{	CBodyPartAttack *pMagicAttack = GetClassPtr( (CBodyPartAttack *)NULL );
	pMagicAttack->Spawn();	
	
	pMagicAttack->pev->movetype = MOVETYPE_TOSS;
	pMagicAttack->pev->solid = SOLID_TRIGGER;	//touches everything
	pMagicAttack->pev->gravity = 0.000000001;//0.2;	
	pMagicAttack->pev->gaitsequence = 0;
	pMagicAttack->pev->frame = 0;
	pMagicAttack->pev->sequence = pMagicAttack->LookupSequence( "bodypart_fly" );
	pMagicAttack->ResetSequenceInfo ( );
	
	//set model
	SET_MODEL(ENT(pMagicAttack->pev), "models/bodypart.mdl");
	pMagicAttack->pev->rendermode = kRenderNormal;
	
	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( "bodypart" );
	
	UTIL_SetOrigin(pMagicAttack->pev,vecStart);
	UTIL_SetSize(pMagicAttack->pev, Vector(-10, -10, -10), Vector(10, 10, 10));
	pMagicAttack->SetTouch(&CBodyPartAttack::StickyTouch);

	pMagicAttack->SetThink( &CBodyPartAttack::NormalThink );
	pMagicAttack->pev->nextthink = gpGlobals->time;
	
	return pMagicAttack;
}

/**
* Bodypart weapon
* @version 10-9-2002
* @author Herwin 'harSens' van Welbergen
*/
class CBodyPart:public CBasePlayerWeapon
{	
public:
	/**
	* Init function
	*/
	void Spawn( void );

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

	/**
	 * Deploys the bodypart attack
	 * @return BOOL: true if succesfully deployed
	 */
	BOOL Deploy();

	/**
	 * Holsters attack
	 * @param skiplocal:?
	 */
	void Holster(int skiplocal = 0);


	/**
	* Get  bodypart slot
	* return int: the slot, is 6 for bodypart attack
	*/
	int iItemSlot( void ) { return 6; }

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

	/**
	* Shoots a bodypart
	*/
	void PrimaryAttack( void );	
};

LINK_ENTITY_TO_CLASS( weapon_bodypart, CBodyPart );

void CBodyPart::Spawn( void )
{	Precache();
	m_iId = WEAPON_BODYPART;
	m_iDefaultAmmo = 0;
	m_iClip = -1;

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

void CBodyPart::Precache( void )
{	PRECACHE_MODEL("models/bodypart.mdl");	
	PRECACHE_MODEL("models/bodypart_grab.mdl");	
	PRECACHE_MODEL("models/bodypart_medium.mdl");
	PRECACHE_MODEL("models/bodypart_small.mdl");
	PRECACHE_MODEL("models/bodypart_large.mdl");
	//test
	PRECACHE_MODEL("models/p_test.mdl");
}



BOOL CBodyPart::Deploy()
{
	CAttachedBodyPart *pBodyPart = GetClassPtr( (CAttachedBodyPart *)NULL );
	pBodyPart->Spawn();	
	SET_MODEL(ENT(pBodyPart->pev), "models/bodypart_grab.mdl");
	pBodyPart->pev->movetype = MOVETYPE_FOLLOW;
	pBodyPart->pev->aiment = m_pPlayer->edict();
	pBodyPart->pev->owner = m_pPlayer->edict();
	pBodyPart->pev->frame = 0;
	pBodyPart->pev->sequence = pBodyPart->LookupSequence( "idle" );
	pBodyPart->ResetSequenceInfo ( );	
	//m_pPlayer->pev->rendermode = kRenderTransAdd;
	//m_pPlayer->pev->renderamt = 25;
	return DefaultDeploy("bodypart");
}

void CBodyPart::Holster(int skiplocal)
{	
}

int CBodyPart::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 = 5;
	p->iPosition = 5;
	p->iId = m_iId = WEAPON_BODYPART;
	p->iWeight = BODYPART_WEIGHT;
	p->iFlags = 0;
	return 1;
}

void CBodyPart::PrimaryAttack( void )
{	
	m_pPlayer->TakeDamage(m_pPlayer->pev,m_pPlayer->pev,2,DMG_MAGIC);

	//shoot the attack
	UTIL_MakeVectors( m_pPlayer->pev->v_angle );
	Vector vecSrc = m_pPlayer->GetGunPosition() + gpGlobals->v_right * 10;
	Vector vecThrow = gpGlobals->v_forward * BODYPART_SPEED;
	CBodyPartAttack::ShootBodyPart( m_pPlayer->pev, vecSrc, vecThrow);

	//set the right animation
	m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
	m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 3;
}