//========= Copyright Valve Corporation, All rights reserved. ============//
// c_eyeball_boss.cpp

#include "cbase.h"
#include "NextBot/C_NextBot.h"
#include "c_eyeball_boss.h"
#include "tf_shareddefs.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

#undef NextBot

#ifdef STAGING_ONLY
static ConVar cl_eyeball_boss_debug( "cl_eyeball_boss_debug", "0" );
#endif


//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EyeballBoss, DT_EyeballBoss, CEyeballBoss )

	RecvPropVector( RECVINFO( m_lookAtSpot ) ),
	RecvPropInt( RECVINFO( m_attitude ) ),
	
END_RECV_TABLE()


//-----------------------------------------------------------------------------
C_EyeballBoss::C_EyeballBoss()
{
	m_ghostEffect = NULL;
	m_auraEffect = NULL;
	m_attitude = EYEBALL_CALM;
	m_priorAttitude = m_attitude;
}


//-----------------------------------------------------------------------------
C_EyeballBoss::~C_EyeballBoss()
{
	if ( m_ghostEffect )
	{
		ParticleProp()->StopEmission( m_ghostEffect );
		m_ghostEffect = NULL;
	}

	if ( m_auraEffect )
	{
		ParticleProp()->StopEmission( m_auraEffect );
		m_auraEffect = NULL;
	}
}


//-----------------------------------------------------------------------------
void C_EyeballBoss::Spawn( void )
{
	BaseClass::Spawn();

	m_leftRightPoseParameter = -1;
	m_upDownPoseParameter = -1;

	m_myAngles = vec3_angle;

	m_attitude = EYEBALL_CALM;
	m_priorAttitude = m_attitude;

	SetNextClientThink( CLIENT_THINK_ALWAYS );
}


//-----------------------------------------------------------------------------
void C_EyeballBoss::OnPreDataChanged( DataUpdateType_t updateType )
{
	BaseClass::OnPreDataChanged( updateType );

	m_priorAttitude = m_attitude;
}


//-----------------------------------------------------------------------------
void C_EyeballBoss::OnDataChanged( DataUpdateType_t updateType )
{
	BaseClass::OnDataChanged( updateType );

	if ( updateType == DATA_UPDATE_CREATED )
	{
		const char *pszMaterial = NULL;
		const char *pszAuraEffect = "eyeboss_aura_calm";
		switch ( GetTeamNumber() )
		{
		case TF_TEAM_RED:
			{
				pszAuraEffect = "eyeboss_team_red";
				//pszMaterial = "models/effects/invulnfx_red.vmt";
			}
			break;
		case TF_TEAM_BLUE:
			{
				pszAuraEffect = "eyeboss_team_blue";
				//pszMaterial = "models/effects/invulnfx_blue.vmt";
			}
			break;
		default:
			{
				if ( !m_ghostEffect )
				{
					m_ghostEffect = ParticleProp()->Create( "ghost_pumpkin", PATTACH_ABSORIGIN_FOLLOW );
				}
			}
			break;
		}

		if ( !m_auraEffect )
		{
			m_auraEffect = ParticleProp()->Create( pszAuraEffect, PATTACH_ABSORIGIN_FOLLOW );
		}

		if ( pszMaterial )
		{
			m_InvulnerableMaterial.Init( pszMaterial, TEXTURE_GROUP_CLIENT_EFFECTS );
		}
		else
		{
			m_InvulnerableMaterial.Shutdown();
		}
	}
	else if ( GetTeamNumber() == TF_TEAM_HALLOWEEN )
	{
		// update eyeball aura
		if ( m_attitude != m_priorAttitude )
		{
			// kill the old aura
			if ( m_auraEffect )
			{
				ParticleProp()->StopEmission( m_auraEffect );
			}

			switch( m_attitude )
			{
			case EYEBALL_CALM:
				m_auraEffect = ParticleProp()->Create( "eyeboss_aura_calm", PATTACH_ABSORIGIN_FOLLOW );
				break;

			case EYEBALL_GRUMPY:
				m_auraEffect = ParticleProp()->Create( "eyeboss_aura_grumpy", PATTACH_ABSORIGIN_FOLLOW );
				break;

			case EYEBALL_ANGRY:
				m_auraEffect = ParticleProp()->Create( "eyeboss_aura_angry", PATTACH_ABSORIGIN_FOLLOW );
				break;
			}

			m_priorAttitude = m_attitude;
		}
	}
}

//-----------------------------------------------------------------------------
void C_EyeballBoss::ClientThink( void )
{
	// update eyeball aim
	if ( m_leftRightPoseParameter < 0 )
	{
		m_leftRightPoseParameter = LookupPoseParameter( "left_right" );
	}

	if ( m_upDownPoseParameter < 0 )
	{
		m_upDownPoseParameter = LookupPoseParameter( "up_down" );
	}


	Vector myForward, myRight, myUp;
	AngleVectors( m_myAngles, &myForward, &myRight, &myUp );

#ifdef STAGING_ONLY
	if ( cl_eyeball_boss_debug.GetBool() )
	{
		QAngle myAbsAngles = GetAbsAngles();

		DevMsg( "%3.2f: EYEBALL BEFORE AIM m_myAngles( %f, %f, %f ), myForward( %f, %f, %f ), GetAbsAngles( %f, %f, %f )\n", 
				gpGlobals->curtime, m_myAngles.x, m_myAngles.y, m_myAngles.z, myForward.x, myForward.y, myForward.z,
				myAbsAngles.x, myAbsAngles.y, myAbsAngles.z );
	}
#endif

	const float myApproachRate = 3.0f; // 1.0f;

	Vector toTarget = m_lookAtSpot - WorldSpaceCenter();
	toTarget.NormalizeInPlace();

	myForward += toTarget * myApproachRate * gpGlobals->frametime;
	myForward.NormalizeInPlace();

	QAngle myNewAngles;
	VectorAngles( myForward, myNewAngles );

	SetAbsAngles( myNewAngles );
	m_myAngles = myNewAngles;

#ifdef STAGING_ONLY
	if ( cl_eyeball_boss_debug.GetBool() )
	{
		QAngle myAbsAngles = GetAbsAngles();

		DevMsg( "%3.2f: EYEBALL AFTER AIM m_myAngles( %f, %f, %f ), myForward( %f, %f, %f ), GetAbsAngles( %f, %f, %f )\n", 
				gpGlobals->curtime, m_myAngles.x, m_myAngles.y, m_myAngles.z, myForward.x, myForward.y, myForward.z,
				myAbsAngles.x, myAbsAngles.y, myAbsAngles.z );
	}
#endif


	// set pose parameters to aim pupil directly at target
	float toTargetRight = DotProduct( myRight, toTarget );
	float toTargetUp = DotProduct( myUp, toTarget );

	if ( m_leftRightPoseParameter >= 0 )
	{
		int angle = -50 * toTargetRight;

		SetPoseParameter( m_leftRightPoseParameter, angle );
	}

	if ( m_upDownPoseParameter >= 0 )
	{
		int angle = -50 * toTargetUp;

		SetPoseParameter( m_upDownPoseParameter, angle );
	}
}


//-----------------------------------------------------------------------------
void C_EyeballBoss::SetDormant( bool bDormant )
{
	BaseClass::SetDormant( bDormant );
}


//-----------------------------------------------------------------------------
void C_EyeballBoss::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
}


//-----------------------------------------------------------------------------
QAngle const &C_EyeballBoss::GetRenderAngles( void )
{
	return m_myAngles;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
int	C_EyeballBoss::InternalDrawModel( int flags )
{
	bool bUseInvulnMaterial = ( GetTeamNumber() == TF_TEAM_RED ) || ( GetTeamNumber() == TF_TEAM_BLUE );

	if ( bUseInvulnMaterial )
	{
		modelrender->ForcedMaterialOverride( m_InvulnerableMaterial );
	}

	int ret = BaseClass::InternalDrawModel( flags );

	if ( bUseInvulnMaterial )
	{
		modelrender->ForcedMaterialOverride( NULL );
	}

	return ret;
}