void CHudDamageIndicator::CalcDamageDirection( const Vector &vecFrom ) { if ( vecFrom == vec3_origin ) { m_flAttackFront = 0.0; m_flAttackRear = 0.0; m_flAttackRight = 0.0; m_flAttackLeft = 0.0; return; } C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); if ( !pLocalPlayer ) { return; } Vector vecDelta = ( vecFrom - pLocalPlayer->GetRenderOrigin() ); if ( vecDelta.Length() <= 50 ) { m_flAttackFront = 1.0; m_flAttackRear = 1.0; m_flAttackRight = 1.0; m_flAttackLeft = 1.0; return; } VectorNormalize( vecDelta ); Vector forward; Vector right; AngleVectors( MainViewAngles(), &forward, &right, NULL ); float flFront = DotProduct( vecDelta, forward ); float flSide = DotProduct( vecDelta, right ); if ( flFront > 0 ) { if ( flFront > 0.3 ) m_flAttackFront = max( m_flAttackFront, flFront ); } else { float f = fabs( flFront ); if ( f > 0.3 ) m_flAttackRear = max( m_flAttackRear, f ); } if ( flSide > 0 ) { if ( flSide > 0.3 ) m_flAttackRight = max( m_flAttackRight, flSide ); } else { float f = fabs( flSide ); if ( f > 0.3 ) m_flAttackLeft = max( m_flAttackLeft, f ); } }
bool CFlashlightEffect::ComputeLightPosAndOrientation( const Vector &vecPos, const Vector &vecForward, const Vector &vecRight, const Vector &vecUp, Vector& vecFinalPos, Quaternion& quatOrientation, bool bTracePlayers ) { const float flEpsilon = 0.1f; // Offset flashlight position along vecUp float flDistCutoff = r_flashlighttracedistcutoff.GetFloat(); const float flDistDrag = 0.2; bool bDebugVis = r_flashlightvisualizetrace.GetBool(); C_BasePlayer *pPlayer = UTIL_PlayerByIndex( m_nEntIndex ); if ( !pPlayer ) { pPlayer = C_BasePlayer::GetLocalPlayer(); if ( !pPlayer ) { Assert( false ); return false; } } // We will lock some of the flashlight params if player is on a ladder, to prevent oscillations due to the trace-rays bool bPlayerOnLadder = ( pPlayer->GetMoveType() == MOVETYPE_LADDER ); CTraceFilterSkipPlayerAndViewModel traceFilter( pPlayer, bTracePlayers ); // Vector vOrigin = vecPos + r_flashlightoffsety.GetFloat() * vecUp; Vector vecOffset; pPlayer->GetFlashlightOffset( vecForward, vecRight, vecUp, &vecOffset ); Vector vOrigin = vecPos + vecOffset; // Not on ladder...trace a hull if ( !bPlayerOnLadder ) { Vector vecPlayerEyePos = pPlayer->GetRenderOrigin() + pPlayer->GetViewOffset(); trace_t pmOriginTrace; UTIL_TraceHull( vecPlayerEyePos, vOrigin, Vector(-2, -2, -2), Vector(2, 2, 2), ( MASK_SOLID & ~(CONTENTS_HITBOX) ) | CONTENTS_WINDOW | CONTENTS_GRATE, &traceFilter, &pmOriginTrace );//1 if ( bDebugVis ) { debugoverlay->AddBoxOverlay( pmOriginTrace.endpos, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), QAngle( 0, 0, 0 ), 0, 255, 0, 16, 0 ); if ( pmOriginTrace.DidHit() || pmOriginTrace.startsolid ) { debugoverlay->AddLineOverlay( pmOriginTrace.startpos, pmOriginTrace.endpos, 255, 128, 128, true, 0 ); } else { debugoverlay->AddLineOverlay( pmOriginTrace.startpos, pmOriginTrace.endpos, 255, 0, 0, true, 0 ); } } if ( pmOriginTrace.DidHit() || pmOriginTrace.startsolid ) { vOrigin = pmOriginTrace.endpos; } else { if ( pPlayer->m_vecFlashlightOrigin != vecPlayerEyePos ) { vOrigin = vecPos; } } } else // on ladder...skip the above hull trace { vOrigin = vecPos; } // Now do a trace along the flashlight direction to ensure there is nothing within range to pull back from int iMask = MASK_OPAQUE_AND_NPCS; iMask &= ~CONTENTS_HITBOX; iMask |= CONTENTS_WINDOW | CONTENTS_GRATE | CONTENTS_IGNORE_NODRAW_OPAQUE; Vector vTarget = vOrigin + vecForward * r_flashlightfar.GetFloat(); // Work with these local copies of the basis for the rest of the function Vector vDir = vTarget - vOrigin; Vector vRight = vecRight; Vector vUp = vecUp; VectorNormalize( vDir ); VectorNormalize( vRight ); VectorNormalize( vUp ); // Orthonormalize the basis, since the flashlight texture projection will require this later... vUp -= DotProduct( vDir, vUp ) * vDir; VectorNormalize( vUp ); vRight -= DotProduct( vDir, vRight ) * vDir; VectorNormalize( vRight ); vRight -= DotProduct( vUp, vRight ) * vUp; VectorNormalize( vRight ); AssertFloatEquals( DotProduct( vDir, vRight ), 0.0f, 1e-3 ); AssertFloatEquals( DotProduct( vDir, vUp ), 0.0f, 1e-3 ); AssertFloatEquals( DotProduct( vRight, vUp ), 0.0f, 1e-3 ); trace_t pmDirectionTrace; UTIL_TraceHull( vOrigin, vTarget, Vector( -1.5, -1.5, -1.5 ), Vector( 1.5, 1.5, 1.5 ), iMask, &traceFilter, &pmDirectionTrace );//.5 if ( bDebugVis ) { debugoverlay->AddBoxOverlay( pmDirectionTrace.endpos, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ), QAngle( 0, 0, 0 ), 0, 0, 255, 16, 0 ); debugoverlay->AddLineOverlay( vOrigin, pmDirectionTrace.endpos, 255, 0, 0, false, 0 ); } float flTargetPullBackDist = 0.0f; float flDist = (pmDirectionTrace.endpos - vOrigin).Length(); if ( flDist < flDistCutoff ) { // We have an intersection with our cutoff range // Determine how far to pull back, then trace to see if we are clear float flPullBackDist = bPlayerOnLadder ? r_flashlightladderdist.GetFloat() : flDistCutoff - flDist; // Fixed pull-back distance if on ladder flTargetPullBackDist = flPullBackDist; if ( !bPlayerOnLadder ) { trace_t pmBackTrace; // start the trace away from the actual trace origin a bit, to avoid getting stuck on small, close "lips" UTIL_TraceHull( vOrigin - vDir * ( flDistCutoff * r_flashlightbacktraceoffset.GetFloat() ), vOrigin - vDir * ( flPullBackDist - flEpsilon ), Vector( -1.5f, -1.5f, -1.5f ), Vector( 1.5f, 1.5f, 1.5f ), iMask, &traceFilter, &pmBackTrace ); if ( bDebugVis ) { debugoverlay->AddLineOverlay( pmBackTrace.startpos, pmBackTrace.endpos, 255, 0, 255, true, 0 ); } if( pmBackTrace.DidHit() ) { // We have an intersection behind us as well, so limit our flTargetPullBackDist float flMaxDist = (pmBackTrace.endpos - vOrigin).Length() - flEpsilon; flTargetPullBackDist = MIN( flMaxDist, flTargetPullBackDist ); //m_flCurrentPullBackDist = MIN( flMaxDist, m_flCurrentPullBackDist ); // possible pop } } } if ( bDebugVis ) { // visualize pullback debugoverlay->AddBoxOverlay( vOrigin - vDir * m_flCurrentPullBackDist, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), QAngle( 0, 0, 0 ), 255, 255, 0, 16, 0 ); debugoverlay->AddBoxOverlay( vOrigin - vDir * flTargetPullBackDist, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 128, 128, 0, 16, 0 ); } m_flCurrentPullBackDist = Lerp( flDistDrag, m_flCurrentPullBackDist, flTargetPullBackDist ); m_flCurrentPullBackDist = MIN( m_flCurrentPullBackDist, flDistCutoff ); // clamp to max pullback dist vOrigin = vOrigin - vDir * m_flCurrentPullBackDist; vecFinalPos = vOrigin; BasisToQuaternion( vDir, vRight, vUp, quatOrientation ); return true; }
//----------------------------------------------------------------------------- // Purpose: Draw function for the element //----------------------------------------------------------------------------- void CTargetID::Paint() { C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if ( !pPlayer ) return; // No id if still choosing class if ( C_BaseTFPlayer::GetLocalPlayer()->GetClass() == TFCLASS_UNDECIDED ) return; // Get our target's ent index int iEntIndex = C_BaseTFPlayer::GetLocalPlayer()->GetIDTarget(); // Didn't find one? if ( !iEntIndex ) { // Check to see if we should clear our ID if ( m_flLastChangeTime && (gpGlobals->curtime > (m_flLastChangeTime + 0.5)) ) { m_flLastChangeTime = 0; m_sIDString[0] = 0; m_iLastEntIndex = 0; } else { // Keep re-using the old one iEntIndex = m_iLastEntIndex; } } else { m_flLastChangeTime = gpGlobals->curtime; } // Is this an entindex sent by the server? if ( iEntIndex ) { C_BaseTFPlayer *pPlayer = static_cast<C_BaseTFPlayer*>(cl_entitylist->GetEnt( iEntIndex )); C_BaseTFPlayer *pLocalPlayer = C_BaseTFPlayer::GetLocalPlayer(); // Some entities we always want to check, cause the text may change // even while we're looking at it // Is it a player? if ( IsPlayerIndex( iEntIndex ) ) { if ( pPlayer->InSameTeam(pLocalPlayer) ) { // Check distance to other player, and if the player is on the same team float flDistSq = pPlayer->GetRenderOrigin().DistToSqr( pLocalPlayer->GetRenderOrigin() ); if ( flDistSq < PLAYER_HINT_DISTANCE_SQ ) { Q_snprintf( m_sIDString, sizeof(m_sIDString), "%s\nHealth: %.0f percent\nUse to donate resources", pPlayer->GetPlayerName(), ((float)pPlayer->GetHealth() / (float)pPlayer->GetMaxHealth() ) * 100 ); } else { Q_snprintf( m_sIDString, sizeof(m_sIDString), "%s\nHealth: %.0f percent", pPlayer->GetPlayerName(), ((float)pPlayer->GetHealth() / (float)pPlayer->GetMaxHealth() ) * 100 ); } } else if (( pPlayer->GetHealth() == 0) && (pLocalPlayer->GetClass() == TFCLASS_INFILTRATOR) ) { Q_snprintf( m_sIDString, sizeof(m_sIDString), "%s\nUse to disguise as this player", pPlayer->GetPlayerName() ); } else { m_sIDString[0] = 0; m_iLastEntIndex = 0; } } else { // Objects C_BaseEntity *pEnt = cl_entitylist->GetEnt( iEntIndex ); if ( !pEnt || !pEnt->InSameTeam(pLocalPlayer) ) { // This can happen because the object was destroyed m_sIDString[0] = 0; m_iLastEntIndex = 0; } else { // Don't check validity if it's sent by the server Q_strncpy( m_sIDString, pEnt->GetIDString(), sizeof(m_sIDString) ); m_iLastEntIndex = iEntIndex; } } } // Draw our ID string if ( m_sIDString[0] ) { int width, height; int ypos = YRES(300); // Messagechars can't handle multiple line strings, so parse out the \n's and give it one line at a time char *ch = m_sIDString; while ( *ch ) { // Find the next newline char *next_line; for ( next_line = ch; *next_line != '\n' && *next_line != 0; next_line++ ) { } // Stomp the newline char *top = next_line; if ( *top == '\n' ) { *top = 0; } else { top = NULL; } // Draw the line messagechars->GetStringLength( m_hFont, &width, &height, ch ); messagechars->DrawString( m_hFont, (ScreenWidth() - width) / 2, ypos, 255, 255, 245, 255, ch, IMessageChars::MESSAGESTRINGID_NONE ); ypos += height; // Restore the newline if ( top ) { *top = '\n'; } // Move to the next line ch = next_line; if ( *ch == '\n' ) { ch++; } } } }