//----------------------------------------------------------------------------- // Purpose: Per-frame handler //----------------------------------------------------------------------------- void CTFGameStats::FrameUpdatePostEntityThink() { // see if any players have stat changes we need to send for( int iPlayerIndex = 1 ; iPlayerIndex <= MAX_PLAYERS; iPlayerIndex++ ) { CTFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( iPlayerIndex ) ); if ( pPlayer && pPlayer->IsConnected() && pPlayer->IsAlive() ) { PlayerStats_t &stats = m_aPlayerStats[pPlayer->entindex()]; // if there are any updated stats for this player and we haven't sent a stat update for this player in the last second, // send one now. if ( ( stats.iStatsChangedBits > 0 ) && ( gpGlobals->curtime >= stats.m_flTimeLastSend + 1.0f ) ) { SendStatsToPlayer( pPlayer, STATMSG_UPDATE ); } } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponKritzkrieg::RemoveHealingTarget( bool bStopHealingSelf ) { CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() ); if ( !pOwner ) return; #ifdef GAME_DLL if ( m_hHealingTarget ) { // HACK: For now, just deal with players if ( m_hHealingTarget->IsPlayer() ) { CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() ); CTFPlayer *pTFPlayer = ToTFPlayer( m_hHealingTarget ); pTFPlayer->m_Shared.StopHealing( pOwner ); pTFPlayer->m_Shared.RecalculateInvuln( false ); pTFPlayer->m_Shared.RecalculateCrits(false); pOwner->SpeakConceptIfAllowed( MP_CONCEPT_MEDIC_STOPPEDHEALING, pTFPlayer->IsAlive() ? "healtarget:alive" : "healtarget:dead" ); pTFPlayer->SpeakConceptIfAllowed( MP_CONCEPT_HEALTARGET_STOPPEDHEALING ); } } // Stop thinking - we no longer have a heal target. SetContextThink( NULL, 0, s_pszKritzkriegHealTargetThink ); #endif m_hHealingTarget.Set( NULL ); // Stop the welding animation if ( m_bHealing ) { SendWeaponAnim( ACT_MP_ATTACK_STAND_POSTFIRE ); pOwner->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_POST ); } #ifndef CLIENT_DLL m_DamageModifier.RemoveModifier(); #endif m_bHealing = false; }
//----------------------------------------------------------------------------- // 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; }