//----------------------------------------------------------------------------- // Purpose: Forces a recompare //----------------------------------------------------------------------------- void CSensorTFTeam::Think( ) { if (!m_pTeam) return; // Check for a difference in the number of respawn stations int nRespawnCount = ComputeRespawnCount(); if ( nRespawnCount != m_nRespawnCount ) { m_OnRespawnCountChangedDelta.Set( nRespawnCount - m_nRespawnCount, this, this ); m_nRespawnCount = nRespawnCount; m_OnRespawnCountChanged.Set( m_nRespawnCount, this, this ); } // Check for a difference in the number of resources harvested if ( m_nResourceCount != m_pTeam->m_flTotalResourcesSoFar ) { m_OnResourceCountChangedDelta.Set( m_pTeam->m_flTotalResourcesSoFar - m_nResourceCount, this, this ); m_nResourceCount = m_pTeam->m_flTotalResourcesSoFar; m_OnResourceCountChanged.Set( m_nResourceCount, this, this ); } // Check for a difference in the number of team members if ( m_nMemberCount != m_pTeam->GetNumPlayers() ) { m_OnMemberCountChangedDelta.Set( m_pTeam->GetNumPlayers() - m_nMemberCount, this, this ); m_nMemberCount = m_pTeam->GetNumPlayers(); m_OnMemberCountChanged.Set( m_nMemberCount, this, this ); } SetNextThink( gpGlobals->curtime + 0.1f ); }
//----------------------------------------------------------------------------- // Compute the number of respawn stations on this team //----------------------------------------------------------------------------- int CSensorTFTeam::ComputeRespawnCount() { int nCount = 0; for (int i = m_pTeam->GetNumObjects(); --i >= 0; ) { CBaseObject *pObject = m_pTeam->GetObject(i); if ( pObject && (pObject->GetType() == OBJ_RESPAWN_STATION) ) { ++nCount; } } return nCount; }
bool OrderCreator_GenericObject( CPlayerClass *pClass, int objectType, float flMaxDist, COrder *pOrder ) { // Can we build one? if ( pClass->CanBuild( objectType ) != CB_CAN_BUILD ) return false; CBaseTFPlayer *pPlayer = pClass->GetPlayer(); CTFTeam *pTeam = pClass->GetTeam(); // Sort nearby objects. CSortBase info; info.m_pPlayer = pPlayer; info.m_flMaxDist = flMaxDist; info.m_ObjectType = objectType; int sorted[MAX_TEAM_OBJECTS]; int nSorted = BuildSortedActiveList( sorted, // the sorted list of objects MAX_TEAM_OBJECTS, SortFn_DistanceAndConcentration, // sort on distance and entity concentration IsValidFn_NearAndNotCovered, // filter function &info, // user data pTeam->GetNumObjects() // number of objects to check ); if( nSorted ) { // Ok, make an order to cover the closest object with a sentry gun. CBaseEntity *pEnt = pTeam->GetObject( sorted[0] ); pTeam->AddOrder( ORDER_BUILD, pEnt, pPlayer, flMaxDist, 60, pOrder ); return true; } else { return false; } }
bool COrderHeal::CreateOrder( CPlayerClass *pClass ) { CTFTeam *pTeam = pClass->GetTeam(); CSortBase info; info.m_pPlayer = pClass->GetPlayer(); int sorted[MAX_PLAYERS]; int nSorted = BuildSortedActiveList( sorted, MAX_PLAYERS, SortFn_Heal, IsValidFn_Heal, &info, pTeam->GetNumPlayers() ); if ( nSorted ) { COrderHeal *pOrder = new COrderHeal; pClass->GetTeam()->AddOrder( ORDER_HEAL, pTeam->GetPlayer( sorted[0] ), pClass->GetPlayer(), 1e24, 60, pOrder ); return true; } else { return false; } }
//----------------------------------------------------------------------------- // Purpose: // Input : *pTeam - //----------------------------------------------------------------------------- void CObjectResupply::ChangeTeam( int iTeamNum ) { CTFTeam *pExisting = (CTFTeam*)GetTeam(); CTFTeam *pTeam = (CTFTeam*)GetGlobalTeam( iTeamNum ); // Already on this team if ( GetTeamNumber() == iTeamNum ) return; if ( pExisting ) { // Remove it from current team ( if it's in one ) and give it to new team pExisting->RemoveResupply( this ); } // Change to new team BaseClass::ChangeTeam( iTeamNum ); // Add this object to the team's list if (pTeam) { pTeam->AddResupply( this ); } }
//----------------------------------------------------------------------------- // 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; }
//----------------------------------------------------------------------------- // Purpose: Think method //----------------------------------------------------------------------------- void CTFFlameEntity::FlameThink( void ) { // if we've expired, remove ourselves if ( gpGlobals->curtime >= m_flTimeRemove ) { UTIL_Remove( this ); return; } // Do collision detection. We do custom collision detection because we can do it more cheaply than the // standard collision detection (don't need to check against world unless we might have hit an enemy) and // flame entity collision detection w/o this was a bottleneck on the X360 server if ( GetAbsOrigin() != m_vecPrevPos ) { CTFPlayer *pAttacker = dynamic_cast<CTFPlayer *>( (CBaseEntity *) m_hAttacker ); if ( !pAttacker ) return; CUtlVector<CTFTeam *> pTeamList; CTFTeam *pTeam = pAttacker->GetTFTeam(); if ( pTeam ) pTeam->GetOpposingTFTeamList(&pTeamList); else return; //CTFTeam *pTeam = pAttacker->GetOpposingTFTeam(); //if ( !pTeam ) // return; bool bHitWorld = false; for (int i = 0; i < pTeamList.Size(); i++) { if (pTeamList[i]) { // check collision against all enemy players for (int iPlayer = 0; iPlayer < pTeamList[i]->GetNumPlayers(); iPlayer++) { CBasePlayer *pPlayer = pTeamList[i]->GetPlayer(iPlayer); // Is this player connected, alive, and an enemy? if (pPlayer && pPlayer->IsConnected() && pPlayer->IsAlive() && pPlayer!=pAttacker) { CheckCollision(pPlayer, &bHitWorld); if (bHitWorld) return; } } // check collision against all enemy objects for (int iObject = 0; iObject < pTeamList[i]->GetNumObjects(); iObject++) { CBaseObject *pObject = pTeamList[i]->GetObject(iObject); if (pObject) { CheckCollision(pObject, &bHitWorld); if (bHitWorld) return; } } } } } // Calculate how long the flame has been alive for float flFlameElapsedTime = tf_flamethrower_flametime.GetFloat() - ( m_flTimeRemove - gpGlobals->curtime ); // Calculate how much of the attacker's velocity to blend in to the flame's velocity. The flame gets the attacker's velocity // added right when the flame is fired, but that velocity addition fades quickly to zero. float flAttackerVelocityBlend = RemapValClamped( flFlameElapsedTime, tf_flamethrower_velocityfadestart.GetFloat(), tf_flamethrower_velocityfadeend.GetFloat(), 1.0, 0 ); // Reduce our base velocity by the air drag constant m_vecBaseVelocity *= tf_flamethrower_drag.GetFloat(); // Add our float upward velocity Vector vecVelocity = m_vecBaseVelocity + Vector( 0, 0, tf_flamethrower_float.GetFloat() ) + ( flAttackerVelocityBlend * m_vecAttackerVelocity ); // Update our velocity SetAbsVelocity( vecVelocity ); // Render debug visualization if convar on if ( tf_debug_flamethrower.GetInt() ) { if ( m_hEntitiesBurnt.Count() > 0 ) { int val = ( (int) ( gpGlobals->curtime * 10 ) ) % 255; NDebugOverlay::EntityBounds(this, val, 255, val, 0 ,0 ); } else { NDebugOverlay::EntityBounds(this, 0, 100, 255, 0 ,0) ; } } SetNextThink( gpGlobals->curtime ); m_vecPrevPos = GetAbsOrigin(); }