source-engine/game/client/proxyplayer.cpp

524 lines
13 KiB
C++
Raw Permalink Normal View History

2020-04-23 00:56:21 +08:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include <KeyValues.h>
#include "materialsystem/imaterialvar.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/itexture.h"
#include "materialsystem/imaterialsystem.h"
#include "functionproxy.h"
#include "toolframework_client.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// forward declarations
void ToolFramework_RecordMaterialParams( IMaterial *pMaterial );
//-----------------------------------------------------------------------------
// Returns the proximity of the player to the entity
//-----------------------------------------------------------------------------
class CPlayerProximityProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
float m_Factor;
};
bool CPlayerProximityProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
m_Factor = pKeyValues->GetFloat( "scale", 0.002 );
return true;
}
void CPlayerProximityProxy::OnBind( void *pC_BaseEntity )
{
if (!pC_BaseEntity)
return;
// Find the distance between the player and this entity....
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer();
if (!pPlayer)
return;
Vector delta;
VectorSubtract( pEntity->WorldSpaceCenter(), pPlayer->WorldSpaceCenter(), delta );
Assert( m_pResult );
SetFloatResult( delta.Length() * m_Factor );
if ( ToolsEnabled() )
{
ToolFramework_RecordMaterialParams( GetMaterial() );
}
}
EXPOSE_INTERFACE( CPlayerProximityProxy, IMaterialProxy, "PlayerProximity" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Returns true if the player's team matches that of the entity the proxy material is attached to
//-----------------------------------------------------------------------------
class CPlayerTeamMatchProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
};
bool CPlayerTeamMatchProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
return true;
}
void CPlayerTeamMatchProxy::OnBind( void *pC_BaseEntity )
{
if (!pC_BaseEntity)
return;
// Find the distance between the player and this entity....
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer();
if (!pPlayer)
return;
Assert( m_pResult );
SetFloatResult( (pEntity->GetTeamNumber() == pPlayer->GetTeamNumber()) ? 1.0 : 0.0 );
if ( ToolsEnabled() )
{
ToolFramework_RecordMaterialParams( GetMaterial() );
}
}
EXPOSE_INTERFACE( CPlayerTeamMatchProxy, IMaterialProxy, "PlayerTeamMatch" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Returns the player view direction
//-----------------------------------------------------------------------------
class CPlayerViewProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
float m_Factor;
};
bool CPlayerViewProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
m_Factor = pKeyValues->GetFloat( "scale", 2 );
return true;
}
void CPlayerViewProxy::OnBind( void *pC_BaseEntity )
{
if (!pC_BaseEntity)
return;
// Find the view angle between the player and this entity....
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer();
if (!pPlayer)
return;
Vector delta;
VectorSubtract( pEntity->WorldSpaceCenter(), pPlayer->WorldSpaceCenter(), delta );
VectorNormalize( delta );
Vector forward;
AngleVectors( pPlayer->GetAbsAngles(), &forward );
Assert( m_pResult );
SetFloatResult( DotProduct( forward, delta ) * m_Factor );
if ( ToolsEnabled() )
{
ToolFramework_RecordMaterialParams( GetMaterial() );
}
}
EXPOSE_INTERFACE( CPlayerViewProxy, IMaterialProxy, "PlayerView" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Returns the player speed
//-----------------------------------------------------------------------------
class CPlayerSpeedProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
float m_Factor;
};
bool CPlayerSpeedProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
m_Factor = pKeyValues->GetFloat( "scale", 0.005 );
return true;
}
void CPlayerSpeedProxy::OnBind( void *pC_BaseEntity )
{
// Find the player speed....
C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer();
if (!pPlayer)
return;
Assert( m_pResult );
SetFloatResult( pPlayer->GetLocalVelocity().Length() * m_Factor );
if ( ToolsEnabled() )
{
ToolFramework_RecordMaterialParams( GetMaterial() );
}
}
EXPOSE_INTERFACE( CPlayerSpeedProxy, IMaterialProxy, "PlayerSpeed" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Returns the player position
//-----------------------------------------------------------------------------
class CPlayerPositionProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
float m_Factor;
};
bool CPlayerPositionProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
m_Factor = pKeyValues->GetFloat( "scale", 0.005 );
return true;
}
void CPlayerPositionProxy::OnBind( void *pC_BaseEntity )
{
// Find the player speed....
C_BaseEntity* pPlayer = C_BasePlayer::GetLocalPlayer();
if (!pPlayer)
return;
// This is actually a vector...
Assert( m_pResult );
Vector res;
VectorMultiply( pPlayer->WorldSpaceCenter(), m_Factor, res );
m_pResult->SetVecValue( res.Base(), 3 );
if ( ToolsEnabled() )
{
ToolFramework_RecordMaterialParams( GetMaterial() );
}
}
EXPOSE_INTERFACE( CPlayerPositionProxy, IMaterialProxy, "PlayerPosition" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Returns the entity speed
//-----------------------------------------------------------------------------
class CEntitySpeedProxy : public CResultProxy
{
public:
void OnBind( void *pC_BaseEntity );
};
void CEntitySpeedProxy::OnBind( void *pC_BaseEntity )
{
// Find the view angle between the player and this entity....
if (!pC_BaseEntity)
return;
// Find the view angle between the player and this entity....
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
Assert( m_pResult );
m_pResult->SetFloatValue( pEntity->GetLocalVelocity().Length() );
if ( ToolsEnabled() )
{
ToolFramework_RecordMaterialParams( GetMaterial() );
}
}
EXPOSE_INTERFACE( CEntitySpeedProxy, IMaterialProxy, "EntitySpeed" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Returns a random # from 0 - 1 specific to the entity it's applied to
//-----------------------------------------------------------------------------
class CEntityRandomProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Factor;
};
bool CEntityRandomProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1 ))
return false;
return true;
}
void CEntityRandomProxy::OnBind( void *pC_BaseEntity )
{
// Find the view angle between the player and this entity....
if (!pC_BaseEntity)
return;
// Find the view angle between the player and this entity....
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
Assert( m_pResult );
m_pResult->SetFloatValue( pEntity->ProxyRandomValue() * m_Factor.GetFloat() );
if ( ToolsEnabled() )
{
ToolFramework_RecordMaterialParams( GetMaterial() );
}
}
EXPOSE_INTERFACE( CEntityRandomProxy, IMaterialProxy, "EntityRandom" IMATERIAL_PROXY_INTERFACE_VERSION );
#include "utlrbtree.h"
//-----------------------------------------------------------------------------
// Returns the player speed
//-----------------------------------------------------------------------------
class CPlayerLogoProxy : public IMaterialProxy
{
public:
CPlayerLogoProxy();
virtual bool Init( IMaterial* pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release()
{
if ( m_pDefaultTexture )
{
m_pDefaultTexture->DecrementReferenceCount();
}
int c = m_Logos.Count();
int i;
for ( i = 0; i < c ; i++ )
{
PlayerLogo *logo = &m_Logos[ i ];
if( logo->texture )
{
logo->texture->DecrementReferenceCount();
}
}
m_Logos.RemoveAll();
}
virtual IMaterial *GetMaterial();
protected:
virtual void OnLogoBindInternal( int playerindex );
private:
IMaterialVar *m_pBaseTextureVar;
struct PlayerLogo
{
unsigned int crc;
ITexture *texture;
};
static bool LogoLessFunc( const PlayerLogo& src1, const PlayerLogo& src2 )
{
return src1.crc < src2.crc;
}
CUtlRBTree< PlayerLogo > m_Logos;
ITexture *m_pDefaultTexture;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CPlayerLogoProxy::CPlayerLogoProxy()
: m_Logos( 0, 0, LogoLessFunc )
{
m_pDefaultTexture = NULL;
}
#define DEFAULT_DECAL_NAME "decals/YBlood1"
bool CPlayerLogoProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
bool found = false;
m_pBaseTextureVar = pMaterial->FindVar( "$basetexture", &found );
if ( !found )
return false;
m_pDefaultTexture = materials->FindTexture( DEFAULT_DECAL_NAME, TEXTURE_GROUP_DECAL );
if ( IsErrorTexture( m_pDefaultTexture ) )
return false;
m_pDefaultTexture->IncrementReferenceCount();
return true;
}
void CPlayerLogoProxy::OnBind( void *pC_BaseEntity )
{
// Decal's are bound with the player index as the passed in paramter
2022-02-23 19:50:30 +08:00
int playerindex = (intp)pC_BaseEntity;
2020-04-23 00:56:21 +08:00
if ( playerindex <= 0 )
return;
if ( playerindex > gpGlobals->maxClients )
return;
if ( !m_pBaseTextureVar )
return;
OnLogoBindInternal( playerindex );
}
void CPlayerLogoProxy::OnLogoBindInternal( int playerindex )
{
// Find player
player_info_t info;
engine->GetPlayerInfo( playerindex, &info );
if ( !info.customFiles[0] )
return;
// So we don't trash this too hard
ITexture *texture = NULL;
PlayerLogo logo;
logo.crc = (unsigned int)info.customFiles[0];
logo.texture = NULL;
int lookup = m_Logos.Find( logo );
if ( lookup == m_Logos.InvalidIndex() )
{
char crcfilename[ 512 ];
char logohex[ 16 ];
Q_binarytohex( (byte *)&info.customFiles[0], sizeof( info.customFiles[0] ), logohex, sizeof( logohex ) );
Q_snprintf( crcfilename, sizeof( crcfilename ), "temp/%s", logohex );
texture = materials->FindTexture( crcfilename, TEXTURE_GROUP_DECAL, false );
if ( texture )
{
// Make sure it doesn't get flushed
texture->IncrementReferenceCount();
logo.texture = texture;
}
m_Logos.Insert( logo );
}
else
{
texture = m_Logos[ lookup ].texture;
}
if ( texture )
{
m_pBaseTextureVar->SetTextureValue( texture );
}
else if ( m_pDefaultTexture )
{
m_pBaseTextureVar->SetTextureValue( m_pDefaultTexture );
}
if ( ToolsEnabled() )
{
ToolFramework_RecordMaterialParams( GetMaterial() );
}
}
IMaterial *CPlayerLogoProxy::GetMaterial()
{
return m_pBaseTextureVar->GetOwningMaterial();
}
EXPOSE_INTERFACE( CPlayerLogoProxy, IMaterialProxy, "PlayerLogo" IMATERIAL_PROXY_INTERFACE_VERSION );
/* @note Tom Bui: This is here for reference, but we don't want people to use it!
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CPlayerLogoOnModelProxy : public CPlayerLogoProxy
{
public:
virtual void OnBind( void *pC_BaseEntity );
};
void CPlayerLogoOnModelProxy::OnBind( void *pC_BaseEntity )
{
if ( pC_BaseEntity )
{
IClientRenderable *pRend = (IClientRenderable *)pC_BaseEntity;
C_BaseEntity *pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if ( pEntity )
{
if ( !pEntity->IsPlayer() )
{
pEntity = pEntity->GetRootMoveParent();
}
if ( pEntity && pEntity->IsPlayer() )
{
int iPlayerIndex = pEntity->entindex();
OnLogoBindInternal( iPlayerIndex );
}
}
}
}
EXPOSE_INTERFACE( CPlayerLogoOnModelProxy, IMaterialProxy, "PlayerLogoOnModel" IMATERIAL_PROXY_INTERFACE_VERSION );
*/