Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

215 lines
5.4 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include <string.h>
#include <stdio.h>
#include "dod_headiconmanager.h"
#include "c_playerresource.h"
#include "cliententitylist.h"
#include "c_baseplayer.h"
#include "materialsystem/imesh.h"
#include "view.h"
#include "materialsystem/imaterial.h"
#include "tier0/dbg.h"
#include "cdll_int.h"
#include "dod_shareddefs.h"
#include "c_dod_player.h"
#include "voice_status.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
static CHeadIconManager s_HeadIconMgr;
CHeadIconManager* HeadIconManager()
{
return &s_HeadIconMgr;
}
CHeadIconManager::CHeadIconManager()
{
m_pAlliesIconMaterial = NULL;
m_pAxisIconMaterial = NULL;
}
CHeadIconManager::~CHeadIconManager()
{
Shutdown();
}
bool CHeadIconManager::Init()
{
if ( !m_pAlliesIconMaterial )
{
m_pAlliesIconMaterial = materials->FindMaterial( "sprites/player_icons/american", TEXTURE_GROUP_VGUI );
}
if ( !m_pAxisIconMaterial )
{
m_pAxisIconMaterial = materials->FindMaterial( "sprites/player_icons/german", TEXTURE_GROUP_VGUI );
}
if ( IsErrorMaterial( m_pAlliesIconMaterial ) ||
IsErrorMaterial( m_pAxisIconMaterial ) )
{
Assert(!"Can't find head icon materials");
return false;
}
m_pAlliesIconMaterial->IncrementReferenceCount();
m_pAxisIconMaterial->IncrementReferenceCount();
m_PlayerDrawn.ClearAll();
return true;
}
void CHeadIconManager::Shutdown()
{
if ( m_pAlliesIconMaterial )
{
m_pAlliesIconMaterial->DecrementReferenceCount();
m_pAlliesIconMaterial = NULL;
}
if ( m_pAxisIconMaterial )
{
m_pAxisIconMaterial->DecrementReferenceCount();
m_pAxisIconMaterial = NULL;
}
}
//-----------------------------------------------------------------------------
// Call from player render calls to indicate a head icon should be drawn for this player this frame
//-----------------------------------------------------------------------------
void CHeadIconManager::PlayerDrawn( C_BasePlayer *pPlayer )
{
m_PlayerDrawn.Set( pPlayer->entindex() - 1 );
}
ConVar cl_headiconoffset( "cl_headiconoffset", "24", FCVAR_CHEAT );
ConVar cl_headiconsize( "cl_headiconsize", "8", FCVAR_CHEAT );
ConVar cl_identiconmode( "cl_identiconmode", "2", FCVAR_ARCHIVE, "2 - icons over teammates' heads\n1- icons over target teammate\n0 - no head icons" );
void CHeadIconManager::DrawHeadIcons()
{
CMatRenderContextPtr pRenderContext( materials );
CBitVec<MAX_PLAYERS> playerDrawn = m_PlayerDrawn;
m_PlayerDrawn.ClearAll();
if ( cl_identiconmode.GetInt() <= 0 )
return;
C_DODPlayer *pLocalPlayer = C_DODPlayer::GetLocalDODPlayer();
if ( !pLocalPlayer )
return;
if ( pLocalPlayer->GetTeamNumber() != TEAM_ALLIES &&
pLocalPlayer->GetTeamNumber() != TEAM_AXIS )
{
return;
}
Vector vUp = CurrentViewUp();
Vector vRight = CurrentViewRight();
if ( fabs( vRight.z ) > 0.95 ) // don't draw it edge-on
return;
vRight.z = 0;
VectorNormalize( vRight );
float flSize = cl_headiconsize.GetFloat();
for(int i=0; i < MAX_PLAYERS; i++)
{
if ( !playerDrawn.IsBitSet( i ) )
continue;
if ( cl_identiconmode.GetInt() == 1 )
{
// only draw if this player is our status bar target
if ( (i+1) != pLocalPlayer->GetIDTarget() )
continue;
}
IClientNetworkable *pClient = cl_entitylist->GetClientEntity( i+1 );
// Don't show an icon if the player is not in our PVS.
if ( !pClient || pClient->IsDormant() )
continue;
C_DODPlayer *pPlayer = dynamic_cast<C_DODPlayer*>(pClient);
if( !pPlayer )
continue;
// Don't show an icon for dead or spectating players (ie: invisible entities).
if( pPlayer->IsPlayerDead() )
continue;
if( pPlayer == pLocalPlayer )
continue;
if( pPlayer->GetTeamNumber() != pLocalPlayer->GetTeamNumber() )
continue;
if ( GetClientVoiceMgr()->IsPlayerSpeaking( i+1 ) )
continue;
if ( C_BasePlayer::GetLocalPlayer()->GetObserverMode() == OBS_MODE_IN_EYE &&
C_BasePlayer::GetLocalPlayer()->GetObserverTarget() == pPlayer )
continue;
IMaterial *pMaterial = pPlayer->GetHeadIconMaterial();
if ( !pMaterial )
continue;
pRenderContext->Bind( pMaterial );
Vector vOrigin;
QAngle vAngle;
int iHeadAttach = pPlayer->LookupAttachment( "head" );
pPlayer->GetAttachment( iHeadAttach, vOrigin, vAngle );
vOrigin.z += cl_headiconoffset.GetFloat();
// Align it towards the viewer
IMesh *pMesh = pRenderContext->GetDynamicMesh();
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
meshBuilder.Color3f( 1.0, 1.0, 1.0 );
meshBuilder.TexCoord2f( 0,0,0 );
meshBuilder.Position3fv( (vOrigin + (vRight * -flSize) + (vUp * flSize)).Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Color3f( 1.0, 1.0, 1.0 );
meshBuilder.TexCoord2f( 0,1,0 );
meshBuilder.Position3fv( (vOrigin + (vRight * flSize) + (vUp * flSize)).Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Color3f( 1.0, 1.0, 1.0 );
meshBuilder.TexCoord2f( 0,1,1 );
meshBuilder.Position3fv( (vOrigin + (vRight * flSize) + (vUp * -flSize)).Base() );
meshBuilder.AdvanceVertex();
meshBuilder.Color3f( 1.0, 1.0, 1.0 );
meshBuilder.TexCoord2f( 0,0,1 );
meshBuilder.Position3fv( (vOrigin + (vRight * -flSize) + (vUp * -flSize)).Base() );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
}