//-----------------------------------------------------------------------------
// Purpose: Figure out if I should be using an attached item rather than this vehicle itself.
//-----------------------------------------------------------------------------
bool CBaseTFVehicle::UseAttachedItem( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
	CBaseTFPlayer* pPlayer = dynamic_cast<CBaseTFPlayer*>(pActivator);
	if ( !pPlayer || !InSameTeam(pPlayer) )
		return false;

	Vector vecPlayerOrigin = pPlayer->GetAbsOrigin();
	int nBestBuildPoint = -1;
	float fBestDistance = FLT_MAX;

	// Get the closest regular entry point:
	int nRole = LocateEntryPoint( pPlayer, &fBestDistance );

	// Iterate through each of the build points, if any, and see which we are closest to.
	int nBuildPoints = GetNumBuildPoints();
	for( int i = 0; i < nBuildPoints; i++ )
	{	
		CBaseObject* pObject = GetBuildPointObject(i);

		// If there's something in the build point that isn't in the process of being built or placed:
		if( pObject && !pObject->IsPlacing() && !pObject->IsBuilding() ) 
		{
			Vector vecOrigin;
			QAngle vecAngles;

			// If the build point is the default point for this role, just take it 
			if (GetBuildPointPassenger(i) == nRole)
			{
				nBestBuildPoint = i;
				break;
			}

			// And I can get the build point.
			if( GetBuildPoint( i, vecOrigin, vecAngles )  )
			{
				float fLength2dSqr = (vecOrigin - vecPlayerOrigin).AsVector2D().LengthSqr();
				if( fLength2dSqr < fBestDistance )
				{
					nBestBuildPoint = i;
					fBestDistance = fLength2dSqr; 
				}
			}
		}
	}

	if( nBestBuildPoint >= 0 )
	{
		// They're using an item on me, so push out the deterioration time
		ResetDeteriorationTime();
		GetBuildPointObject(nBestBuildPoint)->Use( pActivator, pCaller, useType, value );
		return true;
	}

	return false;
}
//-----------------------------------------------------------------------------
// Purpose: Returns an exit point for a vehicle built on a build point...
//-----------------------------------------------------------------------------
void CInfoBuildPoint::GetExitPoint( CBaseEntity *pPlayer, int iPoint, Vector *pAbsOrigin, QAngle *pAbsAngles )
{
	// FIXME: In future, we may well want to use specific exit attachments here...
	GetBuildPoint( iPoint, *pAbsOrigin, *pAbsAngles );

	// Move back along the forward direction a bit...
	Vector vecForward;
	AngleVectors( *pAbsAngles, &vecForward );
	*pAbsOrigin -= vecForward * 60;

	// Now select a good spot to drop onto
	Vector vNewPos;
	if ( !EntityPlacementTest(pPlayer, *pAbsOrigin, vNewPos, true) )
	{
		Warning("Can't find valid place to exit object.\n");
		return;
	}

	*pAbsOrigin = vNewPos;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_BaseObject::HighlightBuildPoints( int flags )
{
	C_TFPlayer *pLocal = C_TFPlayer::GetLocalTFPlayer();
	if ( !pLocal )
		return;

	if ( !GetNumBuildPoints() || !InLocalTeam() )
		return;

	C_TFWeaponBuilder *pBuilderWpn = dynamic_cast< C_TFWeaponBuilder * >( pLocal->GetActiveWeaponForSelection() );
	if ( !pBuilderWpn )
		return;
	if ( !pBuilderWpn->IsPlacingObject() )
		return;
	C_BaseObject *pPlacementObj = pBuilderWpn->GetPlacementModel();
	if ( !pPlacementObj || pPlacementObj == this )
		return;

	// Near enough?
	if ( (GetAbsOrigin() - pLocal->GetAbsOrigin()).LengthSqr() < MAX_VISIBLE_BUILDPOINT_DISTANCE )
	{
		bool bRestoreModel = false;
		Vector vecPrevAbsOrigin = pPlacementObj->GetAbsOrigin();
		QAngle vecPrevAbsAngles = pPlacementObj->GetAbsAngles();

		Vector orgColor;
		render->GetColorModulation( orgColor.Base() );
		float orgBlend = render->GetBlend();

		bool bSameTeam = ( pPlacementObj->GetTeamNumber() == GetTeamNumber() );

		if ( pPlacementObj->IsHostileUpgrade() && bSameTeam )
		{
			// Don't hilight hostile upgrades on friendly objects
			return;
		}
		else if ( !bSameTeam )
		{
			// Don't hilight upgrades on enemy objects
			return;
		}

		// Any empty buildpoints?
		for ( int i = 0; i < GetNumBuildPoints(); i++ )
		{
			// Can this object build on this point?
			if ( CanBuildObjectOnBuildPoint( i, pPlacementObj->GetType() ) )
			{
				Vector vecBPOrigin;
				QAngle vecBPAngles;
				if ( GetBuildPoint(i, vecBPOrigin, vecBPAngles) )
				{
					pPlacementObj->InvalidateBoneCaches();

					Vector color( 0, 255, 0 );
					render->SetColorModulation(	color.Base() );
					float frac = fmod( gpGlobals->curtime, 3 );
					frac *= 2 * M_PI;
					frac = cos( frac );
					render->SetBlend( (175 + (int)( frac * 75.0f )) / 255.0 );

					// FIXME: This truly sucks! The bone cache should use
					// render location for this computation instead of directly accessing AbsAngles
					// Necessary for bone cache computations to work
					pPlacementObj->SetAbsOrigin( vecBPOrigin );
					pPlacementObj->SetAbsAngles( vecBPAngles );

					modelrender->DrawModel( 
						flags, 
						pPlacementObj,
						pPlacementObj->GetModelInstance(),
						pPlacementObj->index, 
						pPlacementObj->GetModel(),
						vecBPOrigin,
						vecBPAngles,
						pPlacementObj->m_nSkin,
						pPlacementObj->m_nBody,
						pPlacementObj->m_nHitboxSet
						);

					bRestoreModel = true;
				}
			}
		}

		if ( bRestoreModel )
		{
			pPlacementObj->SetAbsOrigin(vecPrevAbsOrigin);
			pPlacementObj->SetAbsAngles(vecPrevAbsAngles);
			pPlacementObj->InvalidateBoneCaches();

			render->SetColorModulation( orgColor.Base() );
			render->SetBlend( orgBlend );
		}
	}
}