437 lines
11 KiB
C++
437 lines
11 KiB
C++
//========= Copyright © 1996-2005, 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 "imaterialproxydict.h"
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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 );
|
|
}
|
|
|
|
EXPOSE_MATERIAL_PROXY( CPlayerProximityProxy, PlayerProximity );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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 );
|
|
}
|
|
|
|
EXPOSE_MATERIAL_PROXY( CPlayerTeamMatchProxy, PlayerTeamMatch );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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 );
|
|
}
|
|
|
|
EXPOSE_MATERIAL_PROXY( CPlayerViewProxy, PlayerView );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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 );
|
|
}
|
|
|
|
EXPOSE_MATERIAL_PROXY( CPlayerSpeedProxy, PlayerSpeed );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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 );
|
|
}
|
|
|
|
EXPOSE_MATERIAL_PROXY( CPlayerPositionProxy, PlayerPosition );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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() );
|
|
}
|
|
|
|
EXPOSE_MATERIAL_PROXY( CEntitySpeedProxy, EntitySpeed );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// 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() );
|
|
}
|
|
|
|
EXPOSE_MATERIAL_PROXY( CEntityRandomProxy, EntityRandom );
|
|
|
|
#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();
|
|
|
|
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
|
|
int playerindex = (int)pC_BaseEntity;
|
|
|
|
if ( playerindex <= 0 )
|
|
return;
|
|
|
|
if ( playerindex > gpGlobals->maxClients )
|
|
return;
|
|
|
|
if ( !m_pBaseTextureVar )
|
|
return;
|
|
|
|
// 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 );
|
|
}
|
|
}
|
|
|
|
IMaterial *CPlayerLogoProxy::GetMaterial()
|
|
{
|
|
return m_pBaseTextureVar->GetOwningMaterial();
|
|
}
|
|
|
|
EXPOSE_MATERIAL_PROXY( CPlayerLogoProxy, PlayerLogo ); |