//----------------------------------------------------------------------------- // Purpose: Player has waved his crosshair over this entity. Display appropriate hints. //----------------------------------------------------------------------------- void C_BaseObject::DisplayHintTo( C_BasePlayer *pPlayer ) { bool bHintPlayed = false; C_TFPlayer *pTFPlayer = ToTFPlayer(pPlayer); if ( InSameTeam( pPlayer ) ) { // We're looking at a friendly object. if ( HasSapper() ) { bHintPlayed = pPlayer->HintMessage( HINT_OBJECT_HAS_SAPPER, true, true ); } if ( pTFPlayer->IsPlayerClass( TF_CLASS_ENGINEER ) ) { // I'm an engineer. // If I'm looking at a constructing object, let me know I can help build it (but not // if I built it myself, since I've already got that hint from the wrench). if ( !bHintPlayed && IsBuilding() && GetBuilder() != pTFPlayer ) { bHintPlayed = pPlayer->HintMessage( HINT_ENGINEER_USE_WRENCH_ONOTHER, false, true ); } // If it's damaged, I can repair it if ( !bHintPlayed && !IsBuilding() && GetHealth() < GetMaxHealth() ) { bHintPlayed = pPlayer->HintMessage( HINT_ENGINEER_REPAIR_OBJECT, false, true ); } } } }
//----------------------------------------------------------------------------- // Purpose: Allow players to remove sappers from objects //----------------------------------------------------------------------------- void CGrenadeObjectSapper::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { // Only enemies remove the sapper if ( !InSameTeam( pActivator ) ) { // Enemy is grabbing me EmitSound( "GrenadeObjectSapper.RemoveSapper" ); SetTargetObject( NULL ); UTIL_Remove( this ); } /* ROBIN: Removed self-removal of sapper else { // Ignore everyone except my owner if ( pPlayer != m_hOwner ) return; if ( pPlayer->GiveAmmo( 1, "Sappers") ) { // Picked up, remove me SetTargetObject( NULL ); UTIL_Remove( this ); } } */ }
//----------------------------------------------------------------------------- // 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: //----------------------------------------------------------------------------- void C_AI_BaseNPC::GetTargetIDString( wchar_t *sIDString, int iMaxLenInBytes ) { sIDString[0] = '\0'; C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pLocalTFPlayer ) return; if ( InSameTeam( pLocalTFPlayer ) || pLocalTFPlayer->IsPlayerClass( TF_CLASS_SPY ) || pLocalTFPlayer->GetTeamNumber() == TEAM_SPECTATOR ) { const char *pszClassname = GetClassname(); wchar_t *wszNPCName; wszNPCName = g_pVGuiLocalize->Find( pszClassname ); if ( !wszNPCName ) { wchar_t wszNPCNameBuf[MAX_PLAYER_NAME_LENGTH]; g_pVGuiLocalize->ConvertANSIToUnicode( pszClassname, wszNPCNameBuf, sizeof(wszNPCNameBuf) ); wszNPCName = wszNPCNameBuf; } const char *printFormatString = NULL; if ( pLocalTFPlayer->GetTeamNumber() == TEAM_SPECTATOR || InSameTeam( pLocalTFPlayer ) ) { printFormatString = "#TF_playerid_sameteam"; } else if ( pLocalTFPlayer->IsPlayerClass( TF_CLASS_SPY ) ) { // Spy can see enemy's health. printFormatString = "#TF_playerid_diffteam"; } wchar_t *wszPrepend = L""; if ( printFormatString ) { g_pVGuiLocalize->ConstructString( sIDString, iMaxLenInBytes, g_pVGuiLocalize->Find(printFormatString), 3, wszPrepend, wszNPCName ); } } }
//----------------------------------------------------------------------------- // Purpose: Can we get into the vehicle? //----------------------------------------------------------------------------- bool CBaseTFVehicle::CanGetInVehicle( CBaseTFPlayer *pPlayer ) { if ( !IsPowered() ) return false; if ( !InSameTeam( pPlayer ) ) return false; // Player/Class-specific query. return pPlayer->CanGetInVehicle(); }
//----------------------------------------------------------------------------- // Boost those attached to me as long as I'm not EMPed //----------------------------------------------------------------------------- void CObjectBuffStation::BoostPlayerThink( void ) { // Are we emped? bool bIsEmped = HasPowerup( POWERUP_EMP ); // Get range (squared = faster test). float flMaxRangeSq = obj_buff_station_range.GetFloat(); flMaxRangeSq *= flMaxRangeSq; // Boost all attached players and objects. for ( int iPlayer = 0; iPlayer < BUFF_STATION_MAX_PLAYERS; iPlayer++ ) { // Clean up dangling pointers + dead players, subversion, disconnection CBaseTFPlayer *pPlayer = m_hPlayers[iPlayer].Get(); if ( !pPlayer || !pPlayer->IsAlive() || !InSameTeam( pPlayer ) || !pPlayer->PlayerClass() ) { DetachPlayerByIndex( iPlayer ); continue; } // Check for out of range. float flDistSq = GetAbsOrigin().DistToSqr( pPlayer->GetAbsOrigin() ); if ( flDistSq > flMaxRangeSq ) { DetachPlayerByIndex( iPlayer ); continue; } bool bBoosted = false; if ( !bIsEmped ) { float flHealAmount = obj_buff_station_heal_rate.GetFloat() * BUFF_STATION_BOOST_PLAYER_THINK_INTERVAL; bBoosted = pPlayer->AttemptToPowerup( POWERUP_BOOST, 0, flHealAmount, this, &m_aPlayerAttachInfo[iPlayer].m_DamageModifier ); } if ( !bBoosted ) { m_aPlayerAttachInfo[iPlayer].m_DamageModifier.RemoveModifier(); } } // Set next think time. if ( m_nPlayerCount > 0 ) { SetNextThink( gpGlobals->curtime + BUFF_STATION_BOOST_PLAYER_THINK_INTERVAL, BUFF_STATION_BOOST_PLAYER_THINK_CONTEXT ); } else { SetNextThink( gpGlobals->curtime + 1.0f, BUFF_STATION_BOOST_PLAYER_THINK_CONTEXT ); } }
void CWalkerMiniStrider::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { // Sapper removal if ( RemoveEnemyAttachments( pActivator ) ) return; CBaseTFPlayer *pPlayer = dynamic_cast<CBaseTFPlayer*>(pActivator); if ( !pPlayer || !InSameTeam( pPlayer ) ) return; // Ok, put them in the driver role. AttemptToBoardVehicle( pPlayer ); }
//----------------------------------------------------------------------------- // Purpose: // Input : pOther - The thing that touched us. //----------------------------------------------------------------------------- void CFuncRespawnRoom::RespawnRoomTouch(CBaseEntity *pOther) { if ( PassesTriggerFilters(pOther) ) { if ( pOther->IsPlayer() && InSameTeam( pOther ) ) { // Players carrying the flag drop it if they try to run into a respawn room CTFPlayer *pPlayer = ToTFPlayer(pOther); if ( pPlayer->HasTheFlag() && !m_bAllowFlag ) { pPlayer->DropFlag(); } } } }
//----------------------------------------------------------------------------- // Purpose: Attach to players who touch me //----------------------------------------------------------------------------- void CObjectBuffStation::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if ( useType == USE_ON ) { // See if the activator is a player if ( !pActivator->IsPlayer() || !InSameTeam( pActivator ) || !pActivator->CanBePoweredUp() ) return; CBaseTFPlayer *pPlayer = static_cast<CBaseTFPlayer*>(pActivator); if ( pPlayer ) UpdatePlayerAttachment( pPlayer ); } BaseClass::Use( pActivator, pCaller, useType, value ); }
//----------------------------------------------------------------------------- // Purpose: Only transmit this entity to clients that aren't in our team //----------------------------------------------------------------------------- int CFuncRespawnRoomVisualizer::ShouldTransmit( const CCheckTransmitInfo *pInfo ) { if ( !m_hRespawnRoom || m_hRespawnRoom->GetActive() ) { // Respawn rooms are open in win state if ( TFGameRules()->State_Get() != GR_STATE_TEAM_WIN && GetTeamNumber() != TEAM_UNASSIGNED ) { // Only transmit to enemy players CBaseEntity *pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt ); if ( pRecipientEntity->GetTeamNumber() > LAST_SHARED_TEAM && !InSameTeam(pRecipientEntity) ) return FL_EDICT_ALWAYS; } } return FL_EDICT_DONTSEND; }
//----------------------------------------------------------------------------- // Purpose: Transmit weapon data //----------------------------------------------------------------------------- bool COrder::ShouldTransmit( const edict_t *recipient, const void *pvs, int clientArea ) { CBaseEntity* pRecipientEntity = CBaseEntity::Instance( recipient ); // If this is a personal order, only send to it's owner if ( GetOwner() ) { if ( GetOwner() == pRecipientEntity ) return true; return false; } // Otherwise, only send to players on our team if ( InSameTeam( pRecipientEntity ) ) return true; return false; }
//----------------------------------------------------------------------------- // Purpose: Get into the vehicle //----------------------------------------------------------------------------- void CBaseTFVehicle::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { BaseClass::Use( pActivator, pCaller, useType, value ); if ( useType == USE_ON ) { CBaseTFPlayer *pPlayer = dynamic_cast<CBaseTFPlayer*>(pActivator); if ( pPlayer && InSameTeam(pPlayer) ) { // Check to see if we are really using nearby build points: if( !UseAttachedItem( pActivator, pCaller, useType, value ) ) { // Attempt to board the vehicle: AttemptToBoardVehicle( pPlayer ); } } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CObjectBuffStation::BoostObjectThink( void ) { // Set next boost object think time. SetNextThink( gpGlobals->curtime + BUFF_STATION_BOOST_OBJECT_THINK_INTERVAL, BUFF_STATION_BOOST_OBJECT_THINK_CONTEXT ); // If we're emped, placing, or building, we're not ready to powerup if ( IsPlacing() || IsBuilding() || HasPowerup( POWERUP_EMP ) ) return; float flMaxRangeSq = obj_buff_station_obj_range.GetFloat(); flMaxRangeSq *= flMaxRangeSq; // Boost objects. for ( int iObject = m_nObjectCount; --iObject >= 0; ) { CBaseObject *pObject = m_hObjects[iObject].Get(); if ( !pObject || !InSameTeam( pObject ) ) { DetachObjectByIndex( iObject ); continue; } // Check for out of range. float flDistSq = GetAbsOrigin().DistToSqr( pObject->GetAbsOrigin() ); if ( flDistSq > flMaxRangeSq ) { DetachObjectByIndex( iObject ); continue; } // Don't powerup it until it's finished building if ( pObject->IsPlacing() || pObject->IsBuilding() ) continue; // Boost it if ( !pObject->AttemptToPowerup( POWERUP_BOOST, BUFF_STATION_BOOST_OBJECT_THINK_INTERVAL, 0, this, &m_aObjectAttachInfo[iObject].m_DamageModifier ) ) { m_aObjectAttachInfo[iObject].m_DamageModifier.RemoveModifier(); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CBasePlasmaProjectile::MissileTouch( CBaseEntity *pOther ) { Assert( pOther ); if ( !pOther->IsSolid() ) return; // Create a plasma effect trace_t tr; Vector velDir = GetAbsVelocity(); VectorNormalize( velDir ); Vector vecSpot = GetLocalOrigin() - velDir * 32; // First, just clip to the box Ray_t ray; ray.Init( vecSpot, vecSpot + velDir * 64 ); enginetrace->ClipRayToEntity( ray, MASK_SHOT, pOther, &tr ); // Create the appropriate impact bool bHurtTarget = ( !InSameTeam( pOther ) && pOther->m_takedamage != DAMAGE_NO ); WeaponImpact( &tr, velDir, bHurtTarget, pOther, GetDamageType() ); #if !defined( CLIENT_DLL ) CBaseEntity *pOwner = m_hOwner; // Do damage (unless I'm explosive, in which case I'll do damage later) if ( m_flDamage && !m_flExplosiveRadius ) { ClearMultiDamage(); // Assume it's a projectile, so use its velocity instead Vector vecDamageOrigin = GetAbsVelocity(); VectorNormalize( vecDamageOrigin ); vecDamageOrigin = GetAbsOrigin() - (vecDamageOrigin * 32); CTakeDamageInfo info( this, pOwner, m_flDamage, m_DamageType ); CalculateBulletDamageForce( &info, GetAmmoDef()->Index("MediumRound"), GetAbsVelocity(), vecDamageOrigin ); pOther->DispatchTraceAttack( info, velDir, &tr ); ApplyMultiDamage(); } #endif Detonate(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CEnvLaserDesignation::ShouldTransmit( const edict_t *recipient, const void *pvs, int clientArea ) { // Only transmit to players who care about laser designation: // - Player designating // - Players in tanks // - Commandos CBaseEntity* pRecipientEntity = CBaseEntity::Instance( recipient ); if ( pRecipientEntity->IsPlayer() ) { CBaseTFPlayer *pPlayer = (CBaseTFPlayer*)pRecipientEntity; // Designating player? if ( pPlayer == GetOwnerEntity() ) return true; if ( !InSameTeam( pPlayer ) ) return false; // In a tank? if ( pPlayer->IsInAVehicle() ) { CBaseEntity *pVehicle = pPlayer->GetVehicle()->GetVehicleEnt(); if ( dynamic_cast<CVehicleTank*>(pVehicle) ) { // Make sure it's within range of the tank's fire static float flTankRange = 0; if ( !flTankRange ) { flTankRange = vehicle_tank_range.GetFloat() * weapon_grenade_rocket_track_range_mod.GetFloat(); flTankRange *= flTankRange; } float flDistanceSqr = ( GetAbsOrigin() - pPlayer->GetAbsOrigin() ).LengthSqr(); if ( flDistanceSqr < flTankRange ) return true; } else if ( dynamic_cast<CObjectMannedMissileLauncher*>(pVehicle) ) { // Make sure it's within range of the manned missile launcher's fire static float flGunRange = 0; if ( !flGunRange ) { flGunRange = obj_manned_missilelauncher_range_off.GetFloat() * weapon_grenade_rocket_track_range_mod.GetFloat(); flGunRange *= flGunRange; } float flDistanceSqr = ( GetAbsOrigin() - pPlayer->GetAbsOrigin() ).LengthSqr(); if ( flDistanceSqr < flGunRange ) return true; } } // Is the player a commando? if ( pPlayer->PlayerClass() == TFCLASS_COMMANDO ) { // Make sure it's within range of the commando's rockets static float flCommandoRange = 0; if ( !flCommandoRange ) { flCommandoRange = weapon_rocket_launcher_range.GetFloat() * weapon_grenade_rocket_track_range_mod.GetFloat(); flCommandoRange *= flCommandoRange; } float flDistanceSqr = ( GetAbsOrigin() - pPlayer->GetAbsOrigin() ).LengthSqr(); if ( flDistanceSqr < flCommandoRange ) return true; } } return false; }
//----------------------------------------------------------------------------- // It's a valid ID target when it's building //----------------------------------------------------------------------------- bool C_BaseObject::IsValidIDTarget( void ) { return InSameTeam( C_TFPlayer::GetLocalTFPlayer() ) && m_bBuilding; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_BaseObject::GetTargetIDString( wchar_t *sIDString, int iMaxLenInBytes ) { sIDString[0] = '\0'; C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pLocalPlayer ) return; if ( InSameTeam( pLocalPlayer ) || pLocalPlayer->IsPlayerClass( TF_CLASS_SPY ) || pLocalPlayer->GetTeamNumber() == TEAM_SPECTATOR ) { wchar_t wszBuilderName[ MAX_PLAYER_NAME_LENGTH ]; const char *pszStatusName = GetStatusName(); wchar_t *wszObjectName = g_pVGuiLocalize->Find( pszStatusName ); if ( !wszObjectName ) { wszObjectName = L""; } C_BasePlayer *pBuilder = GetOwner(); if ( pBuilder ) { g_pVGuiLocalize->ConvertANSIToUnicode( pBuilder->GetPlayerName(), wszBuilderName, sizeof(wszBuilderName) ); } else { wszBuilderName[0] = '\0'; } // building or live, show health const char *printFormatString; if ( GetObjectInfo(GetType())->m_AltModes.Count() > 0 ) { printFormatString = "#TF_playerid_object_mode"; pszStatusName = GetObjectInfo( GetType() )->m_AltModes.Element( m_iObjectMode * 3 + 1 ); wchar_t *wszObjectModeName = g_pVGuiLocalize->Find( pszStatusName ); if ( !wszObjectModeName ) { wszObjectModeName = L""; } g_pVGuiLocalize->ConstructString( sIDString, iMaxLenInBytes, g_pVGuiLocalize->Find(printFormatString), 4, wszObjectName, wszBuilderName, wszObjectModeName); } else { if ( m_bMiniBuilding ) printFormatString = "#TF_playerid_object_mini"; else printFormatString = "#TF_playerid_object"; g_pVGuiLocalize->ConstructString( sIDString, iMaxLenInBytes, g_pVGuiLocalize->Find( printFormatString ), 3, wszObjectName, wszBuilderName ); } } }