bool IsValidFn_NearAndNotCovered( void *pUserData, int a ) { CSortBase *p = (CSortBase*)pUserData; CBaseObject *pObj = p->m_pPlayer->GetTFTeam()->GetObject( a ); // Is the object too far away to be covered? if ( p->m_pPlayer->GetAbsOrigin().DistTo( pObj->GetAbsOrigin() ) > p->m_flMaxDist ) return false; // Don't cover certain entities (like sentry guns, sand bags, etc). switch( p->m_ObjectType ) { case OBJ_SENTRYGUN_PLASMA: { if ( !pObj->WantsCoverFromSentryGun() ) return false; if ( p->m_pPlayer->GetTFTeam()->IsCoveredBySentryGun( pObj->GetAbsOrigin() ) ) return false; } break; case OBJ_SHIELDWALL: { if ( !pObj->WantsCover() ) return false; if ( p->m_pPlayer->GetTFTeam()->GetNumShieldWallsCoveringPosition( pObj->GetAbsOrigin() ) ) return false; } break; case OBJ_RESUPPLY: { if ( p->m_pPlayer->GetTFTeam()->GetNumResuppliesCoveringPosition( pObj->GetAbsOrigin() ) ) return false; } break; case OBJ_RESPAWN_STATION: { if ( p->m_pPlayer->GetTFTeam()->GetNumRespawnStationsCoveringPosition( pObj->GetAbsOrigin() ) ) return false; } break; default: { Assert( !"Unsupported object type" ); } break; } return true; }
int SortFn_PlayerObjectsByDistance( void *pUserData, int a, int b ) { CSortBase *pSortBase = (CSortBase*)pUserData; CBaseObject* pObjA = pSortBase->m_pPlayer->GetObject(a); CBaseObject* pObjB = pSortBase->m_pPlayer->GetObject(b); if (!pObjA) return false; if (!pObjB) return true; const Vector &v = pSortBase->m_pPlayer->GetAbsOrigin(); return v.DistTo( pObjA->GetAbsOrigin() ) < v.DistTo( pObjB->GetAbsOrigin() ); }
//----------------------------------------------------------------------------- // 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(); } } }
int SortFn_DistanceAndConcentration( void *pUserData, int a, int b ) { CSortBase *p = (CSortBase*)pUserData; // Compare distances. Each rope attachment to another ent // subtracts 200 inches, so the order is biased towards covering // groups of objects together. CBaseObject *pObjectA = p->GetTeam()->GetObject( a ); CBaseObject *pObjectB = p->GetTeam()->GetObject( b ); const Vector &vOrigin1 = pObjectA->GetAbsOrigin(); const Vector &vOrigin2 = p->GetTeam()->GetObject( b )->GetAbsOrigin(); float flScore1 = -p->m_pPlayer->GetAbsOrigin().DistTo( vOrigin1 ); float flScore2 = -p->m_pPlayer->GetAbsOrigin().DistTo( vOrigin2 ); flScore1 += pObjectA->RopeCount() * 200; flScore2 += pObjectB->RopeCount() * 200; return flScore1 > flScore2; }
//----------------------------------------------------------------------------- // Look for a target //----------------------------------------------------------------------------- bool CObjectSentrygun::FindTarget() { // Disable the sentry guns for ifm. if ( tf_sentrygun_notarget.GetBool() ) return false; if ( IsInCommentaryMode() ) return false; // Sapper, etc. if ( IsDisabled() ) return false; // Loop through players within 1100 units (sentry range). Vector vecSentryOrigin = EyePosition(); // Find the opposing team list. CTFPlayer *pPlayer = ToTFPlayer( GetOwner() ); CUtlVector<CTFTeam *> pTeamList; CTFTeam *pTeam = NULL; //CTFTeam *pTeam = pPlayer->GetOpposingTFTeam(); //if ( !pTeam ) // return false; if ( pPlayer ) { // Try builder's team. pTeam = pPlayer->GetTFTeam(); } else { // If we have no builder use our own team number instead. pTeam = GetTFTeam(); } if ( pTeam ) pTeam->GetOpposingTFTeamList( &pTeamList ); else return false; // If we have an enemy get his minimum distance to check against. Vector vecSegment; Vector vecTargetCenter; float flMinDist2 = 1100.0f * 1100.0f; CBaseEntity *pTargetCurrent = NULL; CBaseEntity *pTargetOld = m_hEnemy.Get(); float flOldTargetDist2 = FLT_MAX; // Sentries will try to target players first, then objects. However, if the enemy held was an object it will continue // to try and attack it first. for (int i = 0; i < pTeamList.Size(); i++) { int nTeamCount = pTeamList[i]->GetNumPlayers(); for (int iPlayer = 0; iPlayer < nTeamCount; ++iPlayer) { CTFPlayer *pTargetPlayer = static_cast<CTFPlayer*>(pTeamList[i]->GetPlayer(iPlayer)); if (pTargetPlayer == NULL) continue; // Make sure the player is alive. if (!pTargetPlayer->IsAlive()) continue; if (pTargetPlayer->GetFlags() & FL_NOTARGET) continue; vecTargetCenter = pTargetPlayer->GetAbsOrigin(); vecTargetCenter += pTargetPlayer->GetViewOffset(); VectorSubtract(vecTargetCenter, vecSentryOrigin, vecSegment); float flDist2 = vecSegment.LengthSqr(); // Store the current target distance if we come across it if (pTargetPlayer == pTargetOld) { flOldTargetDist2 = flDist2; } // Check to see if the target is closer than the already validated target. if (flDist2 > flMinDist2) continue; // It is closer, check to see if the target is valid. if (ValidTargetPlayer(pTargetPlayer, vecSentryOrigin, vecTargetCenter)) { flMinDist2 = flDist2; pTargetCurrent = pTargetPlayer; } } // If we already have a target, don't check objects. if (pTargetCurrent == NULL) { int nTeamObjectCount = pTeamList[i]->GetNumObjects(); for (int iObject = 0; iObject < nTeamObjectCount; ++iObject) { CBaseObject *pTargetObject = pTeamList[i]->GetObject(iObject); if (!pTargetObject) continue; vecTargetCenter = pTargetObject->GetAbsOrigin(); vecTargetCenter += pTargetObject->GetViewOffset(); VectorSubtract(vecTargetCenter, vecSentryOrigin, vecSegment); float flDist2 = vecSegment.LengthSqr(); // Store the current target distance if we come across it if (pTargetObject == pTargetOld) { flOldTargetDist2 = flDist2; } // Check to see if the target is closer than the already validated target. if (flDist2 > flMinDist2) continue; // It is closer, check to see if the target is valid. if (ValidTargetObject(pTargetObject, vecSentryOrigin, vecTargetCenter)) { flMinDist2 = flDist2; pTargetCurrent = pTargetObject; } } } // We have a target. if (pTargetCurrent) { if (pTargetCurrent != pTargetOld) { // flMinDist2 is the new target's distance // flOldTargetDist2 is the old target's distance // Don't switch unless the new target is closer by some percentage if (flMinDist2 < (flOldTargetDist2 * 0.75f)) { FoundTarget(pTargetCurrent, vecSentryOrigin); } } return true; } } return false; }