예제 #1
0
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFForceRespawn::ForceRespawn( bool bSwitchTeams )
{
	int i = 0;

	// respawn the players
	for ( i = 1 ; i <= gpGlobals->maxClients ; i++ )
	{
		CTFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( i ) );
		if ( pPlayer )
		{
			pPlayer->RemoveAllOwnedEntitiesFromWorld();

			// Ignore players who aren't on an active team
			if ( pPlayer->GetTeamNumber() != TF_TEAM_RED && pPlayer->GetTeamNumber() != TF_TEAM_BLUE )
			{
				// Let the player spawn immediately when they do pick a class
				pPlayer->AllowInstantSpawn();
				continue;
			}

			if ( bSwitchTeams )
			{
				if ( pPlayer->GetTeamNumber() == TF_TEAM_RED )
				{
					pPlayer->ForceChangeTeam( TF_TEAM_BLUE );
				}
				else if ( pPlayer->GetTeamNumber() == TF_TEAM_BLUE )
				{
					pPlayer->ForceChangeTeam( TF_TEAM_RED );
				}
			}

			// Ignore players who haven't picked a class yet
			if ( !pPlayer->GetPlayerClass() || pPlayer->GetPlayerClass()->GetClassIndex() == TF_CLASS_UNDEFINED )
			{
				// Allow them to spawn instantly when they do choose
				pPlayer->AllowInstantSpawn();
				continue;
			}

			
			pPlayer->ForceRespawn();
		}
	}

	// remove any dropped weapons/ammo packs	
	CBaseEntity *pEnt = NULL;
	while ( (pEnt = gEntList.FindEntityByClassname( pEnt, "tf_ammo_pack" )) != NULL )
	{
		UTIL_Remove( pEnt );
	}

	// Output.
	m_outputOnForceRespawn.FireOutput( this, this );
}
예제 #2
0
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CTFViewModel::GetSkin()
{
    int nSkin = BaseClass::GetSkin();

    CTFWeaponBase *pWeapon = ( CTFWeaponBase * )GetOwningWeapon();

    if ( !pWeapon )
        return nSkin;

    CTFPlayer *pPlayer = ToTFPlayer( GetOwner() );
    if ( pPlayer )
    {
        if ( pWeapon->GetTFWpnData().m_bHasTeamSkins_Viewmodel )
        {
            switch( pPlayer->GetTeamNumber() )
            {
            case TF_TEAM_RED:
                nSkin = 0;
                break;
            case TF_TEAM_BLUE:
                nSkin = 1;
                break;
            case TF_TEAM_GREEN:
                nSkin = 2;
                break;
            case TF_TEAM_YELLOW:
                nSkin = 3;
                break;
            }
        }
    }

    return nSkin;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CHudMenuSpyDisguise::FireGameEvent( IGameEvent *event )
{
	const char * type = event->GetName();

	if ( Q_strcmp(type, "spy_pda_reset") == 0 )
	{
		CTFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
		if ( pPlayer )
		{
			bool bShowBlue = ( pPlayer->GetTeamNumber() == TF_TEAM_RED );

			for ( int i=0; i<9; i++ )
			{
				m_pClassItems_Red[i]->SetVisible( !bShowBlue );
				m_pClassItems_Blue[i]->SetVisible( bShowBlue );
			}

			m_iShowingTeam = ( bShowBlue ) ? TF_TEAM_BLUE : TF_TEAM_RED;
		}
	}
	else
	{
		CHudElement::FireGameEvent( event );
	}
}
예제 #4
0
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CChangeClassZone::Touch( CBaseEntity *pOther )
{
    if ( !IsDisabled() )
    {
        CTFPlayer *pPlayer = ToTFPlayer( pOther );
        if ( pPlayer )
        {
            if ( pPlayer->GetNextChangeClassTime() > gpGlobals->curtime )
                return;

            int iTeam = GetTeamNumber();
            if ( iTeam && ( pPlayer->GetTeamNumber() != iTeam ) )
                return;

            // bring up the player's changeclass menu
            CCommand args;
            args.Tokenize( "changeclass" );
            pPlayer->ClientCommand( args );
            pPlayer->SetNextChangeClassTime( gpGlobals->curtime + TF_CHANGECLASS_NEXT_USE_TIME );

            CPASAttenuationFilter filter( pOther, TF_CHANGECLASS_SOUND );
            EmitSound( filter, pOther->entindex(), TF_CHANGECLASS_SOUND );
        }
    }
}
예제 #5
0
//-----------------------------------------------------------------------------
// Purpose: Allow bots etc to use slightly different solid masks
//-----------------------------------------------------------------------------
unsigned int CTFGameMovement::PlayerSolidMask( bool brushOnly )
{
	unsigned int uMask = 0;

	if ( m_pTFPlayer )
	{
		switch( m_pTFPlayer->GetTeamNumber() )
		{
		case TF_TEAM_RED:
			uMask = CONTENTS_BLUETEAM | CONTENTS_GREENTEAM | CONTENTS_YELLOWTEAM;
			break;

		case TF_TEAM_BLUE:
			uMask = CONTENTS_REDTEAM | CONTENTS_GREENTEAM | CONTENTS_YELLOWTEAM;
			break;

		case TF_TEAM_GREEN:
			uMask = CONTENTS_REDTEAM | CONTENTS_BLUETEAM | CONTENTS_YELLOWTEAM;
			break;

		case TF_TEAM_YELLOW:
			uMask = CONTENTS_REDTEAM | CONTENTS_BLUETEAM | CONTENTS_GREENTEAM;
			break;
		}
	}

	return ( uMask | BaseClass::PlayerSolidMask( brushOnly ) );
}
예제 #6
0
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CObjectTeleporter::TeleporterTouch( CBaseEntity *pOther )
{
	if ( IsDisabled() )
	{
		return;
	}

	// if it's not a player, ignore
	if ( !pOther->IsPlayer() )
		return;

	CTFPlayer *pPlayer = ToTFPlayer( pOther );

	CTFPlayer *pBuilder = GetBuilder();

	Assert( pBuilder );

	if ( !pBuilder )
	{
		return;
	}

	// if its not a teammate of the builder, notify the builder
	if ( pBuilder->GetTeamNumber() != pOther->GetTeamNumber() )
	{
		// Don't teleport enemies
		return;
	}

	// is this an entrance and do we have an exit?
	if ( GetType() == OBJ_TELEPORTER_ENTRANCE )
	{		
		if ( ( m_iState == TELEPORTER_STATE_READY ) )
		{
			// are we able to teleport?
			if ( pPlayer->HasTheFlag() )
			{
				// If they have the flag, print a warning that you can't tele with the flag
				CSingleUserRecipientFilter filter( pPlayer );
				TFGameRules()->SendHudNotification( filter, HUD_NOTIFY_NO_TELE_WITH_FLAG );
				return;
			}

			// get the velocity of the player touching the teleporter
			if ( pPlayer->GetAbsVelocity().Length() < 5.0 )
			{
				CObjectTeleporter *pDest = GetMatchingTeleporter();

				if ( pDest )
				{
					TeleporterSend( pPlayer );
				}
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFFlameThrower::RestartParticleEffect( void )
{
	CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() );
	if ( !pOwner )
		return;

	if ( m_pFlameEffect && m_hFlameEffectHost.Get() )
	{
		m_hFlameEffectHost->ParticleProp()->StopEmission( m_pFlameEffect );
	}

	m_iParticleWaterLevel = pOwner->GetWaterLevel();
	int iTeam = pOwner->GetTeamNumber();

	// Start the appropriate particle effect
	const char *pszParticleEffect;
	if ( pOwner->GetWaterLevel() == WL_Eyes )
	{
		pszParticleEffect = "flamethrower_underwater";
	}
	else
	{
		if ( m_bCritFire )
		{
			pszParticleEffect = ConstructTeamParticle( "flamethrower_crit_%s", iTeam, true );
		}
		else 
		{
			pszParticleEffect = iTeam == TF_TEAM_RED ? "flamethrower" : ConstructTeamParticle( "flamethrower_%s", pOwner->GetTeamNumber(), true );
		}		
	}

	// Start the effect on the viewmodel if our owner is the local player
	C_BaseEntity *pModel = GetWeaponForEffect();

	if ( pModel )
	{
		m_pFlameEffect = pModel->ParticleProp()->Create( pszParticleEffect, PATTACH_POINT_FOLLOW, "muzzle" );
		m_hFlameEffectHost = pModel;
	}

	pOwner->m_Shared.SetParticleToMercColor( m_pFlameEffect );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFWeaponBuilder::ItemPostFrame( void )
{
	CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
	if ( !pOwner )
		return;

	// If we're building, and our team has lost, stop placing the object
	if ( m_hObjectBeingBuilt.Get() && 
		TFGameRules()->State_Get() == GR_STATE_TEAM_WIN && 
		pOwner->GetTeamNumber() != TFGameRules()->GetWinningTeam() )
	{
		StopPlacement();
		return;
	}

	// Check that I still have enough resources to build this item
	if ( pOwner->CanBuild( m_iObjectType ) != CB_CAN_BUILD )
	{
		SwitchOwnersWeaponToLast();
	}

	if (( pOwner->m_nButtons & IN_ATTACK ) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
	{
		PrimaryAttack();
	}

	if ( pOwner->m_nButtons & IN_ATTACK2 )
	{
		if ( m_flNextSecondaryAttack <= gpGlobals->curtime )
		{
			SecondaryAttack();
		}
	}
	else
	{
		m_bInAttack2 = false;
	}

	WeaponIdle();
}
예제 #9
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
int CTFViewModel::GetSkin()
{
	int nSkin = BaseClass::GetSkin();

	CTFWeaponBase *pWeapon = ( CTFWeaponBase * )GetOwningWeapon();

	if ( !pWeapon ) 
		return nSkin;

	CTFPlayer *pPlayer = ToTFPlayer( GetOwner() );
	if ( pPlayer )
	{
		if ( TFGameRules()->IsDeathmatch() )
		{
			// Merc arms are team colored so use the colored skin for all weapons.
			nSkin = 4;
		}
		else if ( pWeapon->GetTFWpnData().m_bHasTeamSkins_Viewmodel )
		{
			switch ( pPlayer->GetTeamNumber() )
			{
			case TF_TEAM_RED:
				nSkin = 0;
				break;
			case TF_TEAM_BLUE:
				nSkin = 1;
				break;
			case TF_TEAM_GREEN:
				nSkin = 2;
				break;
			case TF_TEAM_YELLOW:
				nSkin = 3;
				break;
			}
		}	
	}

	return nSkin;
}
예제 #10
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CWeaponMedigun::AllowedToHealTarget( CBaseEntity *pTarget )
{
	CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() );
	if ( !pOwner )
		return false;

	CTFPlayer *pTFPlayer = ToTFPlayer( pTarget );
	if ( !pTFPlayer )
		return false;

	bool bStealthed = pTFPlayer->m_Shared.InCond( TF_COND_STEALTHED );
	bool bDisguised = pTFPlayer->m_Shared.InCond( TF_COND_DISGUISED );

	// We can heal teammates and enemies that are disguised as teammates
	if ( !bStealthed &&
		( pTFPlayer->InSameTeam( pOwner ) ||
		( bDisguised && pTFPlayer->m_Shared.GetDisguiseTeam() == pOwner->GetTeamNumber() ) ) )
	{
		return true;
	}

	return false;
}
예제 #11
0
// -----------------------------------------------------------------------------
// Purpose:
// Note: Think function to delay the impact decal until the animation is finished 
//       playing.
// -----------------------------------------------------------------------------
void CTFWeaponBaseMelee::Smack( void )
{
	trace_t trace;

	CBasePlayer *pPlayer = GetPlayerOwner();
	if ( !pPlayer )
		return;

#if !defined (CLIENT_DLL)
	// Move other players back to history positions based on local player's lag
	lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() );
#endif

	// We hit, setup the smack.
	if ( DoSwingTrace( trace ) )
	{
		// Hit sound - immediate.
		if( trace.m_pEnt->IsPlayer()  )
		{
			WeaponSound( MELEE_HIT );
		}
		else
		{
			WeaponSound( MELEE_HIT_WORLD );
		}

		// Get the current player.
		CTFPlayer *pPlayer = GetTFPlayerOwner();
		if ( !pPlayer )
			return;

		Vector vecForward; 
		AngleVectors( pPlayer->EyeAngles(), &vecForward );
		Vector vecSwingStart = pPlayer->Weapon_ShootPosition();
		Vector vecSwingEnd = vecSwingStart + vecForward * 48;

#ifndef CLIENT_DLL
		// Do Damage.
		int iCustomDamage = TF_DMG_CUSTOM_NONE;
		float flDamage = GetMeleeDamage( trace.m_pEnt, iCustomDamage );
		int iDmgType = DMG_BULLET | DMG_NEVERGIB | DMG_CLUB;
		if ( IsCurrentAttackACrit() )
		{
			// TODO: Not removing the old critical path yet, but the new custom damage is marking criticals as well for melee now.
			iDmgType |= DMG_CRITICAL;
		}
		CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
		CTFUbersaw *pUbersaw = dynamic_cast<CTFUbersaw*>(pWpn);
		CWeaponMedigun *pMedigun = static_cast<CWeaponMedigun*>(pPlayer->Weapon_OwnsThisID(TF_WEAPON_MEDIGUN));
		if (pMedigun && pUbersaw)
		{
			if(trace.m_pEnt->IsPlayer() && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber())
			{
				pMedigun->AddCharge();
			}
		}
		CWeaponKritzkrieg *pKritzkrieg = static_cast<CWeaponKritzkrieg*>(pPlayer->Weapon_OwnsThisID(TF_WEAPON_KRITZKRIEG));
		if (pKritzkrieg && pUbersaw)
		{
			if(trace.m_pEnt->IsPlayer() && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber())
			{
				pKritzkrieg->AddCharge();
			}
		}
		CTakeDamageInfo info( pPlayer, pPlayer, flDamage, iDmgType, iCustomDamage );
		CalculateMeleeDamageForce( &info, vecForward, vecSwingEnd, 1.0f / flDamage * tf_meleeattackforcescale.GetFloat() );
		trace.m_pEnt->DispatchTraceAttack( info, vecForward, &trace ); 
		ApplyMultiDamage();

		OnEntityHit( trace.m_pEnt );
#endif
		// Don't impact trace friendly players or objects
		if ( trace.m_pEnt && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber() )
		{
#ifdef CLIENT_DLL
			UTIL_ImpactTrace( &trace, DMG_CLUB );
#endif
			m_bConnected = true;
		}

	}

#if !defined (CLIENT_DLL)
	lagcompensation->FinishLagCompensation( pPlayer );
#endif
}
예제 #12
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFFreezePanel::FireGameEvent( IGameEvent * event )
{
	const char *pEventName = event->GetName();

	if ( Q_strcmp( "player_death", pEventName ) == 0 )
	{
		// see if the local player died
		int iPlayerIndexVictim = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
		C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
		if ( pLocalPlayer && iPlayerIndexVictim == pLocalPlayer->entindex() )
		{
			// the local player is dead, see if this is a new nemesis or a revenge
			if ( event->GetInt( "dominated" ) > 0 )
			{
				m_iShowNemesisPanel = SHOW_NEW_NEMESIS;
			}
			else if ( event->GetInt( "revenge" ) > 0 )
			{
				m_iShowNemesisPanel = SHOW_REVENGE;
			}
			else
			{
				m_iShowNemesisPanel = SHOW_NO_NEMESIS;
			}
		}		
	}
	else if ( Q_strcmp( "hide_freezepanel", pEventName ) == 0 )
	{
		Hide();
	}
	else if ( Q_strcmp( "freezecam_started", pEventName ) == 0 )
	{
		ShowCalloutsIn( 1.0 );
		ShowSnapshotPanelIn( 1.25 );
	}
	else if ( Q_strcmp( "teamplay_win_panel", pEventName ) == 0 )
	{
		Hide();
	}
	else if ( Q_strcmp( "show_freezepanel", pEventName ) == 0 )
	{
		C_TF_PlayerResource *tf_PR = dynamic_cast<C_TF_PlayerResource *>(g_PR);
		if ( !tf_PR )
		{
			m_pNemesisSubPanel->SetDialogVariable( "nemesisname", NULL );
			return;
		}

		Show();

		ShowSnapshotPanel( false );
		m_bHoldingAfterScreenshot = false;

		if ( m_iBasePanelOriginalX > -1 && m_iBasePanelOriginalY > -1 )
		{
			m_pBasePanel->SetPos( m_iBasePanelOriginalX, m_iBasePanelOriginalY );
		}

		// Get the entity who killed us
		m_iKillerIndex = event->GetInt( "killer" );
		C_BaseEntity *pKiller =  ClientEntityList().GetBaseEntity( m_iKillerIndex );

		int xp,yp;
		GetPos( xp, yp );
		if ( TFGameRules()->RoundHasBeenWon() )
		{
			SetPos( xp, m_iYBase - YRES(50) );
		}
		else
		{
			SetPos( xp, m_iYBase );
		}

		if ( pKiller )
		{
			CTFPlayer *pPlayer = ToTFPlayer ( pKiller );
			int iMaxBuffedHealth = 0;

			if ( pPlayer )
			{
				iMaxBuffedHealth = pPlayer->m_Shared.GetMaxBuffedHealth();
			}

			int iKillerHealth = pKiller->GetHealth();
			if ( !pKiller->IsAlive() )
			{
				iKillerHealth = 0;
			}
			m_pKillerHealth->SetHealth( iKillerHealth, pKiller->GetMaxHealth(), iMaxBuffedHealth );

			if ( pKiller->IsPlayer() )
			{
				C_TFPlayer *pVictim = C_TFPlayer::GetLocalTFPlayer();
				CTFPlayer *pTFKiller = ToTFPlayer( pKiller );

				// Set the BG according to the team they're on
				m_pFreezePanelBG->SetBGImage( pTFKiller->GetTeamNumber() );

				//If this was just a regular kill but this guy is our nemesis then just show it.
				if ( pVictim && pTFKiller && pTFKiller->m_Shared.IsPlayerDominated( pVictim->entindex() ) )
				{
					if ( !pKiller->IsAlive() )
					{
						m_pFreezeLabel->SetText( "#FreezePanel_Nemesis_Dead" );
					}
					else
					{
						m_pFreezeLabel->SetText( "#FreezePanel_Nemesis" );
					}
				}
				else
				{
					if ( !pKiller->IsAlive() )
					{
						m_pFreezeLabel->SetText( "#FreezePanel_Killer_Dead" );
					}
					else
					{
						m_pFreezeLabel->SetText( "#FreezePanel_Killer" );
					}
				}

				m_pBasePanel->SetDialogVariable( "killername", g_PR->GetPlayerName( m_iKillerIndex ) );

				if ( m_pAvatar )
				{
					m_pAvatar->SetDefaultAvatar( GetDefaultAvatarImage( (C_BasePlayer*)pKiller ) );

					m_pAvatar->SetPlayer( (C_BasePlayer*)pKiller );
					m_pAvatar->SetShouldDrawFriendIcon( false );
				}
			}
			else if ( pKiller->IsBaseObject() )
			{
				C_BaseObject *pObj = assert_cast<C_BaseObject *>( pKiller );
				C_TFPlayer *pOwner = pObj->GetOwner();

				Assert( pOwner && "Why does this object not have an owner?" );
				
				// Set the BG according to the team it's on
				m_pFreezePanelBG->SetBGImage( pObj->GetTeamNumber() );

				if ( pOwner )
				{
					m_iKillerIndex = pOwner->entindex();

					m_pBasePanel->SetDialogVariable( "killername", g_PR->GetPlayerName( m_iKillerIndex ) );

					if ( m_pAvatar )
					{
						m_pAvatar->SetDefaultAvatar( GetDefaultAvatarImage( pOwner ) );

						m_pAvatar->SetPlayer( pOwner );
						m_pAvatar->SetShouldDrawFriendIcon( false );
					}

					pKiller = pOwner;
				}

				if ( m_pFreezeLabel )
				{
					if ( pKiller && !pKiller->IsAlive() )
					{
						m_pFreezeLabel->SetText( "#FreezePanel_KillerObject_Dead" );
					}
					else
					{
						m_pFreezeLabel->SetText( "#FreezePanel_KillerObject" );
					}
				}
				const char *pszStatusName = pObj->GetStatusName();
				wchar_t *wszLocalized = g_pVGuiLocalize->Find( pszStatusName );

				if ( !wszLocalized )
				{
					m_pBasePanel->SetDialogVariable( "objectkiller", pszStatusName );
				}
				else
				{
					m_pBasePanel->SetDialogVariable( "objectkiller", wszLocalized );
				}
			}
			else if ( m_pFreezeLabel )
			{
				if ( !pKiller->IsAlive() )
				{
					m_pFreezeLabel->SetText( "#FreezePanel_Killer_Dead" );
				}
				else
				{
					m_pFreezeLabel->SetText( "#FreezePanel_Killer" );
				}
			}
		}
		
		// see if we should show nemesis panel
		const wchar_t *pchNemesisText = NULL;
		switch ( m_iShowNemesisPanel )
		{
		case SHOW_NO_NEMESIS:
			{
				C_TFPlayer *pVictim = C_TFPlayer::GetLocalTFPlayer();
				CTFPlayer *pTFKiller = ToTFPlayer( pKiller );
			
				//If this was just a regular kill but this guy is our nemesis then just show it.
				if ( pTFKiller && pTFKiller->m_Shared.IsPlayerDominated( pVictim->entindex() ) )
				{					
					pchNemesisText = g_pVGuiLocalize->Find( "#TF_FreezeNemesis" );
				}	
			}
			break;
		case SHOW_NEW_NEMESIS:
			{
				C_TFPlayer *pVictim = C_TFPlayer::GetLocalTFPlayer();
				CTFPlayer *pTFKiller = ToTFPlayer( pKiller );
				// check to see if killer is still the nemesis of victim; victim may have managed to kill him after victim's
				// death by grenade or some such, extracting revenge and clearing nemesis condition
				if ( pTFKiller && pTFKiller->m_Shared.IsPlayerDominated( pVictim->entindex() ) )
				{					
					pchNemesisText = g_pVGuiLocalize->Find( "#TF_NewNemesis" );
				}			
			}
			break;
		case SHOW_REVENGE:
			pchNemesisText = g_pVGuiLocalize->Find( "#TF_GotRevenge" );
			break;
		default:
			Assert( false );	// invalid value
			break;
		}
		m_pNemesisSubPanel->SetDialogVariable( "nemesisname", pchNemesisText );

		ShowNemesisPanel( NULL != pchNemesisText );
		m_iShowNemesisPanel = SHOW_NO_NEMESIS;
	}
}
예제 #13
0
void CTFBaseRocket::FlyThink( void )
{
    if ( gpGlobals->curtime > m_flCollideWithTeammatesTime && m_bCollideWithTeammates == false )
    {
        m_bCollideWithTeammates = true;
    }

    if ( tf2c_homing_rockets.GetBool() || ( tf2c_homing_deflected_rockets.GetBool() && m_iDeflected ) )
    {
        // Find the closest visible enemy player.
        CUtlVector<CTFPlayer *> vecPlayers;
        int count = CollectPlayers( &vecPlayers, TEAM_ANY, true );
        float flClosest = FLT_MAX;
        Vector vecClosestTarget = vec3_origin;

        for ( int i = 0; i < count; i++ )
        {
            CTFPlayer *pPlayer = vecPlayers[i];
            if ( pPlayer == GetOwnerEntity() )
                continue;

            if ( pPlayer->GetTeamNumber() == GetTeamNumber() && !TFGameRules()->IsDeathmatch() )
                continue;

            Vector vecTarget;
            QAngle angTarget;
            if ( GetWeaponID() == TF_WEAPON_COMPOUND_BOW )
            {
                int iBone = pPlayer->LookupBone( "bip_head" );
                pPlayer->GetBonePosition( iBone, vecTarget, angTarget );;
            }
            else
            {
                vecTarget = pPlayer->EyePosition();
            }

            if ( FVisible( vecTarget ) )
            {
                float flDistSqr = ( vecTarget - GetAbsOrigin() ).LengthSqr();
                if ( flDistSqr < flClosest )
                {
                    flClosest = flDistSqr;
                    vecClosestTarget = vecTarget;
                }
            }
        }

        // Head towards him.
        if ( vecClosestTarget != vec3_origin )
        {
            Vector vecTarget = vecClosestTarget;
            Vector vecDir = vecTarget - GetAbsOrigin();
            VectorNormalize( vecDir );

            float flSpeed = GetAbsVelocity().Length();
            QAngle angForward;
            VectorAngles( vecDir, angForward );
            SetAbsAngles( angForward );
            SetAbsVelocity( vecDir * flSpeed );
        }
    }

    SetNextThink( gpGlobals->curtime + 0.1f );
}