This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@@ -0,0 +1,54 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Acts exactly like "AnimatedTexture", but ONLY if the texture
// it's working on matches the desired texture to work on.
//
// This assumes that some other proxy will be switching out the textures.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/imaterialproxy.h"
#include "materialsystem/imaterialvar.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/itexture.h"
#include "baseanimatedtextureproxy.h"
#include "utlstring.h"
#include <keyvalues.h>
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimateSpecificTexture : public CBaseAnimatedTextureProxy
{
private:
CUtlString m_OnlyAnimateOnTexture;
public:
virtual float GetAnimationStartTime( void* pBaseEntity ) { return 0; }
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
};
bool CAnimateSpecificTexture::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pszAnimateOnTexture = pKeyValues->GetString( "onlyAnimateOnTexture" );
if( !pszAnimateOnTexture )
return false;
m_OnlyAnimateOnTexture.Set( pszAnimateOnTexture );
return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
}
void CAnimateSpecificTexture::OnBind( void *pC_BaseEntity )
{
if( FStrEq( m_AnimatedTextureVar->GetTextureValue()->GetName(), m_OnlyAnimateOnTexture ) )
{
CBaseAnimatedTextureProxy::OnBind( pC_BaseEntity );
}
//else do nothing
}
EXPOSE_MATERIAL_PROXY( CAnimateSpecificTexture, AnimateSpecificTexture );

View File

@@ -0,0 +1,785 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Material Modify control entity.
//
//=============================================================================//
#include "cbase.h"
#include "proxyentity.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "materialsystem/itexture.h"
#include "iviewrender.h"
#include "texture_group_names.h"
#include "baseanimatedtextureproxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define MATERIAL_MODIFY_STRING_SIZE 255
#define MATERIAL_MODIFY_ANIMATION_UNSET -1
// Must match MaterialModifyControl.cpp
enum MaterialModifyMode_t
{
MATERIAL_MODIFY_MODE_NONE = 0,
MATERIAL_MODIFY_MODE_SETVAR = 1,
MATERIAL_MODIFY_MODE_ANIM_SEQUENCE = 2,
MATERIAL_MODIFY_MODE_FLOAT_LERP = 3,
};
ConVar debug_materialmodifycontrol_client( "debug_materialmodifycontrol_client", "0" );
struct materialanimcommands_t
{
int iFrameStart;
int iFrameEnd;
bool bWrap;
float flFrameRate;
};
struct materialfloatlerpcommands_t
{
int flStartValue;
int flEndValue;
float flTransitionTime;
};
//------------------------------------------------------------------------------
// FIXME: This really should inherit from something more lightweight
//------------------------------------------------------------------------------
class C_MaterialModifyControl : public C_BaseEntity
{
public:
DECLARE_CLASS( C_MaterialModifyControl, C_BaseEntity );
C_MaterialModifyControl();
void OnPreDataChanged( DataUpdateType_t updateType );
void OnDataChanged( DataUpdateType_t updateType );
bool ShouldDraw();
IMaterial *GetMaterial( void ) { return m_pMaterial; }
const char *GetMaterialVariableName( void ) { return m_szMaterialVar; }
const char *GetMaterialVariableValue( void ) { return m_szMaterialVarValue; }
DECLARE_CLIENTCLASS();
// Animated texture and Float Lerp usage
bool HasNewAnimationCommands( void ) { return m_bHasNewAnimationCommands; }
void ClearAnimationCommands( void ) { m_bHasNewAnimationCommands = false; }
// Animated texture usage
void GetAnimationCommands( materialanimcommands_t *pCommands );
// FloatLerp usage
void GetFloatLerpCommands( materialfloatlerpcommands_t *pCommands );
void SetAnimationStartTime( float flTime )
{
m_flAnimationStartTime = flTime;
}
float GetAnimationStartTime( void ) const
{
return m_flAnimationStartTime;
}
MaterialModifyMode_t GetModifyMode( void ) const
{
return ( MaterialModifyMode_t)m_nModifyMode;
}
private:
char m_szMaterialName[MATERIAL_MODIFY_STRING_SIZE];
char m_szMaterialVar[MATERIAL_MODIFY_STRING_SIZE];
char m_szMaterialVarValue[MATERIAL_MODIFY_STRING_SIZE];
IMaterial *m_pMaterial;
bool m_bHasNewAnimationCommands;
// Animation commands from the server
int m_iFrameStart;
int m_iFrameEnd;
bool m_bWrap;
float m_flFramerate;
bool m_bNewAnimCommandsSemaphore;
bool m_bOldAnimCommandsSemaphore;
// Float lerp commands from the server
float m_flFloatLerpStartValue;
float m_flFloatLerpEndValue;
float m_flFloatLerpTransitionTime;
bool m_bFloatLerpWrap;
float m_flAnimationStartTime;
int m_nModifyMode;
};
IMPLEMENT_CLIENTCLASS_DT(C_MaterialModifyControl, DT_MaterialModifyControl, CMaterialModifyControl)
RecvPropString( RECVINFO( m_szMaterialName ) ),
RecvPropString( RECVINFO( m_szMaterialVar ) ),
RecvPropString( RECVINFO( m_szMaterialVarValue ) ),
RecvPropInt( RECVINFO(m_iFrameStart) ),
RecvPropInt( RECVINFO(m_iFrameEnd) ),
RecvPropInt( RECVINFO(m_bWrap) ),
RecvPropFloat( RECVINFO(m_flFramerate) ),
RecvPropInt( RECVINFO(m_bNewAnimCommandsSemaphore) ),
RecvPropFloat( RECVINFO(m_flFloatLerpStartValue) ),
RecvPropFloat( RECVINFO(m_flFloatLerpEndValue) ),
RecvPropFloat( RECVINFO(m_flFloatLerpTransitionTime) ),
RecvPropInt( RECVINFO(m_bFloatLerpWrap) ),
RecvPropInt( RECVINFO(m_nModifyMode) ),
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
C_MaterialModifyControl::C_MaterialModifyControl()
{
m_pMaterial = NULL;
m_bOldAnimCommandsSemaphore = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_MaterialModifyControl::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_bOldAnimCommandsSemaphore = m_bNewAnimCommandsSemaphore;
}
//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void C_MaterialModifyControl::OnDataChanged( DataUpdateType_t updateType )
{
if( updateType == DATA_UPDATE_CREATED )
{
m_pMaterial = materials->FindMaterial( m_szMaterialName, TEXTURE_GROUP_OTHER );
// Clear out our variables
m_bHasNewAnimationCommands = true;
}
// Detect changes in the anim commands
if ( m_bNewAnimCommandsSemaphore != m_bOldAnimCommandsSemaphore )
{
m_bHasNewAnimationCommands = true;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_MaterialModifyControl::GetAnimationCommands( materialanimcommands_t *pCommands )
{
pCommands->iFrameStart = m_iFrameStart;
pCommands->iFrameEnd = m_iFrameEnd;
pCommands->bWrap = m_bWrap;
pCommands->flFrameRate = m_flFramerate;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_MaterialModifyControl::GetFloatLerpCommands( materialfloatlerpcommands_t *pCommands )
{
pCommands->flStartValue = m_flFloatLerpStartValue;
pCommands->flEndValue = m_flFloatLerpEndValue;
pCommands->flTransitionTime = m_flFloatLerpTransitionTime;
}
//------------------------------------------------------------------------------
// Purpose: We don't draw.
//------------------------------------------------------------------------------
bool C_MaterialModifyControl::ShouldDraw()
{
return false;
}
//=============================================================================
//
// THE MATERIALMODIFYPROXY ITSELF
//
class CMaterialModifyProxy : public CBaseAnimatedTextureProxy
{
public:
CMaterialModifyProxy();
virtual ~CMaterialModifyProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pEntity );
virtual IMaterial *GetMaterial();
private:
void OnBindSetVar( C_MaterialModifyControl *pControl );
void OnBindAnimatedTexture( C_MaterialModifyControl *pControl );
void OnBindFloatLerp( C_MaterialModifyControl *pControl );
float GetAnimationStartTime( void* pArg );
void AnimationWrapped( void* pArg );
IMaterial *m_pMaterial;
// texture animation stuff
int m_iFrameStart;
int m_iFrameEnd;
bool m_bReachedEnd;
bool m_bCustomWrap;
float m_flCustomFramerate;
// float lerp stuff
IMaterialVar *m_pMaterialVar;
int m_flStartValue;
int m_flEndValue;
float m_flStartTime;
float m_flTransitionTime;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CMaterialModifyProxy::CMaterialModifyProxy()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CMaterialModifyProxy::~CMaterialModifyProxy()
{
}
bool CMaterialModifyProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
// set var stuff
m_pMaterial = pMaterial;
// float lerp stuff
m_flStartValue = MATERIAL_MODIFY_ANIMATION_UNSET;
m_flEndValue = MATERIAL_MODIFY_ANIMATION_UNSET;
// animated stuff
// m_pMaterial = pMaterial;
// m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET;
// m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET;
// m_bReachedEnd = false;
// return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
return true;
}
void CMaterialModifyProxy::OnBind( void *pEntity )
{
// Get the modified material vars from the entity input
IClientRenderable *pRend = (IClientRenderable *)pEntity;
if ( pRend )
{
C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if ( pBaseEntity )
{
if( debug_materialmodifycontrol_client.GetBool() )
{
// DevMsg( 1, "%s\n", pBaseEntity->GetDebugName() );
}
int numChildren = 0;
bool gotOne = false;
for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
{
numChildren++;
C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild );
if ( !pControl )
continue;
if( debug_materialmodifycontrol_client.GetBool() )
{
// DevMsg( 1, "pControl: 0x%p\n", pControl );
}
switch( pControl->GetModifyMode() )
{
case MATERIAL_MODIFY_MODE_NONE:
break;
case MATERIAL_MODIFY_MODE_SETVAR:
gotOne = true;
OnBindSetVar( pControl );
break;
case MATERIAL_MODIFY_MODE_ANIM_SEQUENCE:
OnBindAnimatedTexture( pControl );
break;
case MATERIAL_MODIFY_MODE_FLOAT_LERP:
OnBindFloatLerp( pControl );
break;
default:
Assert( 0 );
break;
}
}
if( gotOne )
{
// DevMsg( 1, "numChildren: %d\n", numChildren );
}
}
}
}
IMaterial *CMaterialModifyProxy::GetMaterial()
{
return m_pMaterial;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::OnBindSetVar( C_MaterialModifyControl *pControl )
{
IMaterial *pMaterial = pControl->GetMaterial();
if( !pMaterial )
{
Assert( 0 );
return;
}
if ( pMaterial != m_pMaterial )
{
// Warning( "\t%s!=%s\n", pMaterial->GetName(), m_pMaterial->GetName() );
return;
}
bool bFound;
IMaterialVar *pMaterialVar = pMaterial->FindVar( pControl->GetMaterialVariableName(), &bFound, false );
if ( !bFound )
return;
if( Q_strcmp( pControl->GetMaterialVariableValue(), "" ) )
{
// const char *pMaterialName = m_pMaterial->GetName();
// const char *pMaterialVarName = pMaterialVar->GetName();
// const char *pMaterialVarValue = pControl->GetMaterialVariableValue();
// if( debug_materialmodifycontrol_client.GetBool()
// && Q_stristr( m_pMaterial->GetName(), "faceandhair" )
// && Q_stristr( pMaterialVar->GetName(), "self" )
// )
// {
// static int count = 0;
// DevMsg( 1, "CMaterialModifyProxy::OnBindSetVar \"%s\" %s=%s %d pControl=0x%p\n",
// m_pMaterial->GetName(), pMaterialVar->GetName(), pControl->GetMaterialVariableValue(), count++, pControl );
// }
pMaterialVar->SetValueAutodetectType( pControl->GetMaterialVariableValue() );
}
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::OnBindAnimatedTexture( C_MaterialModifyControl *pControl )
{
assert ( m_AnimatedTextureVar );
if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
return;
ITexture *pTexture;
pTexture = m_AnimatedTextureVar->GetTextureValue();
if ( !pControl )
return;
if ( pControl->HasNewAnimationCommands() )
{
// Read the data from the modify entity
materialanimcommands_t sCommands;
pControl->GetAnimationCommands( &sCommands );
m_iFrameStart = sCommands.iFrameStart;
m_iFrameEnd = sCommands.iFrameEnd;
m_bCustomWrap = sCommands.bWrap;
m_flCustomFramerate = sCommands.flFrameRate;
m_bReachedEnd = false;
m_flStartTime = gpGlobals->curtime;
pControl->ClearAnimationCommands();
}
// Init all the vars based on whether we're using the base material settings,
// or the custom ones from the entity input.
int numFrames;
bool bWrapAnimation;
float flFrameRate;
int iLastFrame;
// Do we have a custom frame section from the server?
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET )
{
m_iFrameEnd = pTexture->GetNumAnimationFrames();
}
numFrames = (m_iFrameEnd - m_iFrameStart) + 1;
bWrapAnimation = m_bCustomWrap;
flFrameRate = m_flCustomFramerate;
iLastFrame = (m_iFrameEnd - 1);
}
else
{
numFrames = pTexture->GetNumAnimationFrames();
bWrapAnimation = m_WrapAnimation;
flFrameRate = m_FrameRate;
iLastFrame = (numFrames - 1);
}
// Have we already reached the end? If so, stay there.
if ( m_bReachedEnd && !bWrapAnimation )
{
m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame );
return;
}
// NOTE: Must not use relative time based methods here
// because the bind proxy can be called many times per frame.
// Prevent multiple Wrap callbacks to be sent for no wrap mode
float startTime;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
startTime = m_flStartTime;
}
else
{
startTime = GetAnimationStartTime(pControl);
}
float deltaTime = gpGlobals->curtime - startTime;
float prevTime = deltaTime - gpGlobals->frametime;
// Clamp..
if (deltaTime < 0.0f)
deltaTime = 0.0f;
if (prevTime < 0.0f)
prevTime = 0.0f;
float frame = flFrameRate * deltaTime;
float prevFrame = flFrameRate * prevTime;
int intFrame = ((int)frame) % numFrames;
int intPrevFrame = ((int)prevFrame) % numFrames;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
intFrame += m_iFrameStart;
intPrevFrame += m_iFrameStart;
}
// Report wrap situation...
if (intPrevFrame > intFrame)
{
m_bReachedEnd = true;
if (bWrapAnimation)
{
AnimationWrapped( pControl );
}
else
{
// Only sent the wrapped message once.
// when we're in non-wrapping mode
if (prevFrame < numFrames)
AnimationWrapped( pControl );
intFrame = numFrames - 1;
}
}
m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CMaterialModifyProxy::GetAnimationStartTime( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return 0.0f;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
return pEntity->GetTextureAnimationStartTime();
}
return 0.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::AnimationWrapped( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
pEntity->TextureAnimationWrapped();
}
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::OnBindFloatLerp( C_MaterialModifyControl *pControl )
{
if ( !pControl )
return;
if ( pControl->HasNewAnimationCommands() )
{
pControl->SetAnimationStartTime( gpGlobals->curtime );
pControl->ClearAnimationCommands();
}
// Read the data from the modify entity
materialfloatlerpcommands_t sCommands;
pControl->GetFloatLerpCommands( &sCommands );
m_flStartValue = sCommands.flStartValue;
m_flEndValue = sCommands.flEndValue;
m_flTransitionTime = sCommands.flTransitionTime;
m_flStartTime = pControl->GetAnimationStartTime();
bool bFound;
m_pMaterialVar = m_pMaterial->FindVar( pControl->GetMaterialVariableName(), &bFound, false );
if( bFound )
{
float currentValue;
if( m_flTransitionTime > 0.0f )
{
currentValue = m_flStartValue + ( m_flEndValue - m_flStartValue ) * clamp( ( ( gpGlobals->curtime - m_flStartTime ) / m_flTransitionTime ), 0.0f, 1.0f );
}
else
{
currentValue = m_flEndValue;
}
if( debug_materialmodifycontrol_client.GetBool() && Q_stristr( m_pMaterial->GetName(), "faceandhair" ) && Q_stristr( m_pMaterialVar->GetName(), "warp" ) )
{
static int count = 0;
DevMsg( 1, "CMaterialFloatLerpProxy::OnBind \"%s\" %s=%f %d\n", m_pMaterial->GetName(), m_pMaterialVar->GetName(), currentValue, count++ );
}
m_pMaterialVar->SetFloatValue( currentValue );
}
}
//=============================================================================
//
// MATERIALMODIFYANIMATED PROXY
//
class CMaterialModifyAnimatedProxy : public CBaseAnimatedTextureProxy
{
public:
CMaterialModifyAnimatedProxy() {};
virtual ~CMaterialModifyAnimatedProxy() {};
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pEntity );
virtual float GetAnimationStartTime( void* pBaseEntity );
virtual void AnimationWrapped( void* pC_BaseEntity );
private:
IMaterial *m_pMaterial;
int m_iFrameStart;
int m_iFrameEnd;
bool m_bReachedEnd;
float m_flStartTime;
bool m_bCustomWrap;
float m_flCustomFramerate;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CMaterialModifyAnimatedProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
m_pMaterial = pMaterial;
m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET;
m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET;
m_bReachedEnd = false;
return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CMaterialModifyAnimatedProxy::OnBind( void *pEntity )
{
assert ( m_AnimatedTextureVar );
if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
return;
ITexture *pTexture;
pTexture = m_AnimatedTextureVar->GetTextureValue();
// Get the modified material vars from the entity input
IClientRenderable *pRend = (IClientRenderable *)pEntity;
if ( pRend )
{
C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if ( pBaseEntity )
{
for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
{
C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild );
if ( !pControl )
continue;
if ( !pControl->HasNewAnimationCommands() )
continue;
// Read the data from the modify entity
materialanimcommands_t sCommands;
pControl->GetAnimationCommands( &sCommands );
m_iFrameStart = sCommands.iFrameStart;
m_iFrameEnd = sCommands.iFrameEnd;
m_bCustomWrap = sCommands.bWrap;
m_flCustomFramerate = sCommands.flFrameRate;
m_bReachedEnd = false;
m_flStartTime = gpGlobals->curtime;
pControl->ClearAnimationCommands();
}
}
}
// Init all the vars based on whether we're using the base material settings,
// or the custom ones from the entity input.
int numFrames;
bool bWrapAnimation;
float flFrameRate;
int iLastFrame;
// Do we have a custom frame section from the server?
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET )
{
m_iFrameEnd = pTexture->GetNumAnimationFrames();
}
numFrames = (m_iFrameEnd - m_iFrameStart) + 1;
bWrapAnimation = m_bCustomWrap;
flFrameRate = m_flCustomFramerate;
iLastFrame = (m_iFrameEnd - 1);
}
else
{
numFrames = pTexture->GetNumAnimationFrames();
bWrapAnimation = m_WrapAnimation;
flFrameRate = m_FrameRate;
iLastFrame = (numFrames - 1);
}
// Have we already reached the end? If so, stay there.
if ( m_bReachedEnd && !bWrapAnimation )
{
m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame );
return;
}
// NOTE: Must not use relative time based methods here
// because the bind proxy can be called many times per frame.
// Prevent multiple Wrap callbacks to be sent for no wrap mode
float startTime;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
startTime = m_flStartTime;
}
else
{
startTime = GetAnimationStartTime(pEntity);
}
float deltaTime = gpGlobals->curtime - startTime;
float prevTime = deltaTime - gpGlobals->frametime;
// Clamp..
if (deltaTime < 0.0f)
deltaTime = 0.0f;
if (prevTime < 0.0f)
prevTime = 0.0f;
float frame = flFrameRate * deltaTime;
float prevFrame = flFrameRate * prevTime;
int intFrame = ((int)frame) % numFrames;
int intPrevFrame = ((int)prevFrame) % numFrames;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
intFrame += m_iFrameStart;
intPrevFrame += m_iFrameStart;
}
// Report wrap situation...
if (intPrevFrame > intFrame)
{
m_bReachedEnd = true;
if (bWrapAnimation)
{
AnimationWrapped( pEntity );
}
else
{
// Only sent the wrapped message once.
// when we're in non-wrapping mode
if (prevFrame < numFrames)
AnimationWrapped( pEntity );
intFrame = numFrames - 1;
}
}
m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CMaterialModifyAnimatedProxy::GetAnimationStartTime( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return 0.0f;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
return pEntity->GetTextureAnimationStartTime();
}
return 0.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMaterialModifyAnimatedProxy::AnimationWrapped( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
pEntity->TextureAnimationWrapped();
}
}
EXPOSE_MATERIAL_PROXY( CMaterialModifyProxy, MaterialModify );
EXPOSE_MATERIAL_PROXY( CMaterialModifyAnimatedProxy, MaterialModifyAnimated );

View File

@@ -0,0 +1,60 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Water LOD control entity.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "iviewrender.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//------------------------------------------------------------------------------
// FIXME: This really should inherit from something more lightweight
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Purpose : Water LOD control entity
//------------------------------------------------------------------------------
class C_WaterLODControl : public C_BaseEntity
{
public:
DECLARE_CLASS( C_WaterLODControl, C_BaseEntity );
DECLARE_CLIENTCLASS();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
private:
float m_flCheapWaterStartDistance;
float m_flCheapWaterEndDistance;
};
IMPLEMENT_CLIENTCLASS_DT(C_WaterLODControl, DT_WaterLODControl, CWaterLODControl)
RecvPropFloat(RECVINFO(m_flCheapWaterStartDistance)),
RecvPropFloat(RECVINFO(m_flCheapWaterEndDistance)),
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void C_WaterLODControl::OnDataChanged(DataUpdateType_t updateType)
{
view->SetCheapWaterStartDistance( m_flCheapWaterStartDistance );
view->SetCheapWaterEndDistance( m_flCheapWaterEndDistance );
}
//------------------------------------------------------------------------------
// We don't draw...
//------------------------------------------------------------------------------
bool C_WaterLODControl::ShouldDraw()
{
return false;
}

View File

@@ -0,0 +1,231 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Utility code.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "IEffects.h"
#include "fx.h"
#include "c_te_legacytempents.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Client-server neutral effects interface
//-----------------------------------------------------------------------------
class CEffectsClient : public IEffects
{
public:
CEffectsClient();
virtual ~CEffectsClient();
// Members of the IEffect interface
virtual void Beam( const Vector &Start, const Vector &End, int nModelIndex,
int nHaloIndex, unsigned char frameStart, unsigned char frameRate,
float flLife, unsigned char width, unsigned char endWidth, unsigned char fadeLength,
unsigned char noise, unsigned char red, unsigned char green,
unsigned char blue, unsigned char brightness, unsigned char speed);
virtual void Smoke( const Vector &origin, int modelIndex, float scale, float framerate );
virtual void Sparks( const Vector &position, int nMagnitude = 1, int nTrailLength = 1, const Vector *pvecDir = NULL );
virtual void Dust( const Vector &pos, const Vector &dir, float size, float speed );
virtual void MuzzleFlash( const Vector &origin, const QAngle &angles, float fScale, int type );
virtual void MetalSparks( const Vector &position, const Vector &direction );
virtual void EnergySplash( const Vector &position, const Vector &direction, bool bExplosive = false );
virtual void Ricochet( const Vector &position, const Vector &direction );
// FIXME: Should these methods remain in this interface? Or go in some
// other client-server neutral interface?
virtual float Time();
virtual bool IsServer();
virtual void SuppressEffectsSounds( bool bSuppress );
private:
//-----------------------------------------------------------------------------
// Purpose: Returning true means don't even call TE func
// Input : filter -
// *suppress_host -
// Output : static bool
//-----------------------------------------------------------------------------
bool SuppressTE( C_RecipientFilter& filter )
{
if ( !CanPredict() )
return true;
if ( !filter.GetRecipientCount() )
{
// Suppress it
return true;
}
// There's at least one recipient
return false;
}
bool m_bSuppressSound;
};
//-----------------------------------------------------------------------------
// Client-server neutral effects interface accessor
//-----------------------------------------------------------------------------
static CEffectsClient s_EffectClient;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CEffectsClient, IEffects, IEFFECTS_INTERFACE_VERSION, s_EffectClient);
IEffects *g_pEffects = &s_EffectClient;
ConVar r_decals( "r_decals", "2048" );
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CEffectsClient::CEffectsClient()
{
m_bSuppressSound = false;
}
CEffectsClient::~CEffectsClient()
{
}
//-----------------------------------------------------------------------------
// Suppress sound on effects
//-----------------------------------------------------------------------------
void CEffectsClient::SuppressEffectsSounds( bool bSuppress )
{
m_bSuppressSound = bSuppress;
}
//-----------------------------------------------------------------------------
// Generates a beam
//-----------------------------------------------------------------------------
void CEffectsClient::Beam( const Vector &vecStartPoint, const Vector &vecEndPoint,
int nModelIndex, int nHaloIndex, unsigned char frameStart, unsigned char nFrameRate,
float flLife, unsigned char nWidth, unsigned char nEndWidth, unsigned char nFadeLength,
unsigned char noise, unsigned char r, unsigned char g,
unsigned char b, unsigned char brightness, unsigned char nSpeed)
{
Assert(0);
// CBroadcastRecipientFilter filter;
// if ( !SuppressTE( filter ) )
// {
// beams->CreateBeamPoints( vecStartPoint, vecEndPoint, nModelIndex, nHaloIndex,
// m_fHaloScale,
// flLife, 0.1 * nWidth, 0.1 * nEndWidth, nFadeLength, 0.01 * nAmplitude, a, 0.1 * nSpeed,
// m_nStartFrame, 0.1 * nFrameRate, r, g, b );
// }
}
//-----------------------------------------------------------------------------
// Generates various tempent effects
//-----------------------------------------------------------------------------
void CEffectsClient::Smoke( const Vector &vecOrigin, int modelIndex, float scale, float framerate )
{
CPVSFilter filter( vecOrigin );
if ( !SuppressTE( filter ) )
{
int iColor = random->RandomInt(20,35);
color32 color;
color.r = iColor;
color.g = iColor;
color.b = iColor;
color.a = iColor;
QAngle angles;
VectorAngles( Vector(0,0,1), angles );
FX_Smoke( vecOrigin, angles, scale * 0.1f, 4, (unsigned char *)&color, 255 );
}
}
void CEffectsClient::Sparks( const Vector &position, int nMagnitude, int nTrailLength, const Vector *pVecDir )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_ElectricSpark( position, nMagnitude, nTrailLength, pVecDir );
}
}
void CEffectsClient::Dust( const Vector &pos, const Vector &dir, float size, float speed )
{
CPVSFilter filter( pos );
if ( !SuppressTE( filter ) )
{
FX_Dust( pos, dir, size, speed );
}
}
void CEffectsClient::MuzzleFlash( const Vector &vecOrigin, const QAngle &vecAngles, float flScale, int iType )
{
CPVSFilter filter( vecOrigin );
if ( !SuppressTE( filter ) )
{
switch( iType )
{
case MUZZLEFLASH_TYPE_DEFAULT:
FX_MuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE );
break;
case MUZZLEFLASH_TYPE_GUNSHIP:
FX_GunshipMuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE );
break;
case MUZZLEFLASH_TYPE_STRIDER:
FX_StriderMuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE );
break;
default:
Msg("No case for Muzzleflash type: %d\n", iType );
break;
}
}
}
void CEffectsClient::MetalSparks( const Vector &position, const Vector &direction )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_MetalSpark( position, direction, direction );
}
}
void CEffectsClient::EnergySplash( const Vector &position, const Vector &direction, bool bExplosive )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_EnergySplash( position, direction, bExplosive );
}
}
void CEffectsClient::Ricochet( const Vector &position, const Vector &direction )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_MetalSpark( position, direction, direction );
if ( !m_bSuppressSound )
{
FX_RicochetSound( position );
}
}
}
// FIXME: Should these methods remain in this interface? Or go in some
// other client-server neutral interface?
float CEffectsClient::Time()
{
return gpGlobals->curtime;
}
bool CEffectsClient::IsServer()
{
return false;
}

View File

@@ -0,0 +1,56 @@
//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "functionproxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Returns the player health (from 0 to 1)
//-----------------------------------------------------------------------------
class CProxyIsNPC : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Factor;
};
bool CProxyIsNPC::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 CProxyIsNPC::OnBind( void *pC_BaseEntity )
{
if ( !pC_BaseEntity )
return;
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
if ( pEntity && pEntity->IsNPC() )
{
SetFloatResult( m_Factor.GetFloat() );
}
else
{
SetFloatResult( 0.0f );
}
}
EXPOSE_MATERIAL_PROXY( CProxyIsNPC, IsNPC );

View File

@@ -0,0 +1,65 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
// $monitorTextureVar
class CMonitorMaterialProxy : public IMaterialProxy
{
public:
CMonitorMaterialProxy();
virtual ~CMonitorMaterialProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
private:
IMaterialVar *m_pMonitorTextureVar;
};
CMonitorMaterialProxy::CMonitorMaterialProxy()
{
m_pMonitorTextureVar = NULL;
}
CMonitorMaterialProxy::~CMonitorMaterialProxy()
{
m_pMonitorTextureVar = NULL;
}
bool CMonitorMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pMonitorTextureVarName = pKeyValues->getString( "$monitorTextureVar" );
if( !pMonitorTextureVarName )
return false;
bool foundVar;
m_pMonitorTextureVar = pMaterial->FindVar( pMonitorTextureVarName, &foundVar, false );
if( !foundVar )
{
m_pMonitorTextureVar = NULL;
return false;
}
return true;
}
void CMonitorMaterialProxy::OnBind( void *pC_BaseEntity )
{
if( !m_pMonitorTextureVar )
{
return;
}
}
EXPOSE_MATERIAL_PROXY( CMonitorMaterialProxy, Monitor );

101
game/client/NPSClient.h Normal file
View File

@@ -0,0 +1,101 @@
// *******************************************************************************
// *
// * Module Name:
// * NPSClient.h
// *
// * Abstract:
// * Header for NaturalPoint Simple Game Client API.
// *
// * Environment:
// * Microsoft Windows -- User mode
// *
// *******************************************************************************
#ifndef _NPSCLIENT_H_DEFINED_
#define _NPSCLIENT_H_DEFINED_
#pragma pack( push, npsclient_h ) // Save current pack value
#pragma pack(1)
#ifdef __cplusplus
extern "C"{
#endif
//////////////////
/// Typedefs /////////////////////////////////////////////////////////////////////
/////////////////
#ifndef _NPCLIENT_H_DEFINED_
// NPESULT values are returned from the Game Client API functions.
//
typedef enum tagNPResult
{
NP_OK = 0,
NP_ERR_DEVICE_NOT_PRESENT,
NP_ERR_UNSUPPORTED_OS,
NP_ERR_INVALID_ARG,
NP_ERR_DLL_NOT_FOUND,
NP_ERR_NO_DATA,
NP_ERR_INTERNAL_DATA,
NP_ERR_ALREADY_REGISTERED, // a window handle or game ID is already registered
NP_ERR_UNKNOWN_ID, // unknown game ID registered
NP_ERR_READ_ONLY, // parameter is read only
} NPRESULT;
typedef struct tagTrackIRData
{
unsigned short wNPStatus;
unsigned short wPFrameSignature;
unsigned long dwNPIOData;
float fNPRoll;
float fNPPitch;
float fNPYaw;
float fNPX;
float fNPY;
float fNPZ;
float fNPRawX;
float fNPRawY;
float fNPRawZ;
float fNPDeltaX;
float fNPDeltaY;
float fNPDeltaZ;
float fNPSmoothX;
float fNPSmoothY;
float fNPSmoothZ;
} TRACKIRDATA, *LPTRACKIRDATA;
#endif
typedef NPRESULT (__stdcall *PF_NPS_INIT)( HWND );
typedef NPRESULT (__stdcall *PF_NPS_SHUTDOWN)( void );
typedef NPRESULT (__stdcall *PF_NPS_GETDATA)( LPTRACKIRDATA );
//// Function Prototypes ///////////////////////////////////////////////
//
// Functions exported from game client API DLL ( note __stdcall calling convention
// is used for ease of interface to clients of differing implementations including
// C, C++, Pascal (Delphi) and VB. )
//
NPRESULT __stdcall NPS_Init( HWND hWnd );
NPRESULT __stdcall NPS_Shutdown( void );
NPRESULT __stdcall NPS_GetData( LPTRACKIRDATA pTID );
/////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#pragma pack( pop, npsclient_h ) // Ensure previous pack value is restored
#endif // #ifdef NPCLIENT_H_DEFINED_
//
// *** End of file: NPSClient.h ***
//

View File

@@ -0,0 +1,245 @@
// C_NextBot.cpp
// Client-side implementation of Next generation bot system
// Author: Michael Booth, April 2005
// Copyright (c) 2005 Turtle Rock Studios, Inc. - All Rights Reserved
#include "cbase.h"
#include "C_NextBot.h"
#include "debugoverlay_shared.h"
#include <bitbuf.h>
#include "viewrender.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#undef NextBot
ConVar NextBotShadowDist( "nb_shadow_dist", "400" );
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_NextBotCombatCharacter, DT_NextBot, NextBotCombatCharacter )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
C_NextBotCombatCharacter::C_NextBotCombatCharacter()
{
// Left4Dead have surfaces too steep for IK to work properly
m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK;
m_shadowType = SHADOWS_SIMPLE;
m_forcedShadowType = SHADOWS_NONE;
m_bForceShadowType = false;
TheClientNextBots().Register( this );
}
//-----------------------------------------------------------------------------
C_NextBotCombatCharacter::~C_NextBotCombatCharacter()
{
TheClientNextBots().UnRegister( this );
}
//-----------------------------------------------------------------------------
void C_NextBotCombatCharacter::Spawn( void )
{
BaseClass::Spawn();
}
//-----------------------------------------------------------------------------
void C_NextBotCombatCharacter::UpdateClientSideAnimation()
{
if (IsDormant())
{
return;
}
BaseClass::UpdateClientSideAnimation();
}
//--------------------------------------------------------------------------------------------------------
void C_NextBotCombatCharacter::UpdateShadowLOD( void )
{
ShadowType_t oldShadowType = m_shadowType;
if ( m_bForceShadowType )
{
m_shadowType = m_forcedShadowType;
}
else
{
#ifdef NEED_SPLITSCREEN_INTEGRATION
FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
{
C_BasePlayer *pl = C_BasePlayer::GetLocalPlayer(hh);
if ( pl )
{
Vector delta = GetAbsOrigin() - C_BasePlayer::GetLocalPlayer(hh)->GetAbsOrigin();
#else
{
if ( C_BasePlayer::GetLocalPlayer() )
{
Vector delta = GetAbsOrigin() - C_BasePlayer::GetLocalPlayer()->GetAbsOrigin();
#endif
if ( delta.IsLengthLessThan( NextBotShadowDist.GetFloat() ) )
{
m_shadowType = SHADOWS_RENDER_TO_TEXTURE_DYNAMIC;
}
else
{
m_shadowType = SHADOWS_SIMPLE;
}
}
else
{
m_shadowType = SHADOWS_SIMPLE;
}
}
}
if ( oldShadowType != m_shadowType )
{
DestroyShadow();
}
}
//--------------------------------------------------------------------------------------------------------
ShadowType_t C_NextBotCombatCharacter::ShadowCastType( void )
{
if ( !IsVisible() )
return SHADOWS_NONE;
if ( m_shadowTimer.IsElapsed() )
{
m_shadowTimer.Start( 0.15f );
UpdateShadowLOD();
}
return m_shadowType;
}
//--------------------------------------------------------------------------------------------------------
bool C_NextBotCombatCharacter::GetForcedShadowCastType( ShadowType_t* pForcedShadowType ) const
{
if ( pForcedShadowType )
{
*pForcedShadowType = m_forcedShadowType;
}
return m_bForceShadowType;
}
//--------------------------------------------------------------------------------------------------------
/**
* Singleton accessor.
* By returning a reference, we guarantee construction of the
* instance before its first use.
*/
C_NextBotManager &TheClientNextBots( void )
{
static C_NextBotManager manager;
return manager;
}
//--------------------------------------------------------------------------------------------------------
C_NextBotManager::C_NextBotManager( void )
{
}
//--------------------------------------------------------------------------------------------------------
C_NextBotManager::~C_NextBotManager()
{
}
//--------------------------------------------------------------------------------------------------------
void C_NextBotManager::Register( C_NextBotCombatCharacter *bot )
{
m_botList.AddToTail( bot );
}
//--------------------------------------------------------------------------------------------------------
void C_NextBotManager::UnRegister( C_NextBotCombatCharacter *bot )
{
m_botList.FindAndRemove( bot );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_NextBotManager::SetupInFrustumData( void )
{
#ifdef ENABLE_AFTER_INTEGRATION
// Done already this frame.
if ( IsInFrustumDataValid() )
return true;
// Can we use the view data yet?
if ( !FrustumCache()->IsValid() )
return false;
// Get the number of active bots.
int nBotCount = m_botList.Count();
// Reset.
for ( int iBot = 0; iBot < nBotCount; ++iBot )
{
// Get the current bot.
C_NextBotCombatCharacter *pBot = m_botList[iBot];
if ( !pBot )
continue;
pBot->InitFrustumData();
}
FOR_EACH_VALID_SPLITSCREEN_PLAYER( iSlot )
{
ACTIVE_SPLITSCREEN_PLAYER_GUARD( iSlot );
// Get the active local player.
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer )
continue;
for ( int iBot = 0; iBot < nBotCount; ++iBot )
{
// Get the current bot.
C_NextBotCombatCharacter *pBot = m_botList[iBot];
if ( !pBot )
continue;
// Are we in the view frustum?
Vector vecMin, vecMax;
pBot->CollisionProp()->WorldSpaceAABB( &vecMin, &vecMax );
bool bInFrustum = !FrustumCache()->m_Frustums[iSlot].CullBox( vecMin, vecMax );
if ( bInFrustum )
{
Vector vecSegment;
VectorSubtract( pBot->GetAbsOrigin(), pPlayer->GetAbsOrigin(), vecSegment );
float flDistance = vecSegment.LengthSqr();
if ( flDistance < pBot->GetInFrustumDistanceSqr() )
{
pBot->SetInFrustumDistanceSqr( flDistance );
}
pBot->SetInFrustum( true );
}
}
}
// Mark as setup this frame.
m_nInFrustumFrame = gpGlobals->framecount;
#endif
return true;
}
//--------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,134 @@
// C_NextBot.h
// Next generation bot system
// Author: Michael Booth, April 2005
// Copyright (c) 2005 Turtle Rock Studios, Inc. - All Rights Reserved
#ifndef _C_NEXT_BOT_H_
#define _C_NEXT_BOT_H_
#include "c_ai_basenpc.h"
//----------------------------------------------------------------------------------------------------------------
/**
* The interface holding IBody information
*/
class IBodyClient
{
public:
enum ActivityType
{
MOTION_CONTROLLED_XY = 0x0001, // XY position and orientation of the bot is driven by the animation.
MOTION_CONTROLLED_Z = 0x0002, // Z position of the bot is driven by the animation.
ACTIVITY_UNINTERRUPTIBLE= 0x0004, // activity can't be changed until animation finishes
ACTIVITY_TRANSITORY = 0x0008, // a short animation that takes over from the underlying animation momentarily, resuming it upon completion
ENTINDEX_PLAYBACK_RATE = 0x0010, // played back at different rates based on entindex
};
};
//--------------------------------------------------------------------------------------------------------
/**
* The client-side implementation of the NextBot
*/
class C_NextBotCombatCharacter : public C_BaseCombatCharacter
{
public:
DECLARE_CLASS( C_NextBotCombatCharacter, C_BaseCombatCharacter );
DECLARE_CLIENTCLASS();
C_NextBotCombatCharacter();
virtual ~C_NextBotCombatCharacter();
public:
virtual void Spawn( void );
virtual void UpdateClientSideAnimation( void );
virtual ShadowType_t ShadowCastType( void );
virtual bool IsNextBot() { return true; }
void ForceShadowCastType( bool bForce, ShadowType_t forcedShadowType = SHADOWS_NONE ) { m_bForceShadowType = bForce; m_forcedShadowType = forcedShadowType; }
bool GetForcedShadowCastType( ShadowType_t* pForcedShadowType ) const;
// Local In View Data.
void InitFrustumData( void ) { m_bInFrustum = false; m_flFrustumDistanceSqr = FLT_MAX; m_nInFrustumFrame = gpGlobals->framecount; }
bool IsInFrustumValid( void ) { return ( m_nInFrustumFrame == gpGlobals->framecount ); }
void SetInFrustum( bool bInFrustum ) { m_bInFrustum = bInFrustum; }
bool IsInFrustum( void ) { return m_bInFrustum; }
void SetInFrustumDistanceSqr( float flDistance ) { m_flFrustumDistanceSqr = flDistance; }
float GetInFrustumDistanceSqr( void ) { return m_flFrustumDistanceSqr; }
private:
ShadowType_t m_shadowType; // Are we LOD'd to simple shadows?
CountdownTimer m_shadowTimer; // Timer to throttle checks for shadow LOD
ShadowType_t m_forcedShadowType;
bool m_bForceShadowType;
void UpdateShadowLOD( void );
// Local In View Data.
int m_nInFrustumFrame;
bool m_bInFrustum;
float m_flFrustumDistanceSqr;
private:
C_NextBotCombatCharacter( const C_NextBotCombatCharacter & ); // not defined, not accessible
};
//--------------------------------------------------------------------------------------------------------
/**
* The C_NextBotManager manager
*/
class C_NextBotManager
{
public:
C_NextBotManager( void );
~C_NextBotManager();
/**
* Execute functor for each NextBot in the system.
* If a functor returns false, stop iteration early
* and return false.
*/
template < typename Functor >
bool ForEachCombatCharacter( Functor &func )
{
for( int i=0; i < m_botList.Count(); ++i )
{
C_NextBotCombatCharacter *character = m_botList[i];
if ( character->IsPlayer() )
{
continue;
}
if ( character->IsDormant() )
{
continue;
}
if ( !func( character ) )
{
return false;
}
}
return true;
}
int GetActiveCount() { return m_botList.Count(); }
bool SetupInFrustumData( void );
bool IsInFrustumDataValid( void ) { return ( m_nInFrustumFrame == gpGlobals->framecount ); }
private:
friend class C_NextBotCombatCharacter;
void Register( C_NextBotCombatCharacter *bot );
void UnRegister( C_NextBotCombatCharacter *bot );
CUtlVector< C_NextBotCombatCharacter * > m_botList; ///< list of all active NextBots
int m_nInFrustumFrame;
};
// singleton accessor
extern C_NextBotManager &TheClientNextBots( void );
#endif // _C_NEXT_BOT_H_

View File

@@ -0,0 +1,51 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "functionproxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Returns the player health (from 0 to 1)
//-----------------------------------------------------------------------------
class CProxyHealth : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Factor;
};
bool CProxyHealth::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 CProxyHealth::OnBind( void *pC_BaseEntity )
{
if (!pC_BaseEntity)
return;
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
Assert( m_pResult );
SetFloatResult( pEntity->HealthFraction() * m_Factor.GetFloat() );
}
EXPOSE_MATERIAL_PROXY( CProxyHealth, Health );

View File

@@ -0,0 +1,316 @@
#include "cbase.h"
#include "keyvalues.h"
#include "cdll_client_int.h"
#include "view_scene.h"
#include "viewrender.h"
#include "tier0/icommandline.h"
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialsystemhardwareconfig.h"
#include "materialsystem/imaterialvar.h"
#include "ScreenSpaceEffects.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//------------------------------------------------------------------------------
// CScreenSpaceEffectRegistration code
// Used to register and effect with the IScreenSpaceEffectManager
//------------------------------------------------------------------------------
CScreenSpaceEffectRegistration *CScreenSpaceEffectRegistration::s_pHead = NULL;
CScreenSpaceEffectRegistration::CScreenSpaceEffectRegistration( const char *pName, IScreenSpaceEffect *pEffect )
{
m_pEffectName = pName;
m_pEffect = pEffect;
m_pNext = s_pHead;
s_pHead = this;
}
//------------------------------------------------------------------------------
// CScreenSpaceEffectManager - Implementation of IScreenSpaceEffectManager
//------------------------------------------------------------------------------
class CScreenSpaceEffectManager : public IScreenSpaceEffectManager
{
public:
virtual void InitScreenSpaceEffects( );
virtual void ShutdownScreenSpaceEffects( );
virtual IScreenSpaceEffect *GetScreenSpaceEffect( const char *pEffectName );
virtual void SetScreenSpaceEffectParams( const char *pEffectName, KeyValues *params );
virtual void SetScreenSpaceEffectParams( IScreenSpaceEffect *pEffect, KeyValues *params );
virtual void EnableScreenSpaceEffect( const char *pEffectName );
virtual void EnableScreenSpaceEffect( IScreenSpaceEffect *pEffect );
virtual void DisableScreenSpaceEffect( const char *pEffectName );
virtual void DisableScreenSpaceEffect( IScreenSpaceEffect *pEffect );
virtual void DisableAllScreenSpaceEffects( );
virtual void RenderEffects( int x, int y, int w, int h );
};
CScreenSpaceEffectManager g_ScreenSpaceEffectManager;
IScreenSpaceEffectManager *g_pScreenSpaceEffects = &g_ScreenSpaceEffectManager;
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::InitScreenSpaceEffects - Initialise all registered effects
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::InitScreenSpaceEffects( )
{
if ( CommandLine()->FindParm( "-filmgrain" ) )
{
GetScreenSpaceEffect( "filmgrain" )->Enable( true );
}
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
bool bIsEnabled = pEffect->IsEnabled( );
pEffect->Init( );
pEffect->Enable( bIsEnabled );
}
}
}
//----------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::ShutdownScreenSpaceEffects - Shutdown all registered effects
//----------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::ShutdownScreenSpaceEffects( )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
pEffect->Shutdown( );
}
}
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::GetScreenSpaceEffect - Returns a point to the named effect
//---------------------------------------------------------------------------------------
IScreenSpaceEffect *CScreenSpaceEffectManager::GetScreenSpaceEffect( const char *pEffectName )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
if( !Q_stricmp( pReg->m_pEffectName, pEffectName ) )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
return pEffect;
}
}
Warning( "Could not find screen space effect %s\n", pEffectName );
return NULL;
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::SetScreenSpaceEffectParams
// - Assign parameters to the specified effect
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::SetScreenSpaceEffectParams( const char *pEffectName, KeyValues *params )
{
IScreenSpaceEffect *pEffect = GetScreenSpaceEffect( pEffectName );
if( pEffect )
SetScreenSpaceEffectParams( pEffect, params );
}
void CScreenSpaceEffectManager::SetScreenSpaceEffectParams( IScreenSpaceEffect *pEffect, KeyValues *params )
{
if( pEffect )
pEffect->SetParameters( params );
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::EnableScreenSpaceEffect
// - Enables the specified effect
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::EnableScreenSpaceEffect( const char *pEffectName )
{
IScreenSpaceEffect *pEffect = GetScreenSpaceEffect( pEffectName );
if( pEffect )
EnableScreenSpaceEffect( pEffect );
}
void CScreenSpaceEffectManager::EnableScreenSpaceEffect( IScreenSpaceEffect *pEffect )
{
if( pEffect )
pEffect->Enable( true );
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::DisableScreenSpaceEffect
// - Disables the specified effect
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::DisableScreenSpaceEffect( const char *pEffectName )
{
IScreenSpaceEffect *pEffect = GetScreenSpaceEffect( pEffectName );
if( pEffect )
DisableScreenSpaceEffect( pEffect );
}
void CScreenSpaceEffectManager::DisableScreenSpaceEffect( IScreenSpaceEffect *pEffect )
{
if( pEffect )
pEffect->Enable( false );
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::DisableAllScreenSpaceEffects
// - Disables all registered screen space effects
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::DisableAllScreenSpaceEffects( )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
pEffect->Enable( false );
}
}
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::RenderEffects
// - Renders all registered screen space effects
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::RenderEffects( int x, int y, int w, int h )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
pEffect->Render( x, y, w, h );
}
}
}
//------------------------------------------------------------------------------
// Example post-processing effect
//------------------------------------------------------------------------------
class CExampleEffect : public IScreenSpaceEffect
{
public:
CExampleEffect( );
~CExampleEffect( );
void Init( );
void Shutdown( );
void SetParameters( KeyValues *params );
void Render( int x, int y, int w, int h );
void Enable( bool bEnable );
bool IsEnabled( );
private:
bool m_bEnable;
CMaterialReference m_Material;
};
ADD_SCREENSPACE_EFFECT( CExampleEffect, exampleeffect );
//------------------------------------------------------------------------------
// CExampleEffect constructor
//------------------------------------------------------------------------------
CExampleEffect::CExampleEffect( )
{
m_bEnable = false;
}
//------------------------------------------------------------------------------
// CExampleEffect destructor
//------------------------------------------------------------------------------
CExampleEffect::~CExampleEffect( )
{
}
//------------------------------------------------------------------------------
// CExampleEffect init
//------------------------------------------------------------------------------
void CExampleEffect::Init( )
{
// This is just example code, init your effect material here
//m_Material.Init( "engine/exampleeffect", TEXTURE_GROUP_OTHER );
m_bEnable = false;
}
//------------------------------------------------------------------------------
// CExampleEffect shutdown
//------------------------------------------------------------------------------
void CExampleEffect::Shutdown( )
{
m_Material.Shutdown();
}
//------------------------------------------------------------------------------
// CExampleEffect enable
//------------------------------------------------------------------------------
void CExampleEffect::Enable( bool bEnable )
{
// This is just example code, don't enable it
// m_bEnable = bEnable;
}
bool CExampleEffect::IsEnabled( )
{
return m_bEnable;
}
//------------------------------------------------------------------------------
// CExampleEffect SetParameters
//------------------------------------------------------------------------------
void CExampleEffect::SetParameters( KeyValues *params )
{
if( params->GetDataType( "example_param" ) == KeyValues::TYPE_STRING )
{
// ...
}
}
//------------------------------------------------------------------------------
// CExampleEffect render
//------------------------------------------------------------------------------
void CExampleEffect::Render( int x, int y, int w, int h )
{
if ( !IsEnabled() )
return;
// Render Effect
Rect_t actualRect;
UpdateScreenEffectTexture( 0, x, y, w, h, false, &actualRect );
ITexture *pTexture = GetFullFrameFrameBufferTexture( 0 );
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->DrawScreenSpaceRectangle( m_Material, x, y, w, h,
actualRect.x, actualRect.y, actualRect.x+actualRect.width-1, actualRect.y+actualRect.height-1,
pTexture->GetActualWidth(), pTexture->GetActualHeight() );
}

View File

@@ -0,0 +1,88 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=====================================================================================//
#ifndef SCREENSPACEEFFECTS_H
#define SCREENSPACEEFFECTS_H
#ifdef _WIN32
#pragma once
#endif
class KeyValues;
//------------------------------------------------------------------------------
// Simple base class for screen space post-processing effects
//------------------------------------------------------------------------------
abstract_class IScreenSpaceEffect
{
public:
virtual void Init( ) = 0;
virtual void Shutdown( ) = 0;
virtual void SetParameters( KeyValues *params ) = 0;
virtual void Render( int x, int y, int w, int h ) = 0;
virtual void Enable( bool bEnable ) = 0;
virtual bool IsEnabled( ) = 0;
};
//------------------------------------------------------------------------------
// Interface class for managing screen space post-processing effects
//------------------------------------------------------------------------------
abstract_class IScreenSpaceEffectManager
{
public:
virtual void InitScreenSpaceEffects( ) = 0;
virtual void ShutdownScreenSpaceEffects( ) = 0;
virtual IScreenSpaceEffect *GetScreenSpaceEffect( const char *pEffectName ) = 0;
virtual void SetScreenSpaceEffectParams( const char *pEffectName, KeyValues *params ) = 0;
virtual void SetScreenSpaceEffectParams( IScreenSpaceEffect *pEffect, KeyValues *params ) = 0;
virtual void EnableScreenSpaceEffect( const char *pEffectName ) = 0;
virtual void EnableScreenSpaceEffect( IScreenSpaceEffect *pEffect ) = 0;
virtual void DisableScreenSpaceEffect( const char *pEffectName ) = 0;
virtual void DisableScreenSpaceEffect( IScreenSpaceEffect *pEffect ) = 0;
virtual void DisableAllScreenSpaceEffects( ) = 0;
virtual void RenderEffects( int x, int y, int w, int h ) = 0;
};
extern IScreenSpaceEffectManager *g_pScreenSpaceEffects;
//-------------------------------------------------------------------------------------
// Registration class for adding screen space effects to the IScreenSpaceEffectManager
//-------------------------------------------------------------------------------------
class CScreenSpaceEffectRegistration
{
public:
CScreenSpaceEffectRegistration( const char *pName, IScreenSpaceEffect *pEffect );
const char *m_pEffectName;
IScreenSpaceEffect *m_pEffect;
CScreenSpaceEffectRegistration *m_pNext;
static CScreenSpaceEffectRegistration *s_pHead;
};
#define ADD_SCREENSPACE_EFFECT( CEffect, pEffectName ) CEffect pEffectName##_effect; \
CScreenSpaceEffectRegistration pEffectName##_reg( #pEffectName, &pEffectName##_effect );
#endif

View File

@@ -0,0 +1,172 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which is rendered image on top of an entity
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "teambitmapimage.h"
#include <KeyValues.h>
#include "vgui_BitmapImage.h"
#include "PanelMetaClassMgr.h"
#include "vguimatsurface/IMatSystemSurface.h"
#include <vgui_controls/Panel.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// A multiplexer bitmap that chooses a bitmap based on team
//-----------------------------------------------------------------------------
CTeamBitmapImage::CTeamBitmapImage() : m_Alpha(1.0f)
{
memset( m_ppImage, 0, BITMAP_COUNT * sizeof(BitmapImage*) );
m_pEntity = NULL;
m_bRelativeTeams = 0;
}
CTeamBitmapImage::~CTeamBitmapImage()
{
int i;
for ( i = 0; i < BITMAP_COUNT; ++i )
{
if (m_ppImage[i])
delete m_ppImage[i];
}
}
//-----------------------------------------------------------------------------
// initialization
//-----------------------------------------------------------------------------
bool CTeamBitmapImage::Init( vgui::Panel *pParent, KeyValues* pInitData, C_BaseEntity* pEntity )
{
static char *pRelativeTeamNames[BITMAP_COUNT] =
{
"NoTeam",
"MyTeam",
"EnemyTeam",
};
static char *pAbsoluteTeamNames[BITMAP_COUNT] =
{
"Team0",
"Team1",
"Team2",
};
m_pEntity = pEntity;
m_bRelativeTeams = (pInitData->GetInt( "relativeteam" ) != 0);
char **ppTeamNames = m_bRelativeTeams ? pRelativeTeamNames : pAbsoluteTeamNames;
int i;
for ( i = 0 ; i < BITMAP_COUNT; ++i )
{
// Default to null
m_ppImage[i] = NULL;
// Look for team section
KeyValues *pTeamKV = pInitData->FindKey( ppTeamNames[i] );
if ( !pTeamKV )
continue;
char const* pClassImage = pTeamKV->GetString( "material" );
if ( !pClassImage || !pClassImage[ 0 ] )
return false;
// modulation color
Color color;
if (!ParseRGBA( pTeamKV, "color", color ))
color.SetColor( 255, 255, 255, 255 );
// hook in the bitmap
m_ppImage[i] = new BitmapImage( pParent->GetVPanel(), pClassImage );
m_ppImage[i]->SetColor( color );
}
return true;
}
//-----------------------------------------------------------------------------
// Alpha modulate...
//-----------------------------------------------------------------------------
void CTeamBitmapImage::SetAlpha( float alpha )
{
m_Alpha = clamp( alpha, 0.0f, 1.0f );
}
//-----------------------------------------------------------------------------
// draw
//-----------------------------------------------------------------------------
void CTeamBitmapImage::Paint( float yaw /*= 0.0f*/ )
{
if (m_Alpha == 0.0f)
return;
int team = 0;
if (m_bRelativeTeams)
{
if (GetEntity())
{
if (GetEntity()->GetTeamNumber() != 0)
{
team = GetEntity()->InLocalTeam() ? 1 : 2;
}
}
}
else
{
if (GetEntity())
team = GetEntity()->GetTeamNumber();
}
// Paint the image for the current team
if (m_ppImage[team])
{
// Modulate the color based on the alpha....
Color color = m_ppImage[team]->GetColor();
int alpha = color[3];
color[3] = (alpha * m_Alpha);
m_ppImage[team]->SetColor( color );
if ( yaw != 0.0f )
{
g_pMatSystemSurface->DisableClipping( true );
m_ppImage[team]->DoPaint( m_ppImage[team]->GetRenderSizePanel(), yaw );
g_pMatSystemSurface->DisableClipping( false );
}
else
{
// Paint
m_ppImage[team]->Paint();
}
// restore previous color
color[3] = alpha;
m_ppImage[team]->SetColor( color );
}
}
//-----------------------------------------------------------------------------
// Helper method to initialize a team image from KeyValues data..
//-----------------------------------------------------------------------------
bool InitializeTeamImage( KeyValues *pInitData, const char* pSectionName, vgui::Panel *pParent, C_BaseEntity *pEntity, CTeamBitmapImage* pTeamImage )
{
KeyValues *pTeamImageSection = pInitData;
if (pSectionName)
{
pTeamImageSection = pInitData->FindKey( pSectionName );
if ( !pTeamImageSection )
return false;
}
return pTeamImage->Init( pParent, pTeamImageSection, pEntity );
}

View File

@@ -0,0 +1,80 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which is rendered image on top of an entity
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#ifndef TEAMBITMAPIMAGE_H
#define TEAMBITMAPIMAGE_H
#ifdef _WIN32
#pragma once
#endif
//#include "tf_shareddefs.h"
#include <vgui/vgui.h>
namespace vgui
{
class Panel;
}
class BitmapImage;
class C_BaseEntity;
class KeyValues;
//-----------------------------------------------------------------------------
// A multiplexer bitmap that chooses a bitmap based on team
//-----------------------------------------------------------------------------
class CTeamBitmapImage
{
public:
// construction, destruction
CTeamBitmapImage();
~CTeamBitmapImage();
// initialization
bool Init( vgui::Panel *pParent, KeyValues* pInitData, C_BaseEntity* pEntity );
// Alpha override...
void SetAlpha( float alpha );
// Paint the sucka. Paint it the size of the parent panel
void Paint( float yaw = 0.0f );
protected:
// Wrapper so we can implement this with EHANDLES some day
C_BaseEntity *GetEntity() { return m_pEntity; }
private:
enum
{
// NOTE: Was MAX_TF_TEAMS not 4, but I don't like the dependency here.
BITMAP_COUNT = 4 + 1
};
BitmapImage *m_ppImage[ BITMAP_COUNT ];
C_BaseEntity *m_pEntity;
float m_Alpha;
bool m_bRelativeTeams;
};
//-----------------------------------------------------------------------------
// Helper method to initialize a team image from KeyValues data..
// KeyValues contains the bitmap data. pSectionName, if it exists,
// indicates which subsection of pInitData should be looked at to get at the
// image data. The final argument is the bitmap image to initialize.
// The function returns true if it succeeded.
//
// NOTE: This function looks for the key values 'material' and 'color'
// and uses them to set up the material + modulation color of the image
//-----------------------------------------------------------------------------
bool InitializeTeamImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, C_BaseEntity *pEntity, CTeamBitmapImage* pBitmapImage );
#endif // TEAMBITMAPIMAGE_H

View File

@@ -0,0 +1,83 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which is rendered image on top of an entity
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "ViewConeImage.h"
#include <keyvalues.h>
#include <vgui_controls/Panel.h>
#include "VGuiMatSurface/IMatSystemSurface.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// initialization
//-----------------------------------------------------------------------------
bool CViewConeImage::Init( vgui::Panel *pParent, KeyValues* pInitData )
{
Assert( pParent );
// Load viewcone material
if (!m_Image.Init( pParent->GetVPanel(), pInitData ))
return false;
// Position the view cone...
int viewconesize = pInitData->GetInt( "size", 32 );
m_Image.SetRenderSize( viewconesize, viewconesize );
int cx, cy;
pParent->GetSize( cx, cy );
m_Image.SetPos( (cx - viewconesize) / 2, (cy - viewconesize) / 2 );
return true;
}
//-----------------------------------------------------------------------------
// Paint the sucka
//-----------------------------------------------------------------------------
void CViewConeImage::Paint( float yaw )
{
g_pMatSystemSurface->DisableClipping( true );
m_Image.DoPaint( NULL, yaw );
g_pMatSystemSurface->DisableClipping( false );
}
void CViewConeImage::SetColor( int r, int g, int b )
{
m_Image.SetColor( Color( r, g, b, 255 ) );
}
//-----------------------------------------------------------------------------
// Helper method to initialize a view cone image from KeyValues data..
// KeyValues contains the bitmap data, pSectionName, if it exists,
// indicates which subsection of pInitData should be looked at to get at the
// image data. The final argument is the bitmap image to initialize.
// The function returns true if it succeeded.
//
// NOTE: This function looks for the key values 'material' and 'color'
// and uses them to set up the material + modulation color of the image
//-----------------------------------------------------------------------------
bool InitializeViewConeImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, CViewConeImage* pViewConeImage )
{
KeyValues *pViewConeImageSection;
if (pSectionName)
{
pViewConeImageSection = pInitData->FindKey( pSectionName );
if ( !pViewConeImageSection )
return false;
}
else
{
pViewConeImageSection = pInitData;
}
return pViewConeImage->Init( pParent, pViewConeImageSection );
}

View File

@@ -0,0 +1,56 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which draws a viewcone
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#ifndef VIEWCONEIMAGE_H
#define VIEWCONEIMAGE_H
#include "shareddefs.h"
#include "vgui_bitmapimage.h"
namespace vgui
{
class Panel;
}
class C_BaseEntity;
class KeyValues;
//-----------------------------------------------------------------------------
// A bitmap that renders a view cone based on angles
//-----------------------------------------------------------------------------
class CViewConeImage
{
public:
// initialization
bool Init( vgui::Panel *pParent, KeyValues* pInitData );
// Paint the sucka
void Paint( float yaw );
void SetColor( int r, int g, int b );
private:
BitmapImage m_Image;
};
//-----------------------------------------------------------------------------
// Helper method to initialize a view cone image from KeyValues data..
// KeyValues contains the bitmap data, pSectionName, if it exists,
// indicates which subsection of pInitData should be looked at to get at the
// image data. The final argument is the bitmap image to initialize.
// The function returns true if it succeeded.
//
// NOTE: This function looks for the key values 'material' and 'color'
// and uses them to set up the material + modulation color of the image
//-----------------------------------------------------------------------------
bool InitializeViewConeImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, CViewConeImage* pViewConeImage );
#endif // VIEWCONEIMAGE_H

View File

@@ -0,0 +1,75 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/imaterialproxy.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "iviewrender.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// no inputs, assumes that the results go into $CHEAPWATERSTARTDISTANCE and $CHEAPWATERENDDISTANCE
class CWaterLODMaterialProxy : public IMaterialProxy
{
public:
CWaterLODMaterialProxy();
virtual ~CWaterLODMaterialProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
virtual IMaterial *GetMaterial();
private:
IMaterialVar *m_pCheapWaterStartDistanceVar;
IMaterialVar *m_pCheapWaterEndDistanceVar;
};
CWaterLODMaterialProxy::CWaterLODMaterialProxy()
{
m_pCheapWaterStartDistanceVar = NULL;
m_pCheapWaterEndDistanceVar = NULL;
}
CWaterLODMaterialProxy::~CWaterLODMaterialProxy()
{
}
bool CWaterLODMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
bool foundVar;
m_pCheapWaterStartDistanceVar = pMaterial->FindVar( "$CHEAPWATERSTARTDISTANCE", &foundVar, false );
if( !foundVar )
return false;
m_pCheapWaterEndDistanceVar = pMaterial->FindVar( "$CHEAPWATERENDDISTANCE", &foundVar, false );
if( !foundVar )
return false;
return true;
}
void CWaterLODMaterialProxy::OnBind( void *pC_BaseEntity )
{
if( !m_pCheapWaterStartDistanceVar || !m_pCheapWaterEndDistanceVar )
{
return;
}
float start, end;
view->GetWaterLODParams( start, end );
m_pCheapWaterStartDistanceVar->SetFloatValue( start );
m_pCheapWaterEndDistanceVar->SetFloatValue( end );
}
IMaterial *CWaterLODMaterialProxy::GetMaterial()
{
return m_pCheapWaterStartDistanceVar->GetOwningMaterial();
}
EXPOSE_MATERIAL_PROXY( CWaterLODMaterialProxy, WaterLOD );

View File

@@ -0,0 +1,70 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "materialsystem/imaterialproxy.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "c_world.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CWorldDimsProxy : public IMaterialProxy
{
public:
CWorldDimsProxy();
virtual ~CWorldDimsProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
virtual IMaterial *GetMaterial();
public:
IMaterialVar *m_pMinsVar;
IMaterialVar *m_pMaxsVar;
};
CWorldDimsProxy::CWorldDimsProxy()
{
m_pMinsVar = m_pMaxsVar = NULL;
}
CWorldDimsProxy::~CWorldDimsProxy()
{
}
bool CWorldDimsProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
m_pMinsVar = pMaterial->FindVar( "$world_mins", NULL, false );
m_pMaxsVar = pMaterial->FindVar( "$world_maxs", NULL, false );
return true;
}
void CWorldDimsProxy::OnBind( void *pC_BaseEntity )
{
if ( m_pMinsVar && m_pMaxsVar )
{
C_World *pWorld = GetClientWorldEntity();
if ( pWorld )
{
m_pMinsVar->SetVecValue( (const float*)&pWorld->m_WorldMins, 3 );
m_pMaxsVar->SetVecValue( (const float*)&pWorld->m_WorldMaxs, 3 );
}
}
}
IMaterial *CWorldDimsProxy::GetMaterial()
{
return m_pMinsVar->GetOwningMaterial();
}
EXPOSE_MATERIAL_PROXY( CWorldDimsProxy, WorldDims );

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,278 @@
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "hud.h"
#include "hud_macros.h"
#include "hudelement.h"
#include "iclientmode.h"
#include "ienginevgui.h"
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui/IVGUI.h>
#include <vgui_controls/EditablePanel.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/ImagePanel.h>
#include "achievement_notification_panel.h"
#ifndef NO_STEAM
#include "steam/steam_api.h"
#endif
#include "iachievementmgr.h"
#include "fmtstr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
#define ACHIEVEMENT_NOTIFICATION_DURATION 10.0f
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
DECLARE_HUDELEMENT_DEPTH( CAchievementNotificationPanel, 100 );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CAchievementNotificationPanel::CAchievementNotificationPanel( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "AchievementNotificationPanel" )
{
Panel *pParent = GetClientMode()->GetViewport();
SetParent( pParent );
SetScheme( "basemodui_scheme" );
m_flHideTime = 0;
m_pPanelBackground = new EditablePanel( this, "Notification_Background" );
m_pIcon = new ImagePanel( this, "Notification_Icon" );
m_pLabelHeading = new Label( this, "HeadingLabel", "" );
m_pLabelTitle = new Label( this, "TitleLabel", "" );
m_pIcon->SetShouldScaleImage( true );
vgui::ivgui()->AddTickSignal( GetVPanel() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::Init()
{
ListenForGameEvent( "achievement_event" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::ApplySchemeSettings( IScheme *pScheme )
{
// load control settings...
LoadControlSettings( "resource/UI/AchievementNotification.res" );
BaseClass::ApplySchemeSettings( pScheme );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::PerformLayout( void )
{
BaseClass::PerformLayout();
// Set background color of various elements. Need to do this in code, if we do it in res file it gets slammed by the
// scheme. (Incl. label background: some products don't have label background colors set in their scheme and helpfully slam it to white.)
SetBgColor( Color( 0, 0, 0, 0 ) );
m_pLabelHeading->SetBgColor( Color( 0, 0, 0, 0 ) );
m_pLabelTitle->SetBgColor( Color( 0, 0, 0, 0 ) );
m_pPanelBackground->SetBgColor( Color( 62,70,55, 200 ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::FireGameEvent( IGameEvent * event )
{
const char *name = event->GetName();
if ( 0 == Q_strcmp( name, "achievement_event" ) )
{
const char *pchName = event->GetString( "achievement_name" );
int iCur = event->GetInt( "cur_val" );
int iMax = event->GetInt( "max_val" );
wchar_t szLocalizedName[256]=L"";
#ifndef NO_STEAM
if ( IsPC() )
{
// shouldn't ever get achievement progress if steam not running and user logged in, but check just in case
if ( !steamapicontext->SteamUserStats() )
{
Msg( "Steam not running, achievement progress notification not displayed\n" );
}
else
{
// use Steam to show achievement progress UI
steamapicontext->SteamUserStats()->IndicateAchievementProgress( pchName, iCur, iMax );
}
}
else
#endif
{
// on X360 we need to show our own achievement progress UI
const wchar_t *pchLocalizedName = ACHIEVEMENT_LOCALIZED_NAME_FROM_STR( pchName );
Assert( pchLocalizedName );
if ( !pchLocalizedName || !pchLocalizedName[0] )
return;
Q_wcsncpy( szLocalizedName, pchLocalizedName, sizeof( szLocalizedName ) );
// this is achievement progress, compose the message of form: "<name> (<#>/<max>)"
wchar_t szFmt[128]=L"";
wchar_t szText[512]=L"";
wchar_t szNumFound[16]=L"";
wchar_t szNumTotal[16]=L"";
Q_snwprintf( szNumFound, ARRAYSIZE( szNumFound ), L"%i", iCur );
Q_snwprintf( szNumTotal, ARRAYSIZE( szNumTotal ), L"%i", iMax );
const wchar_t *pchFmt = g_pVGuiLocalize->Find( "#GameUI_Achievement_Progress_Fmt" );
if ( !pchFmt || !pchFmt[0] )
return;
Q_wcsncpy( szFmt, pchFmt, sizeof( szFmt ) );
g_pVGuiLocalize->ConstructString( szText, sizeof( szText ), szFmt, 3, szLocalizedName, szNumFound, szNumTotal );
AddNotification( pchName, g_pVGuiLocalize->FindSafe( "#GameUI_Achievement_Progress" ), szText );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Called on each tick
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::OnTick( void )
{
if ( ( m_flHideTime > 0 ) && ( m_flHideTime < gpGlobals->curtime ) )
{
m_flHideTime = 0;
ShowNextNotification();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CAchievementNotificationPanel::ShouldDraw( void )
{
return ( ( m_flHideTime > 0 ) && ( m_flHideTime > gpGlobals->curtime ) && CHudElement::ShouldDraw() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::AddNotification( const char *szIconBaseName, const wchar_t *pHeading, const wchar_t *pTitle )
{
// put this notification in our queue
int iQueueItem = m_queueNotification.AddToTail();
Notification_t &notification = m_queueNotification[iQueueItem];
Q_strncpy( notification.szIconBaseName, szIconBaseName, ARRAYSIZE( notification.szIconBaseName ) );
Q_wcsncpy( notification.szHeading, pHeading, sizeof( notification.szHeading ) );
Q_wcsncpy( notification.szTitle, pTitle, sizeof( notification.szTitle ) );
// if we are not currently displaying a notification, go ahead and show this one
if ( 0 == m_flHideTime )
{
ShowNextNotification();
}
}
//-----------------------------------------------------------------------------
// Purpose: Shows next notification in queue if there is one
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::ShowNextNotification()
{
// see if we have anything to do
if ( 0 == m_queueNotification.Count() )
{
m_flHideTime = 0;
return;
}
Notification_t &notification = m_queueNotification[ m_queueNotification.Head() ];
m_flHideTime = gpGlobals->curtime + ACHIEVEMENT_NOTIFICATION_DURATION;
// set the text and icon in the dialog
SetDialogVariable( "heading", notification.szHeading );
SetDialogVariable( "title", notification.szTitle );
const char *pchIconBaseName = notification.szIconBaseName;
if ( pchIconBaseName && pchIconBaseName[0] )
{
m_pIcon->SetImage( CFmtStr( "achievements/%s.vmt", pchIconBaseName ) );
}
// resize the panel so it always looks good
// get fonts
HFont hFontHeading = m_pLabelHeading->GetFont();
HFont hFontTitle = m_pLabelTitle->GetFont();
// determine how wide the text strings are
int iHeadingWidth = UTIL_ComputeStringWidth( hFontHeading, notification.szHeading );
int iTitleWidth = UTIL_ComputeStringWidth( hFontTitle, notification.szTitle );
// use the widest string
int iTextWidth = MAX( iHeadingWidth, iTitleWidth );
// don't let it be insanely wide
iTextWidth = MIN( iTextWidth, XRES( 300 ) );
int iIconWidth = m_pIcon->GetWide();
int iSpacing = XRES( 10 );
int iPanelWidth = iSpacing + iIconWidth + iSpacing + iTextWidth + iSpacing;
int iPanelX = GetWide() - iPanelWidth;
int iIconX = iPanelX + iSpacing;
int iTextX = iIconX + iIconWidth + iSpacing;
// resize all the elements
SetXAndWide( m_pPanelBackground, iPanelX, iPanelWidth );
SetXAndWide( m_pIcon, iIconX, iIconWidth );
SetXAndWide( m_pLabelHeading, iTextX, iTextWidth );
SetXAndWide( m_pLabelTitle, iTextX, iTextWidth );
m_queueNotification.Remove( m_queueNotification.Head() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::SetXAndWide( Panel *pPanel, int x, int wide )
{
int xCur, yCur;
pPanel->GetPos( xCur, yCur );
pPanel->SetPos( x, yCur );
pPanel->SetWide( wide );
}
CON_COMMAND_F( achievement_notification_test, "Test the hud notification UI", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY )
{
static int iCount=0;
CAchievementNotificationPanel *pPanel = GET_HUDELEMENT( CAchievementNotificationPanel );
if ( pPanel )
{
pPanel->AddNotification( "HL2_KILL_ODESSAGUNSHIP", L"Achievement Progress", ( 0 == ( iCount % 2 ) ? L"Test Notification Message A (1/10)" :
L"Test Message B" ) );
}
#if 0
IGameEvent *event = gameeventmanager->CreateEvent( "achievement_event" );
if ( event )
{
const char *szTestStr[] = { "TF_GET_HEADSHOTS", "TF_PLAY_GAME_EVERYMAP", "TF_PLAY_GAME_EVERYCLASS", "TF_GET_HEALPOINTS" };
event->SetString( "achievement_name", szTestStr[iCount%ARRAYSIZE(szTestStr)] );
event->SetInt( "cur_val", ( iCount%9 ) + 1 );
event->SetInt( "max_val", 10 );
gameeventmanager->FireEvent( event );
}
#endif
iCount++;
}

View File

@@ -0,0 +1,57 @@
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ACHIEVEMENT_NOTIFICATION_PANEL_H
#define ACHIEVEMENT_NOTIFICATION_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/EditablePanel.h>
#include "hudelement.h"
using namespace vgui;
class CAchievementNotificationPanel : public CHudElement, public EditablePanel
{
DECLARE_CLASS_SIMPLE( CAchievementNotificationPanel, EditablePanel );
public:
explicit CAchievementNotificationPanel( const char *pElementName );
virtual void Init();
virtual void ApplySchemeSettings( IScheme *scheme );
virtual bool ShouldDraw( void );
virtual void PerformLayout( void );
virtual void LevelInit( void ) { m_flHideTime = 0; }
virtual void FireGameEvent( IGameEvent * event );
virtual void OnTick( void );
void AddNotification( const char *szIconBaseName, const wchar_t *pHeading, const wchar_t *pTitle );
private:
void ShowNextNotification();
void SetXAndWide( Panel *pPanel, int x, int wide );
float m_flHideTime;
Label *m_pLabelHeading;
Label *m_pLabelTitle;
EditablePanel *m_pPanelBackground;
ImagePanel *m_pIcon;
struct Notification_t
{
char szIconBaseName[255];
wchar_t szHeading[255];
wchar_t szTitle[255];
};
CUtlLinkedList<Notification_t> m_queueNotification;
};
#endif // ACHIEVEMENT_NOTIFICATION_PANEL_H

View File

@@ -0,0 +1,52 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "baseanimatedtextureproxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimatedEntityTextureProxy : public CBaseAnimatedTextureProxy
{
public:
CAnimatedEntityTextureProxy() {}
virtual ~CAnimatedEntityTextureProxy() {}
virtual float GetAnimationStartTime( void* pBaseEntity );
virtual void AnimationWrapped( void* pC_BaseEntity );
};
EXPOSE_MATERIAL_PROXY( CAnimatedEntityTextureProxy, AnimatedEntityTexture );
float CAnimatedEntityTextureProxy::GetAnimationStartTime( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return 0.0f;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
return pEntity->GetTextureAnimationStartTime();
}
return 0.0f;
}
void CAnimatedEntityTextureProxy::AnimationWrapped( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
pEntity->TextureAnimationWrapped();
}
}

View File

@@ -0,0 +1,57 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "baseanimatedtextureproxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimatedOffsetTextureProxy : public CBaseAnimatedTextureProxy
{
public:
CAnimatedOffsetTextureProxy() : m_flFrameOffset( 0.0f ) {}
virtual ~CAnimatedOffsetTextureProxy() {}
virtual float GetAnimationStartTime( void* pBaseEntity );
virtual void OnBind( void *pBaseEntity );
protected:
float m_flFrameOffset;
};
EXPOSE_MATERIAL_PROXY( CAnimatedOffsetTextureProxy, AnimatedOffsetTexture );
//-----------------------------------------------------------------------------
// Purpose:
// Input : pArg -
// Output : float
//-----------------------------------------------------------------------------
float CAnimatedOffsetTextureProxy::GetAnimationStartTime( void* pArg )
{
return m_flFrameOffset;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pBaseEntity -
//-----------------------------------------------------------------------------
void CAnimatedOffsetTextureProxy::OnBind( void *pBaseEntity )
{
C_BaseEntity* pEntity = (C_BaseEntity*)pBaseEntity;
if ( pEntity )
{
m_flFrameOffset = pEntity->GetTextureAnimationStartTime();
}
// Call into the base class
CBaseAnimatedTextureProxy::OnBind( pBaseEntity );
}

View File

@@ -0,0 +1,30 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "baseanimatedtextureproxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimatedTextureProxy : public CBaseAnimatedTextureProxy
{
public:
CAnimatedTextureProxy() {}
virtual ~CAnimatedTextureProxy() {}
virtual float GetAnimationStartTime( void* pBaseEntity );
};
EXPOSE_MATERIAL_PROXY( CAnimatedTextureProxy, AnimatedTexture );
#pragma warning (disable : 4100)
float CAnimatedTextureProxy::GetAnimationStartTime( void* pBaseEntity )
{
return 0;
}

View File

@@ -0,0 +1,347 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef ANIMATIONLAYER_H
#define ANIMATIONLAYER_H
#ifdef _WIN32
#pragma once
#endif
#include "rangecheckedvar.h"
#include "tier1/lerp_functions.h"
#ifdef CLIENT_DLL
class C_BaseAnimatingOverlay;
#endif
class C_AnimationLayer
{
public:
// This allows the datatables to access private members.
ALLOW_DATATABLES_PRIVATE_ACCESS();
C_AnimationLayer();
void Reset();
#ifdef CLIENT_DLL
void SetOwner( C_BaseAnimatingOverlay *pOverlay );
C_BaseAnimatingOverlay *GetOwner() const;
#endif
void SetOrder( int order );
bool IsActive( void );
float GetFadeout( float flCurTime );
void SetSequence( int nSequence );
void SetCycle( float flCycle );
void SetPrevCycle( float flCycle );
void SetPlaybackRate( float flPlaybackRate );
void SetWeight( float flWeight );
void SetWeightDeltaRate( float flDelta );
int GetOrder() const;
int GetSequence( ) const;
float GetCycle( ) const;
float GetPrevCycle( ) const;
float GetPlaybackRate( ) const;
float GetWeight( ) const;
float GetWeightDeltaRate( ) const;
#ifdef CLIENT_DLL
// If the weights, cycle or sequence #s changed due to interpolation then
// we'll need to recompute the bbox
int GetInvalidatePhysicsBits() const;
void SetInvalidatePhysicsBits( int iBit ) { m_nInvalidatePhysicsBits = iBit; }
#endif
public:
float m_flLayerAnimtime;
float m_flLayerFadeOuttime;
// dispatch flags
CStudioHdr *m_pDispatchedStudioHdr;
int m_nDispatchedSrc;
int m_nDispatchedDst;
private:
int m_nOrder;
CRangeCheckedVar<int, -1, 65535, 0> m_nSequence;
CRangeCheckedVar<float, -2, 2, 0> m_flPrevCycle;
CRangeCheckedVar<float, -5, 5, 0> m_flWeight;
CRangeCheckedVar<float, -5, 5, 0> m_flWeightDeltaRate;
// used for automatic crossfades between sequence changes
CRangeCheckedVar<float, -50, 50, 1> m_flPlaybackRate;
CRangeCheckedVar<float, -2, 2, 0> m_flCycle;
#ifdef CLIENT_DLL
C_BaseAnimatingOverlay *m_pOwner;
int m_nInvalidatePhysicsBits;
#endif
friend class C_BaseAnimatingOverlay;
friend C_AnimationLayer LoopingLerp( float flPercent, C_AnimationLayer& from, C_AnimationLayer& to );
friend C_AnimationLayer Lerp( float flPercent, const C_AnimationLayer& from, const C_AnimationLayer& to );
friend C_AnimationLayer LoopingLerp_Hermite( const C_AnimationLayer& current, float flPercent, C_AnimationLayer& prev, C_AnimationLayer& from, C_AnimationLayer& to );
friend C_AnimationLayer Lerp_Hermite( const C_AnimationLayer& current, float flPercent, const C_AnimationLayer& prev, const C_AnimationLayer& from, const C_AnimationLayer& to );
friend void Lerp_Clamp( C_AnimationLayer &val );
friend int CheckForSequenceBoxChanges( const C_AnimationLayer& newLayer, const C_AnimationLayer& oldLayer );
};
#ifdef CLIENT_DLL
#define CAnimationLayer C_AnimationLayer
#endif
inline C_AnimationLayer::C_AnimationLayer()
{
#ifdef CLIENT_DLL
m_pOwner = NULL;
m_nInvalidatePhysicsBits = 0;
#endif
m_pDispatchedStudioHdr = NULL;
m_nDispatchedSrc = ACT_INVALID;
m_nDispatchedDst = ACT_INVALID;
Reset();
}
#ifdef GAME_DLL
inline void C_AnimationLayer::SetSequence( int nSequence )
{
m_nSequence = nSequence;
}
inline void C_AnimationLayer::SetCycle( float flCycle )
{
m_flCycle = flCycle;
}
inline void C_AnimationLayer::SetWeight( float flWeight )
{
m_flWeight = flWeight;
}
#endif // GAME_DLL
FORCEINLINE void C_AnimationLayer::SetPrevCycle( float flPrevCycle )
{
m_flPrevCycle = flPrevCycle;
}
FORCEINLINE void C_AnimationLayer::SetPlaybackRate( float flPlaybackRate )
{
m_flPlaybackRate = flPlaybackRate;
}
FORCEINLINE void C_AnimationLayer::SetWeightDeltaRate( float flDelta )
{
m_flWeightDeltaRate = flDelta;
}
FORCEINLINE int C_AnimationLayer::GetSequence( ) const
{
return m_nSequence;
}
FORCEINLINE float C_AnimationLayer::GetCycle( ) const
{
return m_flCycle;
}
FORCEINLINE float C_AnimationLayer::GetPrevCycle( ) const
{
return m_flPrevCycle;
}
FORCEINLINE float C_AnimationLayer::GetPlaybackRate( ) const
{
return m_flPlaybackRate;
}
FORCEINLINE float C_AnimationLayer::GetWeight( ) const
{
return m_flWeight;
}
FORCEINLINE float C_AnimationLayer::GetWeightDeltaRate( ) const
{
return m_flWeightDeltaRate;
}
FORCEINLINE int C_AnimationLayer::GetOrder() const
{
return m_nOrder;
}
inline float C_AnimationLayer::GetFadeout( float flCurTime )
{
float s;
if (m_flLayerFadeOuttime <= 0.0f)
{
s = 0;
}
else
{
// blend in over 0.2 seconds
s = 1.0 - (flCurTime - m_flLayerAnimtime) / m_flLayerFadeOuttime;
if (s > 0 && s <= 1.0)
{
// do a nice spline curve
s = 3 * s * s - 2 * s * s * s;
}
else if ( s > 1.0f )
{
// Shouldn't happen, but maybe curtime is behind animtime?
s = 1.0f;
}
}
return s;
}
#ifdef CLIENT_DLL
FORCEINLINE int C_AnimationLayer::GetInvalidatePhysicsBits() const
{
return m_nInvalidatePhysicsBits;
}
#endif
inline C_AnimationLayer LoopingLerp( float flPercent, C_AnimationLayer& from, C_AnimationLayer& to )
{
#ifdef CLIENT_DLL
Assert( from.GetOwner() == to.GetOwner() );
#endif
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = LoopingLerp( flPercent, (float)from.m_flCycle, (float)to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
#ifdef CLIENT_DLL
output.SetOwner( to.GetOwner() );
#endif
return output;
}
inline C_AnimationLayer Lerp( float flPercent, const C_AnimationLayer& from, const C_AnimationLayer& to )
{
#ifdef CLIENT_DLL
Assert( from.GetOwner() == to.GetOwner() );
#endif
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = Lerp( flPercent, from.m_flCycle, to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
#ifdef CLIENT_DLL
output.SetOwner( to.GetOwner() );
#endif
return output;
}
inline int CheckForSequenceBoxChanges( const C_AnimationLayer& newLayer, const C_AnimationLayer& oldLayer )
{
int nChangeFlags = 0;
bool bOldIsZero = ( oldLayer.GetWeight() == 0.0f );
bool bNewIsZero = ( newLayer.GetWeight() == 0.0f );
if ( ( newLayer.GetSequence() != oldLayer.GetSequence() ) ||
( bNewIsZero != bOldIsZero ) )
{
nChangeFlags |= SEQUENCE_CHANGED | BOUNDS_CHANGED;
}
if ( newLayer.GetCycle() != oldLayer.GetCycle() )
{
nChangeFlags |= ANIMATION_CHANGED;
}
if ( newLayer.GetOrder() != oldLayer.GetOrder() )
{
nChangeFlags |= BOUNDS_CHANGED;
}
return nChangeFlags;
}
inline C_AnimationLayer LoopingLerp_Hermite( const C_AnimationLayer& current, float flPercent, C_AnimationLayer& prev, C_AnimationLayer& from, C_AnimationLayer& to )
{
#ifdef CLIENT_DLL
Assert( prev.GetOwner() == from.GetOwner() );
Assert( from.GetOwner() == to.GetOwner() );
#endif
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = LoopingLerp_Hermite( (float)current.m_flCycle, flPercent, (float)prev.m_flCycle, (float)from.m_flCycle, (float)to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
#ifdef CLIENT_DLL
output.SetOwner( to.GetOwner() );
output.m_nInvalidatePhysicsBits = CheckForSequenceBoxChanges( output, current );
#endif
return output;
}
// YWB: Specialization for interpolating euler angles via quaternions...
inline C_AnimationLayer Lerp_Hermite( const C_AnimationLayer& current, float flPercent, const C_AnimationLayer& prev, const C_AnimationLayer& from, const C_AnimationLayer& to )
{
#ifdef CLIENT_DLL
Assert( prev.GetOwner() == from.GetOwner() );
Assert( from.GetOwner() == to.GetOwner() );
#endif
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = Lerp_Hermite( (float)current.m_flCycle, flPercent, (float)prev.m_flCycle, (float)from.m_flCycle, (float)to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
#ifdef CLIENT_DLL
output.SetOwner( to.GetOwner() );
output.m_nInvalidatePhysicsBits = CheckForSequenceBoxChanges( output, current );
#endif
return output;
}
inline void Lerp_Clamp( C_AnimationLayer &val )
{
Lerp_Clamp( val.m_nSequence );
Lerp_Clamp( val.m_flCycle );
Lerp_Clamp( val.m_flPrevCycle );
Lerp_Clamp( val.m_flWeight );
Lerp_Clamp( val.m_nOrder );
Lerp_Clamp( val.m_flLayerAnimtime );
Lerp_Clamp( val.m_flLayerFadeOuttime );
}
#endif // ANIMATIONLAYER_H

View File

@@ -0,0 +1,129 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "baseanimatedtextureproxy.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "materialsystem/itexture.h"
#include "tier1/keyvalues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Constructor, destructor:
//-----------------------------------------------------------------------------
CBaseAnimatedTextureProxy::CBaseAnimatedTextureProxy()
{
Cleanup();
}
CBaseAnimatedTextureProxy::~CBaseAnimatedTextureProxy()
{
Cleanup();
}
//-----------------------------------------------------------------------------
// Initialization, shutdown
//-----------------------------------------------------------------------------
bool CBaseAnimatedTextureProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pAnimatedTextureVarName = pKeyValues->GetString( "animatedTextureVar" );
if( !pAnimatedTextureVarName )
return false;
bool foundVar;
m_AnimatedTextureVar = pMaterial->FindVar( pAnimatedTextureVarName, &foundVar, false );
if( !foundVar )
return false;
char const* pAnimatedTextureFrameNumVarName = pKeyValues->GetString( "animatedTextureFrameNumVar" );
if( !pAnimatedTextureFrameNumVarName )
return false;
m_AnimatedTextureFrameNumVar = pMaterial->FindVar( pAnimatedTextureFrameNumVarName, &foundVar, false );
if( !foundVar )
return false;
m_FrameRate = pKeyValues->GetFloat( "animatedTextureFrameRate", 15 );
m_WrapAnimation = !pKeyValues->GetInt( "animationNoWrap", 0 );
return true;
}
void CBaseAnimatedTextureProxy::Cleanup()
{
m_AnimatedTextureVar = NULL;
m_AnimatedTextureFrameNumVar = NULL;
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CBaseAnimatedTextureProxy::OnBind( void *pEntity )
{
Assert ( m_AnimatedTextureVar );
if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
{
return;
}
ITexture *pTexture;
pTexture = m_AnimatedTextureVar->GetTextureValue();
int numFrames = pTexture->GetNumAnimationFrames();
if ( numFrames <= 0 )
{
Assert( !"0 frames in material calling animated texture proxy" );
return;
}
// NOTE: Must not use relative time based methods here
// because the bind proxy can be called many times per frame.
// Prevent multiple Wrap callbacks to be sent for no wrap mode
float startTime = GetAnimationStartTime(pEntity);
float deltaTime = gpGlobals->curtime - startTime;
float prevTime = deltaTime - gpGlobals->frametime;
// Clamp..
if (deltaTime < 0.0f)
deltaTime = 0.0f;
if (prevTime < 0.0f)
prevTime = 0.0f;
float frame = m_FrameRate * deltaTime;
float prevFrame = m_FrameRate * prevTime;
int intFrame = ((int)frame) % numFrames;
int intPrevFrame = ((int)prevFrame) % numFrames;
// Report wrap situation...
if (intPrevFrame > intFrame)
{
if (m_WrapAnimation)
{
AnimationWrapped( pEntity );
}
else
{
// Only sent the wrapped message once.
// when we're in non-wrapping mode
if (prevFrame < numFrames)
AnimationWrapped( pEntity );
intFrame = numFrames - 1;
}
}
m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
}
IMaterial *CBaseAnimatedTextureProxy::GetMaterial()
{
return m_AnimatedTextureVar->GetOwningMaterial();
}

View File

@@ -0,0 +1,47 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BASEANIMATEDTEXTUREPROXY
#define BASEANIMATEDTEXTUREPROXY
#include "materialsystem/imaterialproxy.h"
class IMaterial;
class IMaterialVar;
#pragma warning (disable : 4100)
class CBaseAnimatedTextureProxy : public IMaterialProxy
{
public:
CBaseAnimatedTextureProxy();
virtual ~CBaseAnimatedTextureProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
virtual IMaterial *GetMaterial();
protected:
// derived classes must implement this; it returns the time
// that the animation began
virtual float GetAnimationStartTime( void* pBaseEntity ) = 0;
// Derived classes may implement this if they choose;
// this method is called whenever the animation wraps...
virtual void AnimationWrapped( void* pBaseEntity ) {}
protected:
void Cleanup();
IMaterialVar *m_AnimatedTextureVar;
IMaterialVar *m_AnimatedTextureFrameNumVar;
float m_FrameRate;
bool m_WrapAnimation;
};
#endif // BASEANIMATEDTEXTUREPROXY

View File

@@ -0,0 +1,175 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation for CBaseClientRenderTargets class.
// Provides Init functions for common render textures used by the engine.
// Mod makers can inherit from this class, and call the Create functions for
// only the render textures the want for their mod.
//=============================================================================//
#include "cbase.h"
#include "baseclientrendertargets.h" // header
#include "materialsystem/imaterialsystemhardwareconfig.h" // Hardware config checks
#include "materialsystem/itexture.h" // Hardware config checks
#include "tier0/icommandline.h"
#ifdef GAMEUI_UISYSTEM2_ENABLED
#include "gameui.h"
#endif
#include "c_env_cascade_light.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
ConVar cl_disable_water_render_targets( "cl_disable_water_render_targets", "0" );
ITexture* CBaseClientRenderTargets::CreateWaterReflectionTexture( IMaterialSystem* pMaterialSystem, int iSize )
{
iSize = CommandLine()->ParmValue( "-reflectionTextureSize", iSize );
#if defined( PORTAL )
return pMaterialSystem->CreateNamedMultiRenderTargetTexture(
"_rt_WaterReflection",
iSize, iSize, RT_SIZE_NO_CHANGE,
pMaterialSystem->GetBackBufferFormat(),
// Force separate depth buffer for recursive water reflection views, since using the default depth buffer
// will clear depth in the upper left hand <512,512> corner of the screen causing translucent renderables to
// render on top of closer geometry.
MATERIAL_RT_DEPTH_SEPARATE,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
CREATERENDERTARGETFLAGS_HDR );
#else
return pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_WaterReflection",
iSize, iSize, RT_SIZE_PICMIP,
pMaterialSystem->GetBackBufferFormat(),
MATERIAL_RT_DEPTH_SHARED,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
CREATERENDERTARGETFLAGS_HDR );
#endif
}
ITexture* CBaseClientRenderTargets::CreateWaterRefractionTexture( IMaterialSystem* pMaterialSystem, int iSize )
{
iSize = CommandLine()->ParmValue( "-reflectionTextureSize", iSize );
#if defined( PORTAL )
return pMaterialSystem->CreateNamedMultiRenderTargetTexture(
"_rt_WaterRefraction",
iSize, iSize, RT_SIZE_NO_CHANGE,
// This is different than reflection because it has to have alpha for fog factor.
IMAGE_FORMAT_RGBA8888,
// Force separate depth buffer for recursive water reflection views, since using the default depth buffer
// will clear depth in the upper left hand <512,512> corner of the screen causing translucent renderables to
// render on top of closer geometry.
//
// EDIT: on consoles it doesn't matter for Portal 2 because we never use refraction anyways...we always opt for cheaper translucent water. Save memory instead.
// @TODO: get rid of this buffer entirely on consoles
IsGameConsole() ? MATERIAL_RT_DEPTH_SHARED : MATERIAL_RT_DEPTH_SEPARATE,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
CREATERENDERTARGETFLAGS_HDR );
#else
return pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_WaterRefraction",
iSize, iSize, RT_SIZE_PICMIP,
// This is different than reflection because it has to have alpha for fog factor.
IMAGE_FORMAT_RGBA8888,
MATERIAL_RT_DEPTH_SHARED,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
CREATERENDERTARGETFLAGS_HDR );
#endif
}
ITexture* CBaseClientRenderTargets::CreateCameraTexture( IMaterialSystem* pMaterialSystem, int iSize )
{
iSize = CommandLine()->ParmValue( "-monitorTextureSize", iSize );
return pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_Camera",
iSize, iSize, RT_SIZE_DEFAULT,
pMaterialSystem->GetBackBufferFormat(),
MATERIAL_RT_DEPTH_SHARED,
0,
CREATERENDERTARGETFLAGS_HDR );
}
//-----------------------------------------------------------------------------
// Purpose: Called by the engine in material system init and shutdown.
// Clients should override this in their inherited version, but the base
// is to init all standard render targets for use.
// Input : pMaterialSystem - the engine's material system (our singleton is not yet inited at the time this is called)
// pHardwareConfig - the user hardware config, useful for conditional render target setup
//-----------------------------------------------------------------------------
void CBaseClientRenderTargets::SetupClientRenderTargets( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig, int iWaterTextureSize, int iCameraTextureSize )
{
IMaterialSystem *pSave = materials;
// Make sure our config is loaded before we try to init rendertargets
ConfigureCurrentSystemLevel();
// Water effects
materials = pMaterialSystem; // in case not initted yet for mat system util
g_pMaterialSystem = pMaterialSystem;
g_pMaterialSystemHardwareConfig = pHardwareConfig;
if ( iWaterTextureSize && !cl_disable_water_render_targets.GetBool() )
{
m_WaterReflectionTexture.Init( CreateWaterReflectionTexture( pMaterialSystem, iWaterTextureSize ) );
m_WaterRefractionTexture.Init( CreateWaterRefractionTexture( pMaterialSystem, iWaterTextureSize ) );
}
// mdonofrio - Don't need monitors or flashlight shadows for CS15.
// Still need to initrendertargets for shadowmgr (blob/rtt shadows) - it will skip depth textures if convars set appropriately??
#if !( defined( CSTRIKE15 ) && defined( _PS3 ) )
// Monitors
if ( iCameraTextureSize )
m_CameraTexture.Init( CreateCameraTexture( pMaterialSystem, iCameraTextureSize ) );
#endif
ITexture *pGlintTexture = pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_eyeglint", 32, 32, RT_SIZE_NO_CHANGE, IMAGE_FORMAT_BGRA8888, MATERIAL_RT_DEPTH_NONE );
pGlintTexture->IncrementReferenceCount();
g_CascadeLightManager.InitRenderTargets();
g_pClientShadowMgr->InitRenderTargets();
#ifdef GAMEUI_UISYSTEM2_ENABLED
g_pGameUIGameSystem->InitRenderTargets();
#endif
m_RenderToRTHelperTexture.Init( pMaterialSystem->CreateNamedRenderTargetTextureEx2( "render_to_rt_helper", 512, 512, RT_SIZE_DEFAULT, IMAGE_FORMAT_RGBA8888, MATERIAL_RT_DEPTH_SHARED, TEXTUREFLAGS_SINGLECOPY ) );
materials = pSave;
}
void CBaseClientRenderTargets::InitClientRenderTargets( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig )
{
SetupClientRenderTargets( pMaterialSystem, pHardwareConfig );
}
//-----------------------------------------------------------------------------
// Purpose: Shut down each CTextureReference we created in InitClientRenderTargets.
// Called by the engine in material system shutdown.
// Input : -
//-----------------------------------------------------------------------------
void CBaseClientRenderTargets::ShutdownClientRenderTargets()
{
// Water effects
m_WaterReflectionTexture.Shutdown();
m_WaterRefractionTexture.Shutdown();
// Monitors
m_CameraTexture.Shutdown();
g_pClientShadowMgr->ShutdownRenderTargets();
g_CascadeLightManager.ShutdownRenderTargets();
m_RenderToRTHelperTexture.Shutdown();
}
static CBaseClientRenderTargets g_BaseClientRenderTargets;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CBaseClientRenderTargets, IClientRenderTargets,
CLIENTRENDERTARGETS_INTERFACE_VERSION, g_BaseClientRenderTargets );

View File

@@ -0,0 +1,64 @@
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Has init functions for all the standard render targets used by most games.
// Mods who wish to make their own render targets can inherit from this class
// and in the 'InitClientRenderTargets' interface called by the engine, set up
// their own render targets as well as calling the init functions for various
// common render targets provided by this class.
//
// Note: Unless the client defines a singleton interface by inheriting from
// this class and exposing the singleton instance, these init and shutdown
// functions WILL NOT be called by the engine.
//
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#ifndef CLIENTRENDERTARTETS_H_
#define CLIENTRENDERTARTETS_H_
#ifdef _WIN32
#pragma once
#endif
#include "game/client/iclientrendertargets.h" // base class with interfaces called by the engine
#include "materialsystem/imaterialsystem.h" // for material system classes and interfaces
// Externs
class IMaterialSystem;
class IMaterialSystemHardwareConfig;
class CBaseClientRenderTargets : public IClientRenderTargets
{
// no networked vars
DECLARE_CLASS_GAMEROOT( CBaseClientRenderTargets, IClientRenderTargets );
public:
// Interface called by engine during material system startup.
virtual void InitClientRenderTargets ( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig );
// Shutdown all custom render targets here.
virtual void ShutdownClientRenderTargets ( void );
protected:
void SetupClientRenderTargets( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig, int iWaterTextureSize = 1024, int iCameraTextureSize = 256 );
// Standard render textures used by most mods-- Classes inheriting from
// this can choose to init these or not depending on their needs.
// For reflective and refracting water
CTextureReference m_WaterReflectionTexture;
CTextureReference m_WaterRefractionTexture;
// Used for monitors
CTextureReference m_CameraTexture;
CTextureReference m_RenderToRTHelperTexture;
// Init functions for the common render targets
ITexture* CreateWaterReflectionTexture( IMaterialSystem* pMaterialSystem, int iSize = 1024 );
ITexture* CreateWaterRefractionTexture( IMaterialSystem* pMaterialSystem, int iSize = 1024 );
ITexture* CreateCameraTexture( IMaterialSystem* pMaterialSystem, int iSize = 256 );
};
#endif // CLIENTRENDERTARTETS_H_

1527
game/client/beamdraw.cpp Normal file

File diff suppressed because it is too large Load Diff

165
game/client/beamdraw.h Normal file
View File

@@ -0,0 +1,165 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#if !defined( BEAMDRAW_H )
#define BEAMDRAW_H
#ifdef _WIN32
#pragma once
#endif
#include "materialsystem/imaterial.h"
#include "materialsystem/imesh.h"
#include "mathlib/vector.h"
#include "tier2/beamsegdraw.h"
#include "c_pixel_visibility.h"
#define NOISE_DIVISIONS 128
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct model_t;
struct BeamTrail_t;
//-----------------------------------------------------------------------------
// Purpose: Beams fill out this data structure
// This is also used for rendering
//-----------------------------------------------------------------------------
class Beam_t : public CDefaultClientRenderable
{
public:
Beam_t();
// Methods of IClientRenderable
virtual const Vector& GetRenderOrigin( void );
virtual const QAngle& GetRenderAngles( void );
virtual const matrix3x4_t &RenderableToWorldTransform();
virtual void GetRenderBounds( Vector& mins, Vector& maxs );
virtual bool ShouldDraw( void );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
// Resets the beam state
void Reset();
// Method to computing the bounding box
void ComputeBounds();
// Bounding box...
Vector m_Mins;
Vector m_Maxs;
pixelvis_handle_t *m_queryHandleHalo;
float m_haloProxySize;
// Data is below..
// Next beam in list
Beam_t* next;
// Type of beam
int type;
int flags;
// Control points for the beam
int numAttachments;
Vector attachment[MAX_BEAM_ENTS];
Vector delta;
// 0 .. 1 over lifetime of beam
float t;
float freq;
// Time when beam should die
float die;
float width;
float endWidth;
float fadeLength;
float amplitude;
float life;
// Color
float r, g, b;
float brightness;
// Speed
float speed;
// Animation
float frameRate;
float frame;
int segments;
// Attachment entities for the beam
EHANDLE entity[MAX_BEAM_ENTS];
int attachmentIndex[MAX_BEAM_ENTS];
// Model info
int modelIndex;
int haloIndex;
float haloScale;
int frameCount;
float rgNoise[NOISE_DIVISIONS+1];
// Popcorn trail for beam follows to use
BeamTrail_t* trail;
// for TE_BEAMRINGPOINT
float start_radius;
float end_radius;
// for FBEAM_ONLYNOISEONCE
bool m_bCalculatedNoise;
float m_flHDRColorScale;
};
int ScreenTransform( const Vector& point, Vector& screen );
void DrawSegs( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source, const Vector& delta,
float startWidth, float endWidth, float scale, float freq, float speed, int segments,
int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f );
void DrawTeslaSegs( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source, const Vector& delta,
float startWidth, float endWidth, float scale, float freq, float speed, int segments,
int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f );
void DrawSplineSegs( int noise_divisions, float *prgNoise,
const model_t* beammodel, const model_t* halomodel, float flHaloScale,
float frame, int rendermode, int numAttachments, Vector* attachment,
float startWidth, float endWidth, float scale, float freq, float speed, int segments,
int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f );
void DrawHalo(IMaterial* pMaterial, const Vector& source, float scale, float const* color, float flHDRColorScale = 1.0f );
void BeamDrawHalo( const model_t* spritemodel, float frame, int rendermode, const Vector& source,
float scale, float* color, float flHDRColorScale = 1.0f );
void DrawDisk( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source, const Vector& delta,
float width, float scale, float freq, float speed,
int segments, float* color, float flHDRColorScale = 1.0f );
void DrawCylinder( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source,
const Vector& delta, float width, float scale, float freq,
float speed, int segments, float* color, float flHDRColorScale = 1.0f );
void DrawRing( int noise_divisions, float *prgNoise, void (*pfnNoise)( float *noise, int divs, float scale ),
const model_t* spritemodel, float frame, int rendermode,
const Vector& source, const Vector& delta, float width, float amplitude,
float freq, float speed, int segments, float* color, float flHDRColorScale = 1.0f );
void DrawBeamFollow( const model_t* spritemodel, BeamTrail_t* pHead, int frame, int rendermode, Vector& delta,
Vector& screen, Vector& screenLast, float die, const Vector& source,
int flags, float width, float amplitude, float freq, float* color, float flHDRColorScale = 1.0f );
void DrawBeamQuadratic( const Vector &start, const Vector &control, const Vector &end, float width, const Vector &color, float scrollOffset, float flHDRColorScale = 1.0f );
class CEngineSprite *Draw_SetSpriteTexture( const model_t *pSpriteModel, int frame, int rendermode );
//-----------------------------------------------------------------------------
// Assumes the material has already been bound
//-----------------------------------------------------------------------------
void DrawSprite( const Vector &vecOrigin, float flWidth, float flHeight, color32 color );
#endif // BEAMDRAW_H

View File

@@ -0,0 +1,73 @@
//========== Copyright © 2006, Valve Corporation, All rights reserved. ========
//
// Purpose:
//
//=============================================================================
#ifndef BONETOWORLDARRAY_H
#define BONETOWORLDARRAY_H
#include "tier0/tslist.h"
#if defined( _WIN32 )
#pragma once
#endif
#include "tier0/memdbgon.h" // for _aligned_malloc usage below
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
template <int NUM_ARRAYS>
class CBoneToWorldArrays
{
public:
enum
{
ALIGNMENT = 128,
};
CBoneToWorldArrays()
{
const int SIZE_ARRAY = AlignValue( sizeof(matrix3x4_t) * MAXSTUDIOBONES, ALIGNMENT );
m_pBase = (matrix3x4_t *)_aligned_malloc( SIZE_ARRAY * NUM_ARRAYS, ALIGNMENT );
for ( int i = 0; i < NUM_ARRAYS; i++ )
{
matrix3x4_t *pArray = (matrix3x4_t *)((byte *)m_pBase + SIZE_ARRAY * i);
Assert( (size_t)pArray % ALIGNMENT == 0 );
Free( pArray );
}
}
~CBoneToWorldArrays()
{
_aligned_free( m_pBase );
}
int NumArrays()
{
return NUM_ARRAYS;
}
matrix3x4_t *Alloc( bool bBlock = true )
{
TSLNodeBase_t *p;
while ( ( p = m_Free.Pop() ) == NULL && bBlock )
{
ThreadPause();
}
return (matrix3x4_t *)p;
}
void Free( matrix3x4_t *p )
{
m_Free.Push( (TSLNodeBase_t *) p );
}
private:
CTSListBase m_Free;
matrix3x4_t *m_pBase;
};
#include "tier0/memdbgoff.h" // for _aligned_malloc usage above
#endif // BONETOWORLDARRAY_H

View File

@@ -0,0 +1,85 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#include "buildrenderables_PS3.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CPS3BuildRenderablesJob g_BuildRenderablesJob;
CPS3BuildRenderablesJob* g_pBuildRenderablesJob = &g_BuildRenderablesJob;
job_buildrenderables::JobDescriptor_t g_buildRenderablesJobDescriptor ALIGN128;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPS3BuildRenderablesJob::Init( void )
{
m_bEnabled = false;
m_buildRenderablesJobData.EnsureCapacity(MAX_CONCURRENT_BUILDVIEWS);
m_buildRenderablesJobCount = 0;
// requires a SPURS instance, so register with VJobs
if( g_pVJobs )
{
g_pVJobs->Register( this );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPS3BuildRenderablesJob::Shutdown()
{
g_pVJobs->Unregister( this );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPS3BuildRenderablesJob::OnVjobsInit()
{
m_bEnabled = true;
g_buildRenderablesJobDescriptor.header = *m_pRoot->m_pJobBuildRenderables;
g_buildRenderablesJobDescriptor.header.useInOutBuffer = 1;
g_buildRenderablesJobDescriptor.header.sizeStack = (64*1024)/16;
g_buildRenderablesJobDescriptor.header.sizeInOrInOut = 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPS3BuildRenderablesJob::OnVjobsShutdown()
{
m_bEnabled = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
PS3BuildRenderablesJobData *CPS3BuildRenderablesJob::GetJobData( int job )
{
return &m_buildRenderablesJobData[ job ];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------

View File

@@ -0,0 +1,188 @@
//========= Copyright © Valve Corporation, All rights reserved. ============//
#ifndef BUILDRENDERABLES_PS3_HDR
#define BUILDRENDERABLES_PS3_HDR
#if defined( _PS3 )
#if defined(__SPU__)
#include "ps3/spu_job_shared.h"
#else
#include "utlvector.h"
#include "vjobs/root.h"
#include <vjobs_interface.h>
#include <ps3/vjobutils.h>
#include <ps3/vjobutils_shared.h>
#include "vjobs/jobparams_shared.h"
#include "ClientLeafSystem.h"
#endif // __SPU__
// copied from bspfile.h, do we need the rest of that file?
#define MAX_MAP_AREAS 256
// round up to next 16B boundary, then add 16B
#define ROUNDUPTONEXT16B( a ) (0x10 + ((a) + (0x10 - ((a)%0x10))))
struct ALIGN128 buildRenderablesJob_SPU
{
int debugJob; // for dynamic switching of DebuggerBreak
uint32 pEA_debugRenderable;
SetupRenderInfo_t info;
void* pEA_worldbrush_leafs; // mleaf_t *
void* pEA_detailObjects; // CDetailModel *, g_detailObjectSystem->m_DetailObjects.Base()
void* pEA_detailObjects_origin; // CDetailModel *, g_detailObjectSystem->m_DetailObjects.Base()
// this is ptr to detailmodel.m_origin, so we don't have to fetch the whole thing, stride can this still be sizeof(CDetailModel) to access elements
int detailObjects_count; // g_detailObjectSystem->m_DetailObjects.count()
Vector viewOrigin; // g_vecCurrentRenderOrigin, CurrentViewOrigin()
int strideCDetailModel;
void* pEA_clientRenderablesList_RenderGroups; // ptr to CEntry m_REnderGroups[RENDER_GROUP_COUNT][MAX_GROUP_ENTITIRES]
void* pEA_clientRenderablesList_RenderGroupCounts; // ptr to int m_REnderGroupCounts[RENDER_GROUP_COUNT]
DistanceFadeInfo_t info_mpRenderList_mDetailFade;
int maxCount;
int buildFastReflectionRenderables; // r_fastreflectionfastpath
//
void* pEA_frustums[MAX_MAP_AREAS]; // Frustum_t *
int numAreaFrustums;
// detailobjectsystem info
float flFactor;
float flDetailFadeStart;
float flDetailFadeEnd;
// translucency
float flMinLevelFadeArea;
float flMaxLevelFadeArea;
float flMinGlobalFadeArea;
float flMaxGlobalFadeArea;
float flGlobalDistFadeScale;
int bComputeScreenFade;
ScreenSizeComputeInfo_t screensizecomputeinfo;
int shouldDrawDetailObjects;
// utl
void* pEA_clientleafsystem_mleaf;
void* pEA_renderablesLIST; // renderable_LIST_t *
void* pEA_renderablesInLeafLIST; // renderableInLeaf_LIST_t *
int renderablesHeadIdx;
// extract
int clientleafsystem_alternateSortCount; //
int clientleafsystem_drawStaticProps; //
int clientleafsystem_disableShadowDepthCount;
// convar copies
int r_drawallrenderables;
int r_portaltestents_AND_NOTr_portalsopenall;
int r_occlusion;
// gpGlobals
int frameCount;
float curTime;
// CSM View
bool bCSMView;
bool bDisableCSMCulling;
bool bShadowEntities;
bool bShadowStaticProps;
bool bShadowSprites;
bool bIgnoreDisableShadowDepthRendering;
int cascadeID;
int debugViewID;
int debugViewID_DEBUG;
// OUT
void* ppEA_Renderables; // RenderableInfo **
void* pEA_RenderablesCount; // int *
void* pEA_RLInfo; // BuildRenderListInfo_t *
void* pEA_DetailRenderables; // DetailRenderableInfo_t *
void* pEA_DetailRenderablesCount; // int *
enum
{
MAX_GROUP_ENTITIES = 4096,
MAX_BONE_SETUP_DEPENDENCY = 64,
};
} ALIGN128_POST;
#if !defined( __SPU__ )
struct ALIGN128 PS3BuildRenderablesJobData
{
public:
job_buildrenderables::JobDescriptor_t jobDescriptor ALIGN128;
// src, SPU in only, going to SPU at start of job
buildRenderablesJob_SPU buildRenderablesJobSPU;
} ALIGN128_POST;
class CPS3BuildRenderablesJob : public VJobInstance
{
public:
CPS3BuildRenderablesJob()
{
}
~CPS3BuildRenderablesJob()
{
Shutdown();
}
void OnVjobsInit( void ); // gets called after m_pRoot was created and assigned
void OnVjobsShutdown( void ); // gets called before m_pRoot is about to be destructed and NULL'ed
void Init( void );
void Shutdown( void );
void ResetBoneJobs( void );
PS3BuildRenderablesJobData *GetJobData( int job );
CUtlVector<PS3BuildRenderablesJobData> m_buildRenderablesJobData;
private:
int m_buildRenderablesJobCount;
int m_buildRenderablesJobNextSPURSPort;
bool m_bEnabled;
};
extern IVJobs * g_pVJobs;
extern CPS3BuildRenderablesJob* g_pBuildRenderablesJob;
extern job_buildrenderables::JobDescriptor_t g_buildRenderablesJobDescriptor ALIGN128;
#endif // #if !defined(__SPU__)
#endif // if !defined(_PS3)
#endif

View File

@@ -0,0 +1,169 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if 0
class C_AI_BaseHumanoid : public C_AI_BaseNPC
{
public:
DECLARE_CLASS( C_AI_BaseHumanoid, C_AI_BaseNPC );
DECLARE_CLIENTCLASS();
C_AI_BaseHumanoid();
// model specific
virtual bool Interpolate( float currentTime );
virtual void StandardBlendingRules( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], float currentTime, int boneMask );
float m_recanimtime[3];
AnimationLayer_t m_Layer[4][3];
};
C_AI_BaseHumanoid::C_AI_BaseHumanoid()
{
memset(m_recanimtime, 0, sizeof(m_recanimtime));
memset(m_Layer, 0, sizeof(m_Layer));
}
BEGIN_RECV_TABLE_NOBASE(AnimationLayer_t, DT_Animationlayer)
RecvPropInt(RECVINFO_NAME(nSequence,sequence)),
RecvPropFloat(RECVINFO_NAME(flCycle,cycle)),
RecvPropFloat(RECVINFO_NAME(flPlaybackrate,playbackrate)),
RecvPropFloat(RECVINFO_NAME(flWeight,weight))
END_RECV_TABLE()
IMPLEMENT_CLIENTCLASS_DT(C_AI_BaseHumanoid, DT_BaseHumanoid, CAI_BaseHumanoid)
/*
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[0][2],m_Layer0),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[1][2],m_Layer1),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[2][2],m_Layer2),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[3][2],m_Layer3),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
*/
RecvPropInt(RECVINFO_NAME(m_Layer[0][2].nSequence,sequence0)),
RecvPropFloat(RECVINFO_NAME(m_Layer[0][2].flCycle,cycle0)),
RecvPropFloat(RECVINFO_NAME(m_Layer[0][2].flPlaybackrate,playbackrate0)),
RecvPropFloat(RECVINFO_NAME(m_Layer[0][2].flWeight,weight0)),
RecvPropInt(RECVINFO_NAME(m_Layer[1][2].nSequence,sequence1)),
RecvPropFloat(RECVINFO_NAME(m_Layer[1][2].flCycle,cycle1)),
RecvPropFloat(RECVINFO_NAME(m_Layer[1][2].flPlaybackrate,playbackrate1)),
RecvPropFloat(RECVINFO_NAME(m_Layer[1][2].flWeight,weight1)),
RecvPropInt(RECVINFO_NAME(m_Layer[2][2].nSequence,sequence2)),
RecvPropFloat(RECVINFO_NAME(m_Layer[2][2].flCycle,cycle2)),
RecvPropFloat(RECVINFO_NAME(m_Layer[2][2].flPlaybackrate,playbackrate2)),
RecvPropFloat(RECVINFO_NAME(m_Layer[2][2].flWeight,weight2)),
RecvPropInt(RECVINFO_NAME(m_Layer[3][2].nSequence,sequence3)),
RecvPropFloat(RECVINFO_NAME(m_Layer[3][2].flCycle,cycle3)),
RecvPropFloat(RECVINFO_NAME(m_Layer[3][2].flPlaybackrate,playbackrate3)),
RecvPropFloat(RECVINFO_NAME(m_Layer[3][2].flWeight,weight3))
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_AI_BaseHumanoid::StandardBlendingRules( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], float currentTime, int boneMask )
{
VPROF( "C_AI_BaseHumanoid::StandardBlendingRules" );
BaseClass::StandardBlendingRules( pStudioHdr, pos, q, currentTime, boneMask );
if ( !hdr )
{
return;
}
#if 0
float poseparam[MAXSTUDIOPOSEPARAM];
if ( GetSequence() >= hdr->numseq )
{
SetSequence( 0 );
}
// interpolate pose parameters
for (int i = 0; i < hdr->numposeparameters; i++)
{
poseparam[ i ] = m_flPoseParameter[i];
}
// build root animation
float fCycle = GetCycle();
CalcPose( hdr, NULL, pos, q, GetSequence(), fCycle, poseparam );
// debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 0, "%30s %6.2f : %6.2f", hdr->pSeqdesc( GetSequence() )->pszLabel( ), fCycle, 1.0 );
MaintainSequenceTransitions( hdr, fCycle, poseparam, pos, q, boneMask );
#if 1
for (i = 0; i < 4; i++)
{
if (m_Layer[i][2].nSequence != m_Layer[i][1].nSequence)
{
if (m_Layer[i][2].flWeight > 0.5) m_Layer[i][1].flWeight = 1.0; else m_Layer[i][1].flWeight = 0;
}
}
#endif
#if 1
for (i = 0; i < 4; i++)
{
Vector pos2[MAXSTUDIOBONES];
Quaternion q2[MAXSTUDIOBONES];
float fWeight = m_Layer[i][1].flWeight * (1 - dadt) + m_Layer[i][2].flWeight * dadt;
/*
debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), -i - 1, 0,
"%2d %6.2f %6.2f : %2d %6.2f %6.2f : %2d %6.2f %6.2f",
m_Layer[i][0].nSequence, m_Layer[i][0].flCycle, m_Layer[i][0].flWeight,
m_Layer[i][1].nSequence, m_Layer[i][1].flCycle, m_Layer[i][1].flWeight,
m_Layer[i][2].nSequence, m_Layer[i][2].flCycle, m_Layer[i][2].flWeight );
*/
if (fWeight > 0)
{
mstudioseqdesc_t *pseqdesc = hdr->pSeqdesc( m_Layer[i][2].nSequence );
float fCycle = m_Layer[i][2].flCycle;
// UNDONE: Do IK here.
CalcPose( hdr, NULL, pos2, q2, m_Layer[i][2].nSequence, fCycle, poseparam );
if (fWeight > 1)
fWeight = 1;
SlerpBones( hdr, q, pos, pseqdesc, q2, pos2, fWeight );
engine->Con_NPrintf( 10 + i, "%30s %6.2f : %6.2f", pseqdesc->pszLabel(), fCycle, fWeight );
}
else
{
engine->Con_NPrintf( 10 + i, "%30s %6.2f : %6.2f", " ", 0, 0 );
}
}
#endif
CIKContext auto_ik;
auto_ik.Init( hdr, GetRenderAngles(), GetRenderOrigin(), gpGlobals->curtime );
CalcAutoplaySequences( hdr, &auto_ik, pos, q, poseparam, boneMask, currentTime );
float controllers[MAXSTUDIOBONECTRLS];
GetBoneControllers(controllers);
CalcBoneAdj( hdr, pos, q, controllers );
#endif
}
#endif

View File

@@ -0,0 +1,199 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_ai_basenpc.h"
#include "engine/ivdebugoverlay.h"
#if defined( HL2_DLL ) || defined( HL2_EPISODIC )
#include "c_basehlplayer.h"
#endif
#include "death_pose.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define PING_MAX_TIME 2.0
//
// Global accessors for GLaDOS for lighted mouth proxy
//
CHandle<C_BaseAnimating> g_GLaDOSActor;
void SetGLaDOSActor( C_BaseAnimating *pActor )
{
g_GLaDOSActor = pActor;
}
C_BaseAnimating *GetGLaDOSActor( void )
{
return g_GLaDOSActor;
}
IMPLEMENT_CLIENTCLASS_DT( C_AI_BaseNPC, DT_AI_BaseNPC, CAI_BaseNPC )
RecvPropInt( RECVINFO( m_lifeState ) ),
RecvPropBool( RECVINFO( m_bPerformAvoidance ) ),
RecvPropBool( RECVINFO( m_bIsMoving ) ),
RecvPropBool( RECVINFO( m_bFadeCorpse ) ),
RecvPropInt( RECVINFO ( m_iDeathPose) ),
RecvPropInt( RECVINFO( m_iDeathFrame) ),
RecvPropInt( RECVINFO( m_iSpeedModRadius ) ),
RecvPropInt( RECVINFO( m_iSpeedModSpeed ) ),
RecvPropInt( RECVINFO( m_bSpeedModActive ) ),
RecvPropBool( RECVINFO( m_bImportanRagdoll ) ),
RecvPropFloat( RECVINFO( m_flTimePingEffect ) ),
END_RECV_TABLE()
extern ConVar cl_npc_speedmod_intime;
bool NPC_IsImportantNPC( C_BaseAnimating *pAnimating )
{
C_AI_BaseNPC *pBaseNPC = pAnimating->MyNPCPointer();
if ( pBaseNPC == NULL )
return false;
return pBaseNPC->ImportantRagdoll();
}
C_AI_BaseNPC::C_AI_BaseNPC()
{
}
//-----------------------------------------------------------------------------
// Makes ragdolls ignore npcclip brushes
//-----------------------------------------------------------------------------
unsigned int C_AI_BaseNPC::PhysicsSolidMaskForEntity( void ) const
{
// This allows ragdolls to move through npcclip brushes
if ( !IsRagdoll() )
{
return MASK_NPCSOLID;
}
return MASK_SOLID;
}
void C_AI_BaseNPC::ClientThink( void )
{
BaseClass::ClientThink();
#ifdef HL2_DLL
C_BaseHLPlayer *pPlayer = dynamic_cast<C_BaseHLPlayer*>( C_BasePlayer::GetLocalPlayer() );
if ( ShouldModifyPlayerSpeed() == true )
{
if ( pPlayer )
{
float flDist = (GetAbsOrigin() - pPlayer->GetAbsOrigin()).LengthSqr();
if ( flDist <= GetSpeedModifyRadius() )
{
if ( pPlayer->m_hClosestNPC )
{
if ( pPlayer->m_hClosestNPC != this )
{
float flDistOther = (pPlayer->m_hClosestNPC->GetAbsOrigin() - pPlayer->GetAbsOrigin()).Length();
//If I'm closer than the other NPC then replace it with myself.
if ( flDist < flDistOther )
{
pPlayer->m_hClosestNPC = this;
pPlayer->m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_intime.GetFloat();
}
}
}
else
{
pPlayer->m_hClosestNPC = this;
pPlayer->m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_intime.GetFloat();
}
}
}
}
#endif // HL2_DLL
#ifdef HL2_EPISODIC
C_BaseHLPlayer *pPlayer = dynamic_cast<C_BaseHLPlayer*>( C_BasePlayer::GetLocalPlayer() );
if ( pPlayer && m_flTimePingEffect > gpGlobals->curtime )
{
float fPingEffectTime = m_flTimePingEffect - gpGlobals->curtime;
if ( fPingEffectTime > 0.0f )
{
Vector vRight, vUp;
Vector vMins, vMaxs;
float fFade;
if( fPingEffectTime <= 1.0f )
{
fFade = 1.0f - (1.0f - fPingEffectTime);
}
else
{
fFade = 1.0f;
}
GetRenderBounds( vMins, vMaxs );
AngleVectors (pPlayer->GetAbsAngles(), NULL, &vRight, &vUp );
Vector p1 = GetAbsOrigin() + vRight * vMins.x + vUp * vMins.z;
Vector p2 = GetAbsOrigin() + vRight * vMaxs.x + vUp * vMins.z;
Vector p3 = GetAbsOrigin() + vUp * vMaxs.z;
int r = 0 * fFade;
int g = 255 * fFade;
int b = 0 * fFade;
debugoverlay->AddLineOverlay( p1, p2, r, g, b, true, 0.05f );
debugoverlay->AddLineOverlay( p2, p3, r, g, b, true, 0.05f );
debugoverlay->AddLineOverlay( p3, p1, r, g, b, true, 0.05f );
}
}
#endif
}
void C_AI_BaseNPC::OnDataChanged( DataUpdateType_t type )
{
BaseClass::OnDataChanged( type );
// Make sure we're thinking
if ( type == DATA_UPDATE_CREATED )
{
// If this is the GLaDOS actor, then setup a handle to it, globally
if ( FStrEq( STRING( GetEntityName() ), "@glados" ) || FStrEq( STRING( GetEntityName() ), "@actor_potatos" ) )
{
SetGLaDOSActor( this );
MouthInfo().ActivateEnvelope();
}
}
if ( ( ShouldModifyPlayerSpeed() == true ) || ( m_flTimePingEffect > gpGlobals->curtime ) )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
void C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4a_t *pDeltaBones0, matrix3x4a_t *pDeltaBones1, matrix3x4a_t *pCurrentBones, float boneDt )
{
ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt );
GetRagdollCurSequenceWithDeathPose( this, pDeltaBones1, gpGlobals->curtime, m_iDeathPose, m_iDeathFrame );
float ragdollCreateTime = PhysGetSyncCreateTime();
if ( ragdollCreateTime != gpGlobals->curtime )
{
// The next simulation frame begins before the end of this frame
// so initialize the ragdoll at that time so that it will reach the current
// position at curtime. Otherwise the ragdoll will simulate forward from curtime
// and pop into the future a bit at this point of transition
ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime );
}
else
{
SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime );
}
}

View File

@@ -0,0 +1,61 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_AI_BASENPC_H
#define C_AI_BASENPC_H
#ifdef _WIN32
#pragma once
#endif
#include "c_basecombatcharacter.h"
// NOTE: MOved all controller code into c_basestudiomodel
class C_AI_BaseNPC : public C_BaseCombatCharacter
{
DECLARE_CLASS( C_AI_BaseNPC, C_BaseCombatCharacter );
public:
DECLARE_CLIENTCLASS();
C_AI_BaseNPC();
virtual unsigned int PhysicsSolidMaskForEntity( void ) const;
virtual bool IsNPC( void ) { return true; }
bool IsMoving( void ){ return m_bIsMoving; }
bool ShouldAvoidObstacle( void ){ return m_bPerformAvoidance; }
virtual bool AddRagdollToFadeQueue( void ) { return m_bFadeCorpse; }
virtual void GetRagdollInitBoneArrays( matrix3x4a_t *pDeltaBones0, matrix3x4a_t *pDeltaBones1, matrix3x4a_t *pCurrentBones, float boneDt );
int GetDeathPose( void ) { return m_iDeathPose; }
bool ShouldModifyPlayerSpeed( void ) { return m_bSpeedModActive; }
int GetSpeedModifyRadius( void ) { return m_iSpeedModRadius; }
int GetSpeedModifySpeed( void ) { return m_iSpeedModSpeed; }
void ClientThink( void );
void OnDataChanged( DataUpdateType_t type );
bool ImportantRagdoll( void ) { return m_bImportanRagdoll; }
private:
C_AI_BaseNPC( const C_AI_BaseNPC & ); // not defined, not accessible
float m_flTimePingEffect;
int m_iDeathPose;
int m_iDeathFrame;
int m_iSpeedModRadius;
int m_iSpeedModSpeed;
bool m_bPerformAvoidance;
bool m_bIsMoving;
bool m_bFadeCorpse;
bool m_bSpeedModActive;
bool m_bImportanRagdoll;
};
#endif // C_AI_BASENPC_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef C_BASEANIMATINGOVERLAY_H
#define C_BASEANIMATINGOVERLAY_H
#pragma once
#include "c_baseanimating.h"
#include "toolframework/itoolframework.h"
// For shared code.
#define CBaseAnimatingOverlay C_BaseAnimatingOverlay
class C_BaseAnimatingOverlay : public C_BaseAnimating
{
DECLARE_CLASS( C_BaseAnimatingOverlay, C_BaseAnimating );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
// Inherited from C_BaseAnimating
public:
virtual C_BaseAnimatingOverlay *GetBaseAnimatingOverlay() { return this; }
virtual void AccumulateLayers( IBoneSetup &boneSetup, BoneVector pos[], BoneQuaternion q[], float currentTime );
virtual void DoAnimationEvents( CStudioHdr *pStudioHdr );
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
virtual CStudioHdr *OnNewModel();
virtual bool Interpolate( float flCurrentTime );
#if defined( _PS3 )
virtual void AccumulateLayers_AddPoseCalls( IBoneSetup_PS3 &boneSetup, BoneVector pos[], BoneQuaternion q[], float currentTime );
#endif
public:
enum
{
MAX_OVERLAYS = 15,
};
C_BaseAnimatingOverlay();
CAnimationLayer* GetAnimOverlay( int i, bool bUseOrder = true );
void SetNumAnimOverlays( int num ); // This makes sure there is space for this # of layers.
int GetNumAnimOverlays() const;
void SetOverlayPrevEventCycle( int nSlot, float flValue );
void CheckInterpChanges( void );
void CheckForLayerPhysicsInvalidate( void );
virtual bool UpdateDispatchLayer( CAnimationLayer *pLayer, CStudioHdr *pWeaponStudioHdr, int iSequence );
void AccumulateDispatchedLayers( C_BaseAnimatingOverlay *pWeapon, CStudioHdr *pWeaponStudioHdr, IBoneSetup &boneSetup, BoneVector pos[], BoneQuaternion q[], float currentTime );
void RegenerateDispatchedLayers( IBoneSetup &boneSetup, BoneVector pos[], BoneQuaternion q[], float currentTime );
void AccumulateInterleavedDispatchedLayers( C_BaseAnimatingOverlay *pWeapon, IBoneSetup &boneSetup, BoneVector pos[], BoneQuaternion q[], float currentTime, bool bSetupInvisibleWeapon = false );
virtual void NotifyOnLayerChangeSequence( const CAnimationLayer* pLayer, const int nNewSequence ) {};
virtual void NotifyOnLayerChangeWeight( const CAnimationLayer* pLayer, const float flNewWeight ) {};
virtual void NotifyOnLayerChangeCycle( const CAnimationLayer* pLayer, const float flNewCycle ) {};
private:
void CheckForLayerChanges( CStudioHdr *hdr, float currentTime );
CUtlVector < CAnimationLayer > m_AnimOverlay;
CUtlVector < CInterpolatedVar< CAnimationLayer > > m_iv_AnimOverlay;
float m_flOverlayPrevEventCycle[ MAX_OVERLAYS ];
C_BaseAnimatingOverlay( const C_BaseAnimatingOverlay & ); // not defined, not accessible
friend void ResizeAnimationLayerCallback( void *pStruct, int offsetToUtlVector, int len );
};
inline void C_BaseAnimatingOverlay::SetOverlayPrevEventCycle( int nSlot, float flValue )
{
m_flOverlayPrevEventCycle[nSlot] = flValue;
}
EXTERN_RECV_TABLE(DT_BaseAnimatingOverlay);
#endif // C_BASEANIMATINGOVERLAY_H

View File

@@ -0,0 +1,202 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's C_BaseCombatCharacter entity
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basecombatcharacter.h"
#include "c_cs_player.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if defined( CBaseCombatCharacter )
#undef CBaseCombatCharacter
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BaseCombatCharacter::C_BaseCombatCharacter()
{
for ( int i=0; i < m_iAmmo.Count(); i++ )
m_iAmmo.Set( i, 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BaseCombatCharacter::~C_BaseCombatCharacter()
{
}
/*
//-----------------------------------------------------------------------------
// Purpose: Returns the amount of ammunition of the specified type the character's carrying
//-----------------------------------------------------------------------------
int C_BaseCombatCharacter::GetAmmoCount( char *szName ) const
{
return GetAmmoCount( g_pGameRules->GetAmmoDef()->Index(szName) );
}
*/
//-----------------------------------------------------------------------------
// Purpose: Overload our muzzle flash and send it to any actively held weapon
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::DoMuzzleFlash()
{
// Our weapon takes our muzzle flash command
C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
if ( pWeapon )
{
pWeapon->DoMuzzleFlash();
//NOTENOTE: We do not chain to the base here
}
else
{
BaseClass::DoMuzzleFlash();
}
}
void C_BaseCombatCharacter::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// view weapon model cache monitoring
// NOTE: expected to be updated ONLY once per frame for the primary player ONLY!
// the expectation is that there is ONLY one customer that requires view models
// otherwise the lower level code will thrash as it tries to maintain a single player's view model inventory
{
const char *viewWeapons[MAX_WEAPONS];
int nNumViewWeapons = 0;
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
if ( pLocalPlayer == this && !pLocalPlayer->IsObserver() )
{
// want to know what this player's weapon inventory is to keep all of these in cache
for ( int i = 0; i < MAX_WEAPONS; i++ )
{
C_BaseCombatWeapon *pWeapon = GetWeapon( i );
if ( !pWeapon )
continue;
viewWeapons[nNumViewWeapons] = pWeapon->GetViewModel();
nNumViewWeapons++;
}
}
else if ( pLocalPlayer && pLocalPlayer->GetObserverMode() == OBS_MODE_IN_EYE && pLocalPlayer->GetObserverTarget() == this )
{
// once spectating, PURPOSELY only the active view weapon gets tracked
// cycling through spectators is the more common pattern and tracking just the active weapon prevents massive cache thrashing
// otherwise maintaining the observer targets inventories would needlessly thrash the cache as the player rapidly cycles
C_BaseCombatWeapon *pWeapon = pLocalPlayer->GetActiveWeapon();
if ( pWeapon )
{
viewWeapons[nNumViewWeapons] = pWeapon->GetViewModel();
nNumViewWeapons++;
}
}
if ( nNumViewWeapons )
{
// view model weapons are subject to a cache policy that needs to be kept accurate for a SINGLE Player
modelinfo->UpdateViewWeaponModelCache( viewWeapons, nNumViewWeapons );
}
}
// world weapon model cache monitoring
// world weapons have a much looser cache policy and just needs to monitor the important set of world weapons
{
const char *worldWeapons[MAX_WEAPONS];
int nNumWorldWeapons = 0;
// want to track any world models that are active weapons
// the world weapons lying on the ground are the ones that become LRU purge candidates
C_BasePlayer *pPlayer = ToBasePlayer( this );
if ( pPlayer )
{
C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
if ( pWeapon )
{
worldWeapons[nNumWorldWeapons] = pWeapon->GetWorldModel();
nNumWorldWeapons++;
}
}
C_CSPlayer *pCSPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( pCSPlayer == this )
{
int weaponEntIndex = pCSPlayer->GetTargetedWeapon();
if ( weaponEntIndex > 0 ) //0 is a valid entity index, but will never be used for a weapon
{
C_BaseEntity *pEnt = cl_entitylist->GetEnt( weaponEntIndex );
C_BaseCombatWeapon *pWeapon = dynamic_cast< C_BaseCombatWeapon * >( pEnt );
if ( pWeapon )
{
worldWeapons[nNumWorldWeapons] = pWeapon->GetWorldModel();
nNumWorldWeapons++;
}
}
}
if ( nNumWorldWeapons )
{
modelinfo->TouchWorldWeaponModelCache( worldWeapons, nNumWorldWeapons );
}
}
}
bool C_BaseCombatCharacter::HasEverBeenInjured( void ) const
{
return ( m_flTimeOfLastInjury != 0.0f );
}
float C_BaseCombatCharacter::GetTimeSinceLastInjury( void ) const
{
return gpGlobals->curtime - m_flTimeOfLastInjury;
}
IMPLEMENT_CLIENTCLASS(C_BaseCombatCharacter, DT_BaseCombatCharacter, CBaseCombatCharacter);
// Only send active weapon index to local player
BEGIN_RECV_TABLE_NOBASE( C_BaseCombatCharacter, DT_BCCLocalPlayerExclusive )
RecvPropTime( RECVINFO( m_flNextAttack ) ),
END_RECV_TABLE();
BEGIN_RECV_TABLE_NOBASE( C_BaseCombatCharacter, DT_BCCNonLocalPlayerExclusive )
#if defined( CSTRIKE15 )
// In CS:GO send active weapon index to all players except local
RecvPropArray3( RECVINFO_ARRAY(m_hMyWeapons), RecvPropEHandle( RECVINFO( m_hMyWeapons[0] ) ) ),
#endif
END_RECV_TABLE();
BEGIN_RECV_TABLE(C_BaseCombatCharacter, DT_BaseCombatCharacter)
RecvPropDataTable( "bcc_localdata", 0, 0, &REFERENCE_RECV_TABLE(DT_BCCLocalPlayerExclusive) ),
RecvPropDataTable( "bcc_nonlocaldata", 0, 0, &REFERENCE_RECV_TABLE(DT_BCCNonLocalPlayerExclusive) ),
RecvPropInt( RECVINFO( m_LastHitGroup ) ),
RecvPropEHandle( RECVINFO( m_hActiveWeapon ) ),
RecvPropTime( RECVINFO( m_flTimeOfLastInjury ) ),
RecvPropInt( RECVINFO( m_nRelativeDirectionOfLastInjury ) ),
RecvPropArray3( RECVINFO_ARRAY(m_hMyWeapons), RecvPropEHandle( RECVINFO( m_hMyWeapons[0] ) ) ),
#ifdef INVASION_CLIENT_DLL
RecvPropInt( RECVINFO( m_iPowerups ) ),
#endif
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_BaseCombatCharacter )
DEFINE_PRED_ARRAY( m_iAmmo, FIELD_INTEGER, MAX_AMMO_TYPES, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_flNextAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_hActiveWeapon, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_ARRAY( m_hMyWeapons, FIELD_EHANDLE, MAX_WEAPONS, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()

View File

@@ -0,0 +1,181 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines the client-side representation of CBaseCombatCharacter.
//
// $NoKeywords: $
//===========================================================================//
#ifndef C_BASECOMBATCHARACTER_H
#define C_BASECOMBATCHARACTER_H
#ifdef _WIN32
#pragma once
#endif
#include "shareddefs.h"
#include "c_baseflex.h"
#define BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE 0.9f
class C_BaseCombatWeapon;
class C_WeaponCombatShield;
class C_BaseCombatCharacter : public C_BaseFlex
{
DECLARE_CLASS( C_BaseCombatCharacter, C_BaseFlex );
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
C_BaseCombatCharacter( void );
virtual ~C_BaseCombatCharacter( void );
virtual bool IsBaseCombatCharacter( void ) { return true; };
virtual C_BaseCombatCharacter *MyCombatCharacterPointer( void ) { return this; }
virtual void DropPhysicsMag( const char *options ) {}
// -----------------------
// Vision
// -----------------------
enum FieldOfViewCheckType { USE_FOV, DISREGARD_FOV };
bool IsAbleToSee( const CBaseEntity *entity, FieldOfViewCheckType checkFOV ); // Visible starts with line of sight, and adds all the extra game checks like fog, smoke, camo...
bool IsAbleToSee( C_BaseCombatCharacter *pBCC, FieldOfViewCheckType checkFOV ); // Visible starts with line of sight, and adds all the extra game checks like fog, smoke, camo...
virtual bool IsLookingTowards( const CBaseEntity *target, float cosTolerance = BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE ) const; // return true if our view direction is pointing at the given target, within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
virtual bool IsLookingTowards( const Vector &target, float cosTolerance = BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE ) const; // return true if our view direction is pointing at the given target, within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
virtual bool IsInFieldOfView( CBaseEntity *entity ) const; // Calls IsLookingAt with the current field of view.
virtual bool IsInFieldOfView( const Vector &pos ) const;
enum LineOfSightCheckType
{
IGNORE_NOTHING,
IGNORE_ACTORS
};
virtual bool IsLineOfSightClear( CBaseEntity *entity, LineOfSightCheckType checkType = IGNORE_NOTHING ) const;// strictly LOS check with no other considerations
virtual bool IsLineOfSightClear( const Vector &pos, LineOfSightCheckType checkType = IGNORE_NOTHING, CBaseEntity *entityToIgnore = NULL ) const;
int LastHitGroup() const { return m_LastHitGroup; }
// -----------------------
// Ammo
// -----------------------
void RemoveAmmo( int iCount, int iAmmoIndex );
void RemoveAmmo( int iCount, const char *szName );
void RemoveAllAmmo( );
int GetAmmoCount( int iAmmoIndex ) const;
int GetAmmoCount( char *szName ) const;
virtual C_BaseCombatWeapon* Weapon_OwnsThisType( const char *pszWeapon, int iSubType = 0 ) const; // True if already owns a weapon of this class
virtual C_BaseCombatWeapon *Weapon_GetSlot( int slot ) const;
virtual C_BaseCombatWeapon *Weapon_GetPosition( int pos ) const;
virtual bool Weapon_Switch( C_BaseCombatWeapon *pWeapon, int viewmodelindex = 0 );
virtual bool Weapon_CanSwitchTo(C_BaseCombatWeapon *pWeapon);
// I can't use my current weapon anymore. Switch me to the next best weapon.
bool SwitchToNextBestWeapon(C_BaseCombatWeapon *pCurrent);
virtual C_BaseCombatWeapon *GetActiveWeapon( void ) const;
int WeaponCount() const;
virtual C_BaseCombatWeapon *GetWeapon( int i ) const;
// This is a sort of hack back-door only used by physgun!
void SetAmmoCount( int iCount, int iAmmoIndex );
bool HasEverBeenInjured( void ) const;
float GetTimeSinceLastInjury( void ) const;
RelativeDamagedDirection_t GetLastInjuryRelativeDirection( void ) { return m_nRelativeDirectionOfLastInjury; }
float GetNextAttack() const { return m_flNextAttack; }
void SetNextAttack( float flWait ) { m_flNextAttack = flWait; }
virtual int BloodColor();
// Blood color (see BLOOD_COLOR_* macros in baseentity.h)
void SetBloodColor( int nBloodColor );
virtual void DoMuzzleFlash();
public:
// BEGIN PREDICTION DATA COMPACTION (these fields are together to allow for faster copying in prediction system)
float m_flNextAttack;
private:
bool ComputeLOS( const Vector &vecEyePosition, const Vector &vecTarget ) const;
public:
int m_LastHitGroup;
private:
CNetworkArray( int, m_iAmmo, MAX_AMMO_TYPES );
CHandle<C_BaseCombatWeapon> m_hMyWeapons[MAX_WEAPONS];
CHandle< C_BaseCombatWeapon > m_hActiveWeapon;
float m_flTimeOfLastInjury;
RelativeDamagedDirection_t m_nRelativeDirectionOfLastInjury;
// END PREDICTION DATA COMPACTION
protected:
int m_bloodColor; // color of blood particless
private:
private:
C_BaseCombatCharacter( const C_BaseCombatCharacter & ); // not defined, not accessible
//-----------------------
#ifdef INVASION_CLIENT_DLL
public:
virtual void Release( void );
virtual void SetDormant( bool bDormant );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
// TF2 Powerups
virtual bool CanBePoweredUp( void ) { return true; }
bool HasPowerup( int iPowerup ) { return ( m_iPowerups & (1 << iPowerup) ) != 0; };
virtual void PowerupStart( int iPowerup, bool bInitial );
virtual void PowerupEnd( int iPowerup );
void RemoveAllPowerups( void );
// Powerup effects
void AddEMPEffect( float flSize );
void AddBuffEffect( float flSize );
C_WeaponCombatShield *GetShield( void );
public:
int m_iPowerups;
int m_iPrevPowerups;
#endif
public:
virtual void OnDataChanged( DataUpdateType_t updateType );
};
inline C_BaseCombatCharacter *ToBaseCombatCharacter( C_BaseEntity *pEntity )
{
return pEntity ? pEntity->MyCombatCharacterPointer() : NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
inline int C_BaseCombatCharacter::WeaponCount() const
{
return MAX_WEAPONS;
}
EXTERN_RECV_TABLE(DT_BaseCombatCharacter);
#endif // C_BASECOMBATCHARACTER_H

View File

@@ -0,0 +1,661 @@
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client side implementation of CBaseCombatWeapon.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "history_resource.h"
#include "iclientmode.h"
#include "iinput.h"
#include "weapon_selection.h"
#include "hud_crosshair.h"
#include "engine/ivmodelinfo.h"
#include "tier0/vprof.h"
#include "hltvcamera.h"
#include "tier1/keyvalues.h"
#include "toolframework/itoolframework.h"
#include "toolframework_client.h"
#if defined( CSTRIKE15 )
#include "c_cs_player.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::SetDormant( bool bDormant )
{
// If I'm going from active to dormant and I'm carried by another player, holster me.
if ( !IsDormant() && bDormant && GetOwner() && !IsCarriedByLocalPlayer() )
{
Holster( NULL );
}
BaseClass::SetDormant( bDormant );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::NotifyShouldTransmit( ShouldTransmitState_t state )
{
BaseClass::NotifyShouldTransmit(state);
if (state == SHOULDTRANSMIT_END)
{
if (m_iState == WEAPON_IS_ACTIVE)
{
m_iState = WEAPON_IS_CARRIED_BY_PLAYER;
}
}
else if( state == SHOULDTRANSMIT_START )
{
// We don't check the value of m_iState because if the weapon is active, we need the state to match reguardless
// of what it was.
if( GetOwner() && GetOwner()->GetActiveWeapon() == this )
{
// Restore the Activeness of the weapon if we client-twiddled it off in the first case above.
m_iState = WEAPON_IS_ACTIVE;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: To wrap PORTAL mod specific functionality into one place
//-----------------------------------------------------------------------------
static inline bool ShouldDrawLocalPlayer( C_BasePlayer *pl )
{
#if defined( PORTAL )
return true;
#else
Assert( pl );
return pl->ShouldDrawLocalPlayer();
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::OnRestore()
{
BaseClass::OnRestore();
// if the player is holding this weapon,
// mark it as just restored so it won't show as a new pickup
if ( C_BasePlayer::IsLocalPlayer( GetOwner() ) )
{
m_bJustRestored = true;
}
}
void C_BaseCombatWeapon::UpdateOnRemove( void )
{
BaseClass::UpdateOnRemove();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::OnDataChanged( DataUpdateType_t updateType )
{
// Must update visibility prior to calling OnDataChanged so that
// shadows are dealt with correctly.
UpdateVisibility();
BaseClass::OnDataChanged( updateType );
// let the world model know we're updating, in case it wants to as well
CBaseWeaponWorldModel *pWeaponWorldModel = GetWeaponWorldModel();
if ( pWeaponWorldModel )
{
pWeaponWorldModel->OnDataChanged( updateType );
}
// If it's being carried by the *local* player, on the first update,
// find the registered weapon for this ID
C_BaseCombatCharacter *pOwner = GetOwner();
C_BasePlayer *pPlayer = ToBasePlayer( pOwner );
#if defined( CSTRIKE15 )
C_CSPlayer *pObservedPlayer = GetHudPlayer();
// check if weapon was dropped by local player or the player we are observing
if ( pObservedPlayer == pPlayer && pObservedPlayer->State_Get() == STATE_ACTIVE )
#else
// check if weapon is carried by local player
bool bIsLocalPlayer = C_BasePlayer::IsLocalPlayer( pPlayer );
if ( bIsLocalPlayer )
#endif
{
ACTIVE_SPLITSCREEN_PLAYER_GUARD( C_BasePlayer::GetSplitScreenSlotForPlayer( pPlayer ) );
// If I was just picked up, or created & immediately carried, add myself to this client's list of weapons
if ( m_iState != WEAPON_NOT_CARRIED && m_iOldState == WEAPON_NOT_CARRIED )
{
// Tell the HUD this weapon's been picked up
if ( ShouldDrawPickup() )
{
CBaseHudWeaponSelection *pHudSelection = GetHudWeaponSelection();
if ( pHudSelection )
{
pHudSelection->OnWeaponPickup( this );
}
}
}
}
UpdateVisibility();
m_iOldState = m_iState;
m_bJustRestored = false;
}
//-----------------------------------------------------------------------------
// Is anyone carrying it?
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsBeingCarried() const
{
return ( m_hOwner.Get() != NULL );
}
//-----------------------------------------------------------------------------
// Is the carrier alive?
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsCarrierAlive() const
{
if ( !m_hOwner.Get() )
return false;
return m_hOwner.Get()->GetHealth() > 0;
}
//-----------------------------------------------------------------------------
// Should this object cast shadows?
//-----------------------------------------------------------------------------
ShadowType_t C_BaseCombatWeapon::ShadowCastType()
{
if ( IsEffectActive( /*EF_NODRAW |*/ EF_NOSHADOW ) )
return SHADOWS_NONE;
if (!IsBeingCarried())
return SHADOWS_RENDER_TO_TEXTURE;
if (IsCarriedByLocalPlayer())
return SHADOWS_NONE;
return (m_iState != WEAPON_IS_CARRIED_BY_PLAYER) ? SHADOWS_RENDER_TO_TEXTURE : SHADOWS_NONE;
}
//-----------------------------------------------------------------------------
// Purpose: This weapon is the active weapon, and it should now draw anything
// it wants to. This gets called every frame.
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::Redraw()
{
if ( GetClientMode()->ShouldDrawCrosshair() )
{
DrawCrosshair();
}
// ammo drawing has been moved into hud_ammo.cpp
}
//-----------------------------------------------------------------------------
// Purpose: Draw the weapon's crosshair
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::DrawCrosshair()
{
#ifndef INFESTED_DLL
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
if ( !player )
return;
Color clr = GetHud().m_clrNormal;
/*
// TEST: if the thing under your crosshair is on a different team, light the crosshair with a different color.
Vector vShootPos, vShootAngles;
GetShootPosition( vShootPos, vShootAngles );
Vector vForward;
AngleVectors( vShootAngles, &vForward );
// Change the color depending on if we're looking at a friend or an enemy.
CPartitionFilterListMask filter( PARTITION_ALL_CLIENT_EDICTS );
trace_t tr;
traceline->TraceLine( vShootPos, vShootPos + vForward * 10000, COLLISION_GROUP_NONE, MASK_SHOT, &tr, true, ~0, &filter );
if ( tr.index != 0 && tr.index != INVALID_CLIENTENTITY_HANDLE )
{
C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( tr.index );
if ( pEnt )
{
if ( pEnt->GetTeamNumber() != player->GetTeamNumber() )
{
g = b = 0;
}
}
}
*/
CHudCrosshair *crosshair = GET_HUDELEMENT( CHudCrosshair );
if ( !crosshair )
return;
// Find out if this weapon's auto-aimed onto a target
bool bOnTarget = ( m_iState == WEAPON_IS_ACTIVE ) && player->m_fOnTarget;
if ( player->GetFOV() >= 90 )
{
// normal crosshairs
if ( bOnTarget && GetWpnData().iconAutoaim )
{
clr[3] = 255;
crosshair->SetCrosshair( GetWpnData().iconAutoaim, clr );
}
else if ( GetWpnData().iconCrosshair )
{
clr[3] = 255;
crosshair->SetCrosshair( GetWpnData().iconCrosshair, clr );
}
else
{
crosshair->ResetCrosshair();
}
}
else
{
Color white( 255, 255, 255, 255 );
// zoomed crosshairs
if (bOnTarget && GetWpnData().iconZoomedAutoaim)
crosshair->SetCrosshair(GetWpnData().iconZoomedAutoaim, white);
else if ( GetWpnData().iconZoomedCrosshair )
crosshair->SetCrosshair( GetWpnData().iconZoomedCrosshair, white );
else
crosshair->ResetCrosshair();
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose: This weapon is the active weapon, and the viewmodel for it was just drawn.
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::ViewModelDrawn( int nFlags, C_BaseViewModel *pViewModel )
{
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if this client's carrying this weapon
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsCarriedByLocalPlayer( void )
{
if ( !GetOwner() )
return false;
return ( C_BasePlayer::IsLocalPlayer( GetOwner() ) );
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if this weapon is the local client's currently wielded weapon
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsActiveByLocalPlayer( void )
{
if ( IsCarriedByLocalPlayer() )
{
return (m_iState == WEAPON_IS_ACTIVE);
}
return false;
}
bool C_BaseCombatWeapon::GetShootPosition( Vector &vOrigin, QAngle &vAngles )
{
// Get the entity because the weapon doesn't have the right angles.
C_BaseCombatCharacter *pEnt = ToBaseCombatCharacter( GetOwner() );
if ( pEnt )
{
if ( pEnt == C_BasePlayer::GetLocalPlayer() )
{
vAngles = pEnt->EyeAngles();
}
else
{
vAngles = pEnt->GetRenderAngles();
}
}
else
{
vAngles.Init();
}
C_BasePlayer *player = ToBasePlayer( pEnt );
bool bUseViewModel = false;
if ( C_BasePlayer::IsLocalPlayer( pEnt ) )
{
ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( pEnt );
bUseViewModel = !player->ShouldDrawLocalPlayer();
}
QAngle vDummy;
if ( IsActiveByLocalPlayer() && bUseViewModel )
{
C_BaseViewModel *vm = player ? player->GetViewModel( 0 ) : NULL;
if ( vm )
{
int iAttachment = vm->LookupAttachment( "muzzle" );
if ( vm->GetAttachment( iAttachment, vOrigin, vDummy ) )
{
return true;
}
}
}
else
{
// Thirdperson
int iAttachment = LookupAttachment( "muzzle" );
if ( GetAttachment( iAttachment, vOrigin, vDummy ) )
{
return true;
}
}
vOrigin = GetRenderOrigin();
return false;
}
bool C_BaseCombatWeapon::ShouldSuppressForSplitScreenPlayer( int nSlot )
{
if ( BaseClass::ShouldSuppressForSplitScreenPlayer( nSlot ) )
{
return true;
}
C_BaseCombatCharacter *pOwner = GetOwner();
// If the owner of this weapon is not allowed to draw in this split screen slot, then don't draw the weapon either.
if ( pOwner && pOwner->ShouldSuppressForSplitScreenPlayer( nSlot ) )
{
return true;
}
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer( nSlot );
// Carried by local player?
// Only draw the weapon if we're in some kind of 3rd person mode because the viewmodel will do that otherwise.
if ( pOwner == pLocalPlayer && !pLocalPlayer->ShouldDrawLocalPlayer() )
{
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::ShouldDraw( void )
{
if ( IsEffectActive( EF_NODRAW ) )
return false;
// weapon has no owner, always draw it
if ( !GetOwner() && !IsViewModel() )
{
return true;
}
else
{
CBaseWeaponWorldModel *pWeaponWorldModel = GetWeaponWorldModel();
if ( pWeaponWorldModel )
{
return false; // the weapon world model will render in our place if it exists
}
else
{
// render only if equipped. The holstered model will render for weapons that aren't equipped
return ( GetOwner() && GetOwner()->GetActiveWeapon() == this );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Return true if a weapon-pickup icon should be displayed when this weapon is received
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::ShouldDrawPickup( void )
{
if ( GetWeaponFlags() & ITEM_FLAG_NOITEMPICKUP )
return false;
if ( m_bJustRestored )
return false;
return true;
}
bool C_BaseCombatWeapon::IsFirstPersonSpectated( void )
{
// check if local player chases owner of this weapon in first person
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
if ( localplayer && localplayer->IsObserver() && GetOwner() )
{
// don't draw weapon if chasing this guy as spectator
// we don't check that in ShouldDraw() since this may change
// without notification
if ( localplayer->GetObserverMode() == OBS_MODE_IN_EYE &&
localplayer->GetObserverTarget() == GetOwner() &&
localplayer->GetObserverInterpState() != C_BasePlayer::OBSERVER_INTERP_TRAVELING )
return true;
}
return false;
}
//----------------------------------------------------------------------------
// Hooks into the fast path render system
//----------------------------------------------------------------------------
IClientModelRenderable* C_BaseCombatWeapon::GetClientModelRenderable()
{
if ( !m_bReadyToDraw )
return 0;
if( IsFirstPersonSpectated() )
return NULL;
VerifyAndSetContextSensitiveWeaponModel();
return BaseClass::GetClientModelRenderable();
}
//-----------------------------------------------------------------------------
// Purpose: Render the weapon. Draw the Viewmodel if the weapon's being carried
// by this player, otherwise draw the worldmodel.
//-----------------------------------------------------------------------------
int C_BaseCombatWeapon::DrawModel( int flags, const RenderableInstance_t &instance )
{
VPROF_BUDGET( "C_BaseCombatWeapon::DrawModel", VPROF_BUDGETGROUP_MODEL_RENDERING );
if ( !m_bReadyToDraw )
return 0;
if ( !IsVisible() )
return 0;
if( IsFirstPersonSpectated() )
return 0;
return BaseClass::DrawModel( flags, instance );
}
#ifdef _DEBUG
ConVar stickers_enabled_thirdperson( "stickers_enabled_thirdperson", "1", FCVAR_DEVELOPMENTONLY, "Enable work-in-progress stickers on worldmodels." );
ConVar stickers_debug_thirdperson_constant( "stickers_debug_thirdperson_constant", "0", FCVAR_DEVELOPMENTONLY, "Continually apply stickers on worldmodels. SLOW" );
ConVar stickers_debug_thirdperson_ray( "stickers_debug_thirdperson_ray", "0", FCVAR_DEVELOPMENTONLY, "Show worldmodel sticker projection position and direction." );
ConVar stickers_debug_thirdperson_ray_duration( "stickers_debug_thirdperson_ray_duration", "0.1", FCVAR_DEVELOPMENTONLY, "Duration to show sticker projection lines." );
ConVar stickers_debug_thirdperson_size( "stickers_debug_thirdperson_size", "0", FCVAR_DEVELOPMENTONLY, "Override worldmodel sticker size." );
extern ConVar stickers_debug_randomize;
#endif
void C_BaseCombatWeapon::ApplyThirdPersonStickers( C_BaseAnimating *pWeaponModelTargetOverride )
{
#ifdef _DEBUG
if (stickers_enabled_thirdperson.GetBool() == 0)
return;
#endif
if ( !IsAbsQueriesValid() )
return;
CEconItemView *pItem = GetEconItemView();
if (!pItem)
return;
if ( pItem->GetNumSupportedStickerSlots() == 0 )
return;
C_BaseAnimating *pTargetModel = pWeaponModelTargetOverride ? pWeaponModelTargetOverride : this;
if ( !pTargetModel->ShouldDraw() )
return;
MDLCACHE_CRITICAL_SECTION();
pTargetModel->CreateModelInstance();
if ( pTargetModel->GetModelInstance() != MODEL_INSTANCE_INVALID )
{
if ( modelrender->ModelHasDecals( pTargetModel->GetModelInstance() ) &&
#ifdef _DEBUG
!stickers_debug_thirdperson_constant.GetBool() &&
#endif
pItem->ItemHasAnyStickersApplied() )
{
return; //decals are already applied
}
modelrender->RemoveAllDecals( pTargetModel->GetModelInstance() );
}
else
{
return; //no model instance
}
matrix3x4_t weaponBoneTransform;
const char* const szStickerBoneLookupTable[] = {
"sticker_a",
"sticker_b",
"sticker_c",
"sticker_d",
"sticker_e"
};
for (int i=0; i<pItem->GetNumSupportedStickerSlots(); i++ )
{
IMaterial *pStickerMaterialThirdPerson = pItem->GetStickerIMaterialBySlotIndex(i, true);
if ( !pStickerMaterialThirdPerson )
{
#ifdef _DEBUG
if ( stickers_debug_randomize.GetBool() )
{
pItem->GenerateStickerMaterials();
pStickerMaterialThirdPerson = pItem->GetStickerIMaterialBySlotIndex(i, true);
}
else
{
continue;
}
#else
continue; //sticker material is not valid
#endif
}
//if the weapon model has world model sticker projection points, use those
//otherwise use schema values
Vector vecWorldRayOrigin, vecWorldRayDirection;
bool bWeaponProvidedStickerAttachments = false;
int nStickerAttachmentBoneIndex = pTargetModel->LookupBone( szStickerBoneLookupTable[i] );
if ( nStickerAttachmentBoneIndex != -1 )
{
pTargetModel->GetBoneTransform( nStickerAttachmentBoneIndex, weaponBoneTransform );
MatrixPosition( weaponBoneTransform, vecWorldRayOrigin );
Vector a,b;
MatrixVectors( weaponBoneTransform, &vecWorldRayDirection, &a, &b );
bWeaponProvidedStickerAttachments = true;
}
else
{
int nBIndex = pTargetModel->LookupBone( pItem->GetStickerWorldModelBoneParentNameBySlotIndex(i) );
if ( nBIndex == -1 )
continue; //couldn't find the parent bone this sticker slot wanted
pTargetModel->GetBoneTransform( nBIndex, weaponBoneTransform );
Ray_t stickerRayLocal;
stickerRayLocal.Init( pItem->GetStickerSlotWorldProjectionStartBySlotIndex( i ),
pItem->GetStickerSlotWorldProjectionEndBySlotIndex( i ) );
VectorTransform( stickerRayLocal.m_Start, weaponBoneTransform, vecWorldRayOrigin );
VectorRotate( stickerRayLocal.m_Delta, weaponBoneTransform, vecWorldRayDirection );
}
#ifdef _DEBUG
if ( stickers_debug_thirdperson_ray.GetBool() )
{
debugoverlay->AddBoxOverlay( vecWorldRayOrigin, Vector(-0.25,-0.25,-0.25), Vector(0.5,0.5,0.5), QAngle(0,0,0), 255, 0, 0, 180, stickers_debug_thirdperson_ray_duration.GetFloat() );
debugoverlay->AddLineOverlay( vecWorldRayOrigin, vecWorldRayOrigin + vecWorldRayDirection, 0,255,0, true, stickers_debug_thirdperson_ray_duration.GetFloat() );
}
#endif
Ray_t stickerRayWorld;
stickerRayWorld.Init( vecWorldRayOrigin, vecWorldRayOrigin + (3*vecWorldRayDirection) );
VMatrix vmatrix_weaponBoneTransform( weaponBoneTransform );
Vector vecStickerUp = vmatrix_weaponBoneTransform.GetLeft();
if ( bWeaponProvidedStickerAttachments )
{
//content defined sticker attachments are z-up
vecStickerUp = -vmatrix_weaponBoneTransform.GetUp();
}
#ifdef _DEBUG
float flStickerSize = (stickers_debug_thirdperson_size.GetFloat() == 0) ? stickers_debug_thirdperson_size.GetFloat() : 1.2f;
pTargetModel->GetBaseEntity()->AddStudioMaterialDecal( stickerRayWorld, pStickerMaterialThirdPerson, flStickerSize, vecStickerUp );
#else
pTargetModel->GetBaseEntity()->AddStudioMaterialDecal( stickerRayWorld, pStickerMaterialThirdPerson, 1.2f, vecStickerUp );
#endif
}
//Msg( "Applied stickers to: %s\n", this->GetName() );
}
//-----------------------------------------------------------------------------
// tool recording
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::GetToolRecordingState( KeyValues *msg )
{
if ( !ToolsEnabled() )
return;
Assert(false);
}

View File

@@ -0,0 +1,22 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CBaseCombatWeapon entity
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASECOMBATWEAPON_H
#define C_BASECOMBATWEAPON_H
#ifdef _WIN32
#pragma once
#endif
#include "basecombatweapon_shared.h"
#include "weapons_resource.h"
class CViewSetup;
class C_BaseViewModel;
#endif // C_BASECOMBATWEAPON

View File

@@ -0,0 +1,28 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basedoor.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef CBaseDoor
#undef CBaseDoor
#endif
IMPLEMENT_CLIENTCLASS_DT(C_BaseDoor, DT_BaseDoor, CBaseDoor)
RecvPropFloat(RECVINFO(m_flWaveHeight)),
END_RECV_TABLE()
C_BaseDoor::C_BaseDoor( void )
{
m_flWaveHeight = 0.0f;
}
C_BaseDoor::~C_BaseDoor( void )
{
}

33
game/client/c_basedoor.h Normal file
View File

@@ -0,0 +1,33 @@
//========= Copyright Š 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#if !defined( C_BASEDOOR_H )
#define C_BASEDOOR_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
#include "c_basetoggle.h"
#if defined( CLIENT_DLL )
#define CBaseDoor C_BaseDoor
#endif
class C_BaseDoor : public C_BaseToggle
{
public:
DECLARE_CLASS( C_BaseDoor, C_BaseToggle );
DECLARE_CLIENTCLASS();
C_BaseDoor( void );
~C_BaseDoor( void );
public:
float m_flWaveHeight;
};
#endif // C_BASEDOOR_H

7223
game/client/c_baseentity.cpp Normal file

File diff suppressed because it is too large Load Diff

2795
game/client/c_baseentity.h Normal file

File diff suppressed because it is too large Load Diff

2200
game/client/c_baseflex.cpp Normal file

File diff suppressed because it is too large Load Diff

308
game/client/c_baseflex.h Normal file
View File

@@ -0,0 +1,308 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
// Client-side CBasePlayer
#ifndef C_STUDIOFLEX_H
#define C_STUDIOFLEX_H
#pragma once
#include "c_baseanimatingoverlay.h"
#include "sceneentity_shared.h"
#include "utlvector.h"
//-----------------------------------------------------------------------------
// Purpose: Item in list of loaded scene files
//-----------------------------------------------------------------------------
class CFlexSceneFile
{
public:
enum
{
MAX_FLEX_FILENAME = 128,
};
char filename[ MAX_FLEX_FILENAME ];
void *buffer;
};
// For phoneme emphasis track
struct Emphasized_Phoneme;
class CSentence;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_BaseFlex : public C_BaseAnimatingOverlay
{
DECLARE_CLASS( C_BaseFlex, C_BaseAnimatingOverlay );
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
C_BaseFlex();
virtual ~C_BaseFlex();
virtual void Spawn();
virtual IClientModelRenderable* GetClientModelRenderable();
virtual void InitPhonemeMappings();
void SetupMappings( char const *pchFileRoot );
virtual CStudioHdr *OnNewModel( void );
virtual void StandardBlendingRules( CStudioHdr *hdr, BoneVector pos[], BoneQuaternionAligned q[], float currentTime, int boneMask );
virtual void OnThreadedDrawSetup();
// model specific
virtual void BuildTransformations( CStudioHdr *pStudioHdr, BoneVector *pos, BoneQuaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed );
virtual void SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights );
virtual bool UsesFlexDelayedWeights();
virtual bool GetSoundSpatialization( SpatializationInfo_t& info );
virtual void GetToolRecordingState( KeyValues *msg );
// Called at the lowest level to actually apply a flex animation
void AddFlexAnimation( CSceneEventInfo *info );
void SetFlexWeight( LocalFlexController_t index, float value );
float GetFlexWeight( LocalFlexController_t index );
// Look up flex controller index by global name
LocalFlexController_t FindFlexController( const char *szName );
public:
Vector m_viewtarget;
CInterpolatedVar< Vector > m_iv_viewtarget;
// indexed by model local flexcontroller
float m_flexWeight[MAXSTUDIOFLEXCTRL];
CInterpolatedVarArray< float, MAXSTUDIOFLEXCTRL > m_iv_flexWeight;
int m_blinktoggle;
static int AddGlobalFlexController( char *szName );
static char const *GetGlobalFlexControllerName( int idx );
// bah, this should be unified with all prev/current stuff.
public:
// Keep track of what scenes are being played
void StartChoreoScene( CChoreoScene *scene );
void RemoveChoreoScene( CChoreoScene *scene );
// Start the specifics of an scene event
virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, C_BaseEntity *pTarget );
virtual bool ProcessSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
// Remove all playing events
void ClearSceneEvents( CChoreoScene *scene, bool canceled );
// Stop specifics of event
virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
// Add the event to the queue for this actor
void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, C_BaseEntity *pTarget = NULL, bool bClientSide = false, C_SceneEntity *pSceneEntity = NULL );
// Remove the event from the queue for this actor
void RemoveSceneEvent( CChoreoScene *scene, CChoreoEvent *event, bool fastKill );
// Checks to see if the event should be considered "completed"
bool CheckSceneEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event );
// Checks to see if a event should be considered "completed"
virtual bool CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event );
int FlexControllerLocalToGlobal( const flexsettinghdr_t *pSettinghdr, int key );
void EnsureTranslations( const flexsettinghdr_t *pSettinghdr );
// For handling scene files
const void *FindSceneFile( const char *filename );
static void InvalidateFlexCaches();
bool IsFlexCacheValid() const;
private:
Vector SetViewTarget( CStudioHdr *pStudioHdr, const float *pGlobalFlexWeight );
void RunFlexRules( CStudioHdr *pStudioHdr, const float *pGlobalFlexWeight, float *dest );
// Manipulation of events for the object
// Should be called by think function to process all scene events
// The default implementation resets m_flexWeight array and calls
// AddSceneEvents
void ProcessSceneEvents( bool bFlexEvents, float *pGlobalFlexWeight );
// Assumes m_flexWeight array has been set up, this adds the actual currently playing
// expressions to the flex weights and adds other scene events as needed
bool ProcessSceneEvent( float *pGlobalFlexWeight, bool bFlexEvents, CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
bool RequestStartSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
bool ProcessFlexAnimationSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
bool ProcessFlexSettingSceneEvent( float *pGlobalFlexWeight, CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
void AddFlexSetting( float *pGlobalFlexWeight, const char *expr, float scale,
const flexsettinghdr_t *pSettinghdr, bool newexpression );
// Array of active SceneEvents, in order oldest to newest
CUtlVector < CSceneEventInfo > m_SceneEvents;
CUtlVector < CChoreoScene * > m_ActiveChoreoScenes;
bool HasSceneEvents() const;
private:
// Mapping for each loaded scene file used by this actor
struct FS_LocalToGlobal_t
{
explicit FS_LocalToGlobal_t() :
m_Key( 0 ),
m_nCount( 0 ),
m_Mapping( 0 )
{
}
explicit FS_LocalToGlobal_t( const flexsettinghdr_t *key ) :
m_Key( key ),
m_nCount( 0 ),
m_Mapping( 0 )
{
}
void SetCount( int count )
{
Assert( !m_Mapping );
Assert( count > 0 );
m_nCount = count;
m_Mapping = new int[ m_nCount ];
Q_memset( m_Mapping, 0, m_nCount * sizeof( int ) );
}
FS_LocalToGlobal_t( const FS_LocalToGlobal_t& src )
{
m_Key = src.m_Key;
delete m_Mapping;
m_Mapping = new int[ src.m_nCount ];
Q_memcpy( m_Mapping, src.m_Mapping, src.m_nCount * sizeof( int ) );
m_nCount = src.m_nCount;
}
~FS_LocalToGlobal_t()
{
delete m_Mapping;
m_nCount = 0;
m_Mapping = 0;
}
const flexsettinghdr_t *m_Key;
int m_nCount;
int *m_Mapping;
};
static bool FlexSettingLessFunc( const FS_LocalToGlobal_t& lhs, const FS_LocalToGlobal_t& rhs );
CUtlRBTree< FS_LocalToGlobal_t, unsigned short > m_LocalToGlobal;
float m_blinktime;
int m_prevblinktoggle;
int m_iBlink;
LocalFlexController_t m_iEyeUpdown;
LocalFlexController_t m_iEyeRightleft;
int m_iMouthAttachment;
float *m_flFlexDelayedWeight;
int m_iMostRecentFlexCounter;
Vector m_CachedViewTarget;
CUtlVector< float > m_CachedFlexWeights;
CUtlVector< float > m_CachedDelayedFlexWeights;
// shared flex controllers
static int g_numflexcontrollers;
static char *g_flexcontroller[MAXSTUDIOFLEXCTRL*4]; // room for global set of flexcontrollers
static float s_pGlobalFlexWeight[MAXSTUDIOFLEXCTRL*4];
protected:
enum
{
PHONEME_CLASS_WEAK = 0,
PHONEME_CLASS_NORMAL,
PHONEME_CLASS_STRONG,
NUM_PHONEME_CLASSES
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
struct Emphasized_Phoneme
{
// Global fields, setup at start
char classname[ 64 ];
bool required;
// Global fields setup first time tracks played
bool basechecked;
const flexsettinghdr_t *base;
const flexsetting_t *exp;
// Local fields, processed for each sentence
bool valid;
float amount;
};
Emphasized_Phoneme m_PhonemeClasses[ NUM_PHONEME_CLASSES ];
private:
C_BaseFlex( const C_BaseFlex & ); // not defined, not accessible
const flexsetting_t *FindNamedSetting( const flexsettinghdr_t *pSettinghdr, const char *expr );
void ProcessVisemes( Emphasized_Phoneme *classes, float *pGlobalFlexWeight );
void AddVisemesForSentence( float *pGlobalFlexWeight, Emphasized_Phoneme *classes, float emphasis_intensity, CSentence *sentence, float t, float dt, bool juststarted );
void AddViseme( float *pGlobalFlexWeight, Emphasized_Phoneme *classes, float emphasis_intensity, int phoneme, float scale, bool newexpression );
bool SetupEmphasisBlend( Emphasized_Phoneme *classes, int phoneme );
void ComputeBlendedSetting( Emphasized_Phoneme *classes, float emphasis_intensity );
#ifdef HL2_CLIENT_DLL
public:
Vector m_vecLean;
CInterpolatedVar< Vector > m_iv_vecLean;
Vector m_vecShift;
CInterpolatedVar< Vector > m_iv_vecShift;
#endif
};
//-----------------------------------------------------------------------------
// Do we have active expressions?
//-----------------------------------------------------------------------------
inline bool C_BaseFlex::HasSceneEvents() const
{
return m_SceneEvents.Count() != 0;
}
EXTERN_RECV_TABLE(DT_BaseFlex);
float *GetVisemeWeights( int phoneme );
#endif // C_STUDIOFLEX_H

3953
game/client/c_baselesson.cpp Normal file

File diff suppressed because it is too large Load Diff

462
game/client/c_baselesson.h Normal file
View File

@@ -0,0 +1,462 @@
//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client handler for instruction players how to play
//
//=============================================================================//
#ifndef _C_BASELESSON_H_
#define _C_BASELESSON_H_
#include "GameEventListener.h"
#include "hud_locator_target.h"
#define DECLARE_LESSON( _lessonClassName, _baseLessonClassName ) \
typedef _baseLessonClassName BaseClass;\
typedef _lessonClassName ThisClass;\
_lessonClassName( const char *pchName, bool bIsDefaultHolder, bool bIsOpenOpportunity, int nSplitScreenSlot )\
: _baseLessonClassName( pchName, bIsDefaultHolder, bIsOpenOpportunity, nSplitScreenSlot )\
{\
Init();\
}
enum LessonInstanceType
{
LESSON_INSTANCE_MULTIPLE,
LESSON_INSTANCE_SINGLE_OPEN,
LESSON_INSTANCE_FIXED_REPLACE,
LESSON_INSTANCE_SINGLE_ACTIVE,
LESSON_INSTANCE_TYPE_TOTAL
};
// This is used to solve a problem where bots can take the place of a player, where on or the other don't have valid entities on the client at the same time
#define MAX_DELAYED_PLAYER_SWAPS 8
struct delayed_player_swap_t
{
CHandle<C_BaseEntity> *phHandleToChange;
int iNewUserID;
delayed_player_swap_t( void )
{
phHandleToChange = NULL;
iNewUserID = -1;
}
};
abstract_class CBaseLesson : public CGameEventListener
{
public:
CBaseLesson( const char *pchName, bool bIsDefaultHolder, bool bIsOpenOpportunity, int nSplitScreenSlot );
virtual ~CBaseLesson( void );
void AddPrerequisite( const char *pchLessonName );
const CGameInstructorSymbol& GetNameSymbol( void ) const { return m_stringName; }
const char * GetName( void ) const { return m_stringName.String(); }
int GetPriority( void ) const { return m_iPriority; }
const char * GetCloseReason( void ) const { return m_stringCloseReason.String(); }
void SetCloseReason( const char *pchReason ) { m_stringCloseReason = pchReason; }
CBaseLesson* GetRoot( void ) const { return m_pRoot; }
void SetRoot( CBaseLesson *pRoot );
const CUtlVector < CBaseLesson * >* GetChildren( void ) const { return &m_OpenOpportunities; }
float GetInitTime( void ) { return m_fInitTime; }
void SetStartTime( void ) { m_fStartTime = gpGlobals->curtime; }
void ResetStartTime( void ) { m_fStartTime = 0.0f; m_bHasPlayedSound = false; }
bool ShouldShowSpew( void );
bool NoPriority( void ) const;
bool IsDefaultHolder( void ) const { return m_bIsDefaultHolder; }
bool IsOpenOpportunity( void ) const { return m_bIsOpenOpportunity; }
bool IsLocked( void ) const;
bool CanOpenWhenDead( void ) const { return m_bCanOpenWhenDead; }
bool CanOpenOnceLearned( void ) const { return !m_bOnceLearnedNeverOpen; }
bool IsUsableInMidair( void ) const { return m_bUsableInMidair; }
bool IsInstructing( void ) const { return ( m_fStartTime > 0.0f ); }
bool IsLearned( void ) const;
bool PrerequisitesHaveBeenMet( void ) const;
bool IsTimedOut( void );
int InstanceType( void ) const { return m_iInstanceType; }
const CGameInstructorSymbol& GetReplaceKeySymbol( void ) const { return m_stringReplaceKey; }
const char* GetReplaceKey( void ) const { return m_stringReplaceKey.String(); }
int GetFixedInstancesMax( void ) const { return m_iFixedInstancesMax; }
bool ShouldReplaceOnlyWhenStopped( void ) const { return m_bReplaceOnlyWhenStopped; }
void SetInstanceActive( bool bInstanceActive ) { m_bInstanceActive = bInstanceActive; }
bool IsInstanceActive( void ) const { return m_bInstanceActive; }
void ResetDisplaysAndSuccesses( void );
bool IncDisplayCount( void );
bool IncSuccessCount( void );
void SetDisplayCount( int iDisplayCount ) { m_iDisplayCount = iDisplayCount; }
void SetSuccessCount( int iSuccessCount ) { m_iSuccessCount = iSuccessCount; }
int GetDisplayCount( void ) const { return m_iDisplayCount; }
int GetSuccessCount( void ) const { return m_iSuccessCount; }
int GetDisplayLimit( void ) const { return m_iDisplayLimit; }
int GetSuccessLimit( void ) const { return m_iSuccessLimit; }
void Init( void ); // NOT virtual, each constructor calls their own
virtual void InitPrerequisites( void ) {};
virtual void Start( void ) = 0;
virtual void Stop( void ) = 0;
virtual void OnOpen( void ) {};
virtual void Update( void ) {};
virtual void UpdateInactive( void ) {};
virtual bool ShouldDisplay( void ) const { return true; }
virtual bool IsVisible( void ) const { return true; }
virtual bool WasDisplayed( void ) const { return m_bWasDisplayed ? true : false; }
virtual void SwapOutPlayers( int iOldUserID, int iNewUserID ) {}
virtual void TakePlaceOf( CBaseLesson *pLesson );
int GetSplitScreenSlot() const { return m_nSplitScreenSlot; }
const char *GetGroup() { return m_szLessonGroup.String(); }
void SetEnabled( bool bEnabled ) { m_bDisabled = !bEnabled; }
protected:
void MarkSucceeded( void );
void CloseOpportunity( const char *pchReason );
bool DoDelayedPlayerSwaps( void ) const;
private:
CBaseLesson *m_pRoot;
CUtlVector < CBaseLesson * > m_OpenOpportunities;
CUtlVector < const CBaseLesson * > m_Prerequisites;
CGameInstructorSymbol m_stringCloseReason;
protected:
CGameInstructorSymbol m_stringName;
private:
bool m_bInstanceActive : 1;
bool m_bSuccessCounted : 1;
bool m_bIsDefaultHolder : 1;
bool m_bIsOpenOpportunity : 1;
protected:
LessonInstanceType m_iInstanceType;
int m_iPriority;
CGameInstructorSymbol m_stringReplaceKey;
int m_iFixedInstancesMax;
bool m_bReplaceOnlyWhenStopped;
int m_iTeam;
bool m_bOnlyKeyboard;
bool m_bOnlyGamepad;
bool m_bNoSplitscreen;
int m_iDisplayLimit;
int m_iDisplayCount;
bool m_bWasDisplayed;
int m_iSuccessLimit;
int m_iSuccessCount;
int m_nSplitScreenSlot;
float m_fLockDuration;
float m_fTimeout;
float m_fInitTime;
float m_fStartTime;
float m_fLockTime;
float m_fUpdateInterval;
bool m_bHasPlayedSound;
CGameInstructorSymbol m_szStartSound;
CGameInstructorSymbol m_szLessonGroup;
bool m_bCanOpenWhenDead;
bool m_bBumpWithTimeoutWhenLearned;
bool m_bOnceLearnedNeverOpen;
bool m_bCanTimeoutWhileInactive;
bool m_bDisabled;
bool m_bUsableInMidair;
// Right now we can only queue up 4 swaps...
// this number can be increased if more entity handle scripted variables are added
mutable delayed_player_swap_t m_pDelayedPlayerSwap[ MAX_DELAYED_PLAYER_SWAPS ];
mutable int m_iNumDelayedPlayerSwaps;
public:
// Colors for console spew in verbose mode
static Color m_rgbaVerboseHeader;
static Color m_rgbaVerbosePlain;
static Color m_rgbaVerboseName;
static Color m_rgbaVerboseOpen;
static Color m_rgbaVerboseClose;
static Color m_rgbaVerboseSuccess;
static Color m_rgbaVerboseUpdate;
};
class CTextLesson : public CBaseLesson
{
public:
DECLARE_LESSON( CTextLesson, CBaseLesson );
void Init( void ); // NOT virtual, each constructor calls their own
virtual void Start( void );
virtual void Stop( void );
protected:
CGameInstructorSymbol m_szDisplayText;
CGameInstructorSymbol m_szDisplayParamText;
CGameInstructorSymbol m_szBinding;
CGameInstructorSymbol m_szGamepadBinding;
};
class CIconLesson : public CTextLesson
{
public:
DECLARE_LESSON( CIconLesson, CTextLesson );
void Init( void ); // NOT virtual, each constructor calls their own
virtual void Start( void );
virtual void Stop( void );
virtual void Update( void );
virtual void UpdateInactive( void );
virtual bool ShouldDisplay( void ) const;
virtual bool IsVisible( void ) const;
virtual void SwapOutPlayers( int iOldUserID, int iNewUserID );
virtual void TakePlaceOf( CBaseLesson *pLesson );
void SetLocatorBinding( CLocatorTarget * pLocatorTarget );
const char *GetCaptionColorString() { return m_szCaptionColor.String(); }
bool IsPresentComplete( void );
void PresentStart( void );
void PresentEnd( void );
private:
virtual void UpdateLocatorTarget( CLocatorTarget *pLocatorTarget, C_BaseEntity *pIconTarget );
protected:
CHandle<C_BaseEntity> m_hIconTarget;
CGameInstructorSymbol m_szVguiTargetName;
CGameInstructorSymbol m_szVguiTargetLookup;
int m_nVguiTargetEdge;
float m_flUpOffset;
float m_flRelativeUpOffset;
float m_fFixedPositionX;
float m_fFixedPositionY;
int m_hLocatorTarget;
int m_iFlags;
float m_fRange;
float m_fCurrentDistance;
float m_fOnScreenStartTime;
float m_fUpdateDistanceTime;
CGameInstructorSymbol m_szOnscreenIcon;
CGameInstructorSymbol m_szOffscreenIcon;
CGameInstructorSymbol m_szCaptionColor;
bool m_bFixedPosition;
bool m_bNoIconTarget;
bool m_bAllowNodrawTarget;
bool m_bVisible;
bool m_bShowWhenOccluded;
bool m_bNoOffscreen;
bool m_bForceCaption;
};
enum LessonAction
{
LESSON_ACTION_NONE,
LESSON_ACTION_SCOPE_IN,
LESSON_ACTION_SCOPE_OUT,
LESSON_ACTION_CLOSE,
LESSON_ACTION_SUCCESS,
LESSON_ACTION_LOCK,
LESSON_ACTION_PRESENT_COMPLETE,
LESSON_ACTION_PRESENT_START,
LESSON_ACTION_PRESENT_END,
LESSON_ACTION_REFERENCE_OPEN,
LESSON_ACTION_IS_MULTIPLAYER,
LESSON_ACTION_SET,
LESSON_ACTION_ADD,
LESSON_ACTION_SUBTRACT,
LESSON_ACTION_MULTIPLY,
LESSON_ACTION_IS,
LESSON_ACTION_LESS_THAN,
LESSON_ACTION_HAS_PREFIX,
LESSON_ACTION_HAS_BIT,
LESSON_ACTION_BIT_COUNT_IS,
LESSON_ACTION_BIT_COUNT_LESS_THAN,
LESSON_ACTION_GET_DISTANCE,
LESSON_ACTION_GET_ANGULAR_DISTANCE,
LESSON_ACTION_GET_PLAYER_DISPLAY_NAME,
LESSON_ACTION_CLASSNAME_IS,
LESSON_ACTION_MODELNAME_IS,
LESSON_ACTION_TEAM_IS,
LESSON_ACTION_HEALTH_LESS_THAN,
LESSON_ACTION_HEALTH_PERCENTAGE_LESS_THAN,
LESSON_ACTION_GET_ACTIVE_WEAPON,
LESSON_ACTION_WEAPON_IS,
LESSON_ACTION_WEAPON_HAS,
LESSON_ACTION_GET_ACTIVE_WEAPON_SLOT,
LESSON_ACTION_GET_WEAPON_SLOT,
LESSON_ACTION_GET_WEAPON_IN_SLOT,
LESSON_ACTION_CLIP_PERCENTAGE_LESS_THAN,
LESSON_ACTION_WEAPON_AMMO_LOW,
LESSON_ACTION_WEAPON_AMMO_FULL,
LESSON_ACTION_WEAPON_AMMO_EMPTY,
LESSON_ACTION_WEAPON_CAN_USE,
LESSON_ACTION_USE_TARGET_IS,
LESSON_ACTION_GET_USE_TARGET,
LESSON_ACTION_GET_POTENTIAL_USE_TARGET,
// Enum continued in Mod_LessonAction
LESSON_ACTION_MOD_START,
};
struct LessonElement_t
{
int iVariable;
int iParamVarIndex;
int iAction;
_fieldtypes paramType;
CGameInstructorSymbol szParam;
bool bNot : 1;
bool bOptionalParam : 1;
LessonElement_t( int p_iVariable, int p_iAction, bool p_bNot, bool p_bOptionalParam, const char *pchParam, int p_iParamVarIndex, _fieldtypes p_paramType )
{
iVariable = p_iVariable;
iAction = p_iAction;
bNot = p_bNot;
bOptionalParam = p_bOptionalParam;
szParam = pchParam;
iParamVarIndex = p_iParamVarIndex;
paramType = p_paramType;
}
LessonElement_t( const LessonElement_t &p_LessonElement )
{
iVariable = p_LessonElement.iVariable;
iAction = p_LessonElement.iAction;
bNot = p_LessonElement.bNot;
bOptionalParam = p_LessonElement.bOptionalParam;
szParam = p_LessonElement.szParam;
iParamVarIndex = p_LessonElement.iParamVarIndex;
paramType = p_LessonElement.paramType;
}
};
struct LessonEvent_t
{
CUtlVector< LessonElement_t > elements;
CGameInstructorSymbol szEventName;
};
class CScriptedIconLesson : public CIconLesson
{
public:
DECLARE_LESSON( CScriptedIconLesson, CIconLesson )
DECLARE_SIMPLE_DATADESC();
virtual ~CScriptedIconLesson( void );
static void PreReadLessonsFromFile( void );
static void Mod_PreReadLessonsFromFile( void );
void Init( void ); // NOT virtual, each constructor calls their own
virtual void InitPrerequisites( void );
virtual void OnOpen( void );
virtual void Update( void );
virtual void SwapOutPlayers( int iOldUserID, int iNewUserID );
virtual void FireGameEvent( IGameEvent *event );
virtual void ProcessOpenGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event );
virtual void ProcessCloseGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event );
virtual void ProcessSuccessGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event );
CUtlVector< LessonEvent_t >& GetOpenEvents( void ) { return m_OpenEvents; }
CUtlVector< LessonEvent_t >& GetCloseEvents( void ) { return m_CloseEvents; }
CUtlVector< LessonEvent_t >& GetSuccessEvents( void ) { return m_SuccessEvents; }
CUtlVector< LessonEvent_t >& GetOnOpenEvents( void ) { return m_OnOpenEvents; }
CUtlVector< LessonEvent_t >& GetUpdateEvents( void ) { return m_UpdateEvents; }
bool ProcessElements( IGameEvent *event, const CUtlVector< LessonElement_t > *pElements );
private:
void InitElementsFromKeys( CUtlVector< LessonElement_t > *pLessonElements, KeyValues *pKey );
void InitElementsFromElements( CUtlVector< LessonElement_t > *pLessonElements, const CUtlVector< LessonElement_t > *pLessonElements2 );
void InitFromKeys( KeyValues *pKey );
bool ProcessElement( IGameEvent *event, const LessonElement_t *pLessonElement, bool bInFailedScope );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, float &bVar, const CGameInstructorSymbol *pchParamName, float fParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, int &bVar, const CGameInstructorSymbol *pchParamName, float fParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, bool &bVar, const CGameInstructorSymbol *pchParamName, float fParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, EHANDLE &hVar, const CGameInstructorSymbol *pchParamName, float fParam, C_BaseEntity *pParam, const char *pchParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, CGameInstructorSymbol *pchVar, const CGameInstructorSymbol *pchParamName, const char *pchParam );
// Implemented per mod so they can have custom actions
bool Mod_ProcessElementAction( int iAction, bool bNot, const char *pchVarName, EHANDLE &hVar, const CGameInstructorSymbol *pchParamName, float fParam, C_BaseEntity *pParam, const char *pchParam, bool &bModHandled );
LessonEvent_t * AddOpenEvent( void );
LessonEvent_t * AddCloseEvent( void );
LessonEvent_t * AddSuccessEvent( void );
LessonEvent_t * AddOnOpenEvent( void );
LessonEvent_t * AddUpdateEvent( void );
private:
static CUtlDict< int, int > LessonActionMap;
EHANDLE m_hLocalPlayer;
float m_fOutput;
CHandle<C_BaseEntity> m_hEntity1;
CHandle<C_BaseEntity> m_hEntity2;
CGameInstructorSymbol m_szString1;
CGameInstructorSymbol m_szString2;
int m_iInteger1;
int m_iInteger2;
float m_fFloat1;
float m_fFloat2;
CUtlVector< CGameInstructorSymbol > m_PrerequisiteNames;
CUtlVector< LessonEvent_t > m_OpenEvents;
CUtlVector< LessonEvent_t > m_CloseEvents;
CUtlVector< LessonEvent_t > m_SuccessEvents;
CUtlVector< LessonEvent_t > m_OnOpenEvents;
CUtlVector< LessonEvent_t > m_UpdateEvents;
float m_fUpdateEventTime;
CScriptedIconLesson *m_pDefaultHolder;
int m_iScopeDepth;
// Need this to get offsets to scripted variables
friend class LessonVariableInfo;
friend int LessonActionFromString( const char *pchName );
};
#endif // _C_BASELESSON_H_

3809
game/client/c_baseplayer.cpp Normal file

File diff suppressed because it is too large Load Diff

1017
game/client/c_baseplayer.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,201 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Core Temp Entity client implementation.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basetempentity.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS(C_BaseTempEntity, DT_BaseTempEntity, CBaseTempEntity);
BEGIN_RECV_TABLE_NOBASE(C_BaseTempEntity, DT_BaseTempEntity)
END_RECV_TABLE()
// Global list of temp entity classes
C_BaseTempEntity *C_BaseTempEntity::s_pTempEntities = NULL;
// Global list of dynamic temp entities
C_BaseTempEntity *C_BaseTempEntity::s_pDynamicEntities = NULL;
//-----------------------------------------------------------------------------
// Purpose: Returns head of list
// Output : CBaseTempEntity * -- head of list
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetDynamicList( void )
{
return s_pDynamicEntities;
}
//-----------------------------------------------------------------------------
// Purpose: Returns head of list
// Output : CBaseTempEntity * -- head of list
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetList( void )
{
return s_pTempEntities;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output :
//-----------------------------------------------------------------------------
C_BaseTempEntity::C_BaseTempEntity( void )
{
// Add to list
m_pNext = s_pTempEntities;
s_pTempEntities = this;
m_pNextDynamic = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output :
//-----------------------------------------------------------------------------
C_BaseTempEntity::~C_BaseTempEntity( void )
{
}
//-----------------------------------------------------------------------------
// Purpose: Get next temp ent in chain
// Output : CBaseTempEntity *
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetNext( void )
{
return m_pNext;
}
//-----------------------------------------------------------------------------
// Purpose: Get next temp ent in chain
// Output : CBaseTempEntity *
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetNextDynamic( void )
{
return m_pNextDynamic;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseTempEntity::Precache( void )
{
// Nothing...
}
//-----------------------------------------------------------------------------
// Purpose: Called at startup to allow temp entities to precache any models/sounds that they need
//-----------------------------------------------------------------------------
void C_BaseTempEntity::PrecacheTempEnts( void )
{
C_BaseTempEntity *te = GetList();
while ( te )
{
te->Precache();
te = te->GetNext();
}
}
//-----------------------------------------------------------------------------
// Purpose: Called at startup and level load to clear out leftover temp entities
//-----------------------------------------------------------------------------
void C_BaseTempEntity::ClearDynamicTempEnts( void )
{
C_BaseTempEntity *next;
C_BaseTempEntity *te = s_pDynamicEntities;
while ( te )
{
next = te->GetNextDynamic();
delete te;
te = next;
}
s_pDynamicEntities = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Called at startup and level load to clear out leftover temp entities
//-----------------------------------------------------------------------------
void C_BaseTempEntity::CheckDynamicTempEnts( void )
{
C_BaseTempEntity *next, *newlist = NULL;
C_BaseTempEntity *te = s_pDynamicEntities;
while ( te )
{
next = te->GetNextDynamic();
if ( te->ShouldDestroy() )
{
delete te;
}
else
{
te->m_pNextDynamic = newlist;
newlist = te;
}
te = next;
}
s_pDynamicEntities = newlist;
}
//-----------------------------------------------------------------------------
// Purpose: Dynamic/non-singleton temp entities are initialized by
// calling into here. They should be added to a list of C_BaseTempEntities so
// that their memory can be deallocated appropriately.
// Input : *pEnt -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_BaseTempEntity::Init( int entnum, int iSerialNum )
{
if ( entnum != -1 )
{
Assert( 0 );
}
// Link into dynamic entity list
m_pNextDynamic = s_pDynamicEntities;
s_pDynamicEntities = this;
return true;
}
void C_BaseTempEntity::Release()
{
Assert( !"C_BaseTempEntity::Release should never be called" );
}
void C_BaseTempEntity::NotifyShouldTransmit( ShouldTransmitState_t state )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bool -
//-----------------------------------------------------------------------------
void C_BaseTempEntity::PreDataUpdate( DataUpdateType_t updateType )
{
// TE's may or may not implement this
}
int C_BaseTempEntity::entindex( void ) const { Assert( 0 ); return 0; }
void C_BaseTempEntity::PostDataUpdate( DataUpdateType_t updateType ) { Assert( 0 ); }
void C_BaseTempEntity::OnPreDataChanged( DataUpdateType_t updateType ) { Assert( 0 ); }
void C_BaseTempEntity::OnDataChanged( DataUpdateType_t updateType ) { Assert( 0 ); }
void C_BaseTempEntity::SetDormant( bool bDormant ) { Assert( 0 ); }
bool C_BaseTempEntity::IsDormant( void ) const { Assert( 0 ); return false; };
void C_BaseTempEntity::ReceiveMessage( int classID, bf_read &msg ) { Assert( 0 ); }
void C_BaseTempEntity::SetDestroyedOnRecreateEntities( void ) { Assert(0); }
void* C_BaseTempEntity::GetDataTableBasePtr()
{
return this;
}

View File

@@ -0,0 +1,123 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef C_BASETEMPENTITY_H
#define C_BASETEMPENTITY_H
#ifdef _WIN32
#pragma once
#endif
#include "client_class.h"
#include "iclientnetworkable.h"
#include "c_recipientfilter.h"
//-----------------------------------------------------------------------------
// Purpose: Base class for TEs. All TEs should derive from this and at
// least implement OnDataChanged to be notified when the TE has been received
// from the server
//-----------------------------------------------------------------------------
class C_BaseTempEntity : public IClientUnknown, public IClientNetworkable
{
public:
DECLARE_CLASS_NOBASE( C_BaseTempEntity );
DECLARE_CLIENTCLASS();
C_BaseTempEntity( void );
virtual ~C_BaseTempEntity( void );
// IClientUnknown implementation.
public:
virtual void SetRefEHandle( const CBaseHandle &handle ) { Assert( false ); }
virtual const CBaseHandle& GetRefEHandle() const { Assert( false ); return *( ( CBaseHandle* )0 ); }
virtual IClientUnknown* GetIClientUnknown() { return this; }
virtual ICollideable* GetCollideable() { return 0; }
virtual IClientNetworkable* GetClientNetworkable() { return this; }
virtual IClientRenderable* GetClientRenderable() { return 0; }
virtual IClientEntity* GetIClientEntity() { return 0; }
virtual C_BaseEntity* GetBaseEntity() { return 0; }
virtual IClientThinkable* GetClientThinkable() { return 0; }
virtual IClientModelRenderable* GetClientModelRenderable() { return 0; }
virtual IClientAlphaProperty* GetClientAlphaProperty() { return 0; }
// IClientNetworkable overrides.
public:
virtual void Release();
virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual void OnDataUnchangedInPVS( void ) { }
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void SetDormant( bool bDormant );
virtual bool IsDormant( void ) const;
virtual int entindex( void ) const;
virtual void ReceiveMessage( int classID, bf_read &msg );
virtual void* GetDataTableBasePtr();
virtual void SetDestroyedOnRecreateEntities( void );
public:
// Dummy for CNetworkVars.
void NetworkStateChanged() {}
void NetworkStateChanged( void *pVar ) {}
virtual bool Init(int entnum, int iSerialNum);
virtual void Precache( void );
// For dynamic entities, return true to allow destruction
virtual bool ShouldDestroy( void ) { return false; };
C_BaseTempEntity *GetNext( void );
// Get list of tempentities
static C_BaseTempEntity *GetList( void );
C_BaseTempEntity *GetNextDynamic( void );
// Determine the color modulation amount
void GetColorModulation( float* color )
{
assert(color);
color[0] = color[1] = color[2] = 1.0f;
}
// Should this object be able to have shadows cast onto it?
virtual bool ShouldReceiveProjectedTextures( int flags ) { return false; }
// Static members
public:
// List of dynamically allocated temp entis
static C_BaseTempEntity *GetDynamicList();
// Called at startup to allow temp entities to precache any models/sounds that they need
static void PrecacheTempEnts( void );
static void ClearDynamicTempEnts( void );
static void CheckDynamicTempEnts( void );
private:
// Next in chain
C_BaseTempEntity *m_pNext;
C_BaseTempEntity *m_pNextDynamic;
// TEs add themselves to this list for the executable.
static C_BaseTempEntity *s_pTempEntities;
static C_BaseTempEntity *s_pDynamicEntities;
};
#endif // C_BASETEMPENTITY_H

View File

@@ -0,0 +1,120 @@
//--------------------------------------------------------------------------------------------------------
// Copyright (c) 2007 Turtle Rock Studios, Inc.
#include "cbase.h"
#include "c_basetoggle.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_BaseToggle, DT_BaseToggle, CBaseToggle )
RecvPropVector( RECVINFO( m_vecFinalDest ) ),
RecvPropInt( RECVINFO( m_movementType ) ),
RecvPropFloat( RECVINFO( m_flMoveTargetTime ) ),
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_BaseToggle )
END_PREDICTION_DATA()
ConVar cl_predict_basetoggles("cl_predict_basetoggles", "1" );
//--------------------------------------------------------------------------------------------------------
// Returns the velocity imparted to players standing on us.
void C_BaseToggle::GetGroundVelocityToApply( Vector &vecGroundVel )
{
vecGroundVel = GetLocalVelocity();
if( !GetPredictable() )
{
vecGroundVel.z = 0.0f; // don't give upward velocity, or it could predict players into the air.
}
}
bool C_BaseToggle::ShouldPredict( void )
{
return cl_predict_basetoggles.GetBool() && (m_movementType == MOVE_TOGGLE_LINEAR);
}
C_BasePlayer *C_BaseToggle::GetPredictionOwner( void )
{
C_BasePlayer *pPlayer = (C_BasePlayer *)m_hPredictionOwner.Get();
if( pPlayer && pPlayer->IsLocalPlayer() )
return pPlayer;
return NULL;
}
bool C_BaseToggle::PredictionIsPhysicallySimulated( void )
{
return (m_movementType == MOVE_TOGGLE_LINEAR);
}
void C_BaseToggle::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
m_vLastNetworked = GetNetworkOrigin();
m_fLastNetworkedTime = gpGlobals->curtime;
if( GetPredictionEligible() && m_bWasPredictingMotion && (m_movementType == MOVE_TOGGLE_NONE) )
{
SetPredictionEligible( false );
ResetLatched();
}
m_bWasPredictingMotion = (m_movementType != MOVE_TOGGLE_NONE);
}
void C_BaseToggle::PhysicsSimulate( void )
{
BaseClass::PhysicsSimulate();
if( GetPredictable() )
{
Vector vOrigin = PredictPosition( GetPredictionOwner()->PredictedServerTime() );
if( vOrigin == m_vecFinalDest )
{
SetLocalVelocity( vec3_origin );
}
SetLocalOrigin( vOrigin );
SetNetworkOrigin( vOrigin );
}
}
Vector C_BaseToggle::PredictPosition( float fCurTime )
{
if( (m_movementType != MOVE_TOGGLE_LINEAR) || m_flMoveTargetTime <= 0.0f )
return GetNetworkOrigin();
if( m_flMoveTargetTime > fCurTime )
{
float fTargetTime = m_flMoveTargetTime;
float fTimeRemaining = fTargetTime - fCurTime;
float fTotalTime = fTargetTime - m_fLastNetworkedTime;
if( fTotalTime <= 0.0f )
return m_vecFinalDest;
float fInterp = fTimeRemaining / fTotalTime;
return (m_vLastNetworked * fInterp) + (m_vecFinalDest * (1.0f - fInterp));
}
else
{
return m_vecFinalDest;
}
}
//--------------------------------------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_BaseButton, DT_BaseButton, CBaseButton )
RecvPropBool( RECVINFO( m_usable ) ),
END_RECV_TABLE()
//--------------------------------------------------------------------------------------------------------
bool C_BaseButton::IsPotentiallyUsable( void )
{
return true;
}

View File

@@ -0,0 +1,99 @@
//--------------------------------------------------------------------------------------------------------
// Copyright (c) 2007 Turtle Rock Studios, Inc.
#if !defined( C_BASETOGGLE_H )
#define C_BASETOGGLE_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
//copy/paste from server subs.cpp
enum togglemovetypes_t
{
MOVE_TOGGLE_NONE = 0,
MOVE_TOGGLE_LINEAR = 1,
MOVE_TOGGLE_ANGULAR = 2,
};
//--------------------------------------------------------------------------------------------------------
class C_BaseToggle: public C_BaseEntity
{
public:
DECLARE_CLASS( C_BaseToggle, C_BaseEntity );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE(); //elevators
virtual void GetGroundVelocityToApply( Vector &vecGroundVel );
virtual bool ShouldPredict( void );
virtual C_BasePlayer *GetPredictionOwner( void );
virtual void PhysicsSimulate( void );
virtual bool PredictionErrorShouldResetLatchedForAllPredictables( void ) { return false; }
virtual bool PredictionIsPhysicallySimulated( void );
virtual void PostDataUpdate( DataUpdateType_t updateType );
Vector PredictPosition( float fCurTime );
EHANDLE m_hPredictionOwner;
Vector m_vLastNetworked;
float m_fLastNetworkedTime;
Vector m_vecFinalDest;
int m_movementType;
float m_flMoveTargetTime;
bool m_bWasPredictingMotion;
};
//--------------------------------------------------------------------------------------------------------
class C_BaseButton: public C_BaseToggle
{
public:
DECLARE_CLASS( C_BaseButton, C_BaseToggle );
DECLARE_CLIENTCLASS();
C_BaseButton()
{
}
virtual bool IsPotentiallyUsable( void );
private:
bool m_usable;
};
//--------------------------------------------------------------------------------------------------------
//
// CButtonTimed - func_button_timed
//
//--------------------------------------------------------------------------------------------------------
class C_ButtonTimed: public C_BaseButton
{
public:
DECLARE_CLASS( C_BaseButton, C_BaseButton );
DECLARE_CLIENTCLASS();
C_ButtonTimed();
const char * GetUseString( void ) const
{
return m_sUseString;
}
const char * GetUseSubString( void ) const
{
return m_sUseSubString;
}
private:
char m_sUseString[64];
char m_sUseSubString[64];
};
#endif // C_BASETOGGLE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client side view model implementation. Responsible for drawing
// the view model.
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASEVIEWMODEL_H
#define C_BASEVIEWMODEL_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseanimating.h"
#include "utlvector.h"
#include "baseviewmodel_shared.h"
#endif // C_BASEVIEWMODEL_H

View File

@@ -0,0 +1,355 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "cbase.h"
#include "dlight.h"
#include "iefx.h"
#include "beam_shared.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CSpotlightTraceCacheEntry
{
public:
CSpotlightTraceCacheEntry()
{
m_origin.Init();
m_radius = -1.0f;
}
bool IsValidFor( const Vector &origin )
{
if ( m_radius > 0 && m_origin.DistToSqr(origin) < 1.0f )
return true;
return false;
}
void Cache( const Vector &origin, const trace_t &tr )
{
m_radius = (tr.endpos - origin).Length();
m_origin = origin;
}
Vector m_origin;
float m_radius;
};
static const int NUM_CACHE_ENTRIES = 64;
class C_BeamSpotLight : public C_BaseEntity
{
public:
DECLARE_CLASS( C_BeamSpotLight, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_BeamSpotLight();
~C_BeamSpotLight();
bool ShouldDraw();
void ClientThink( void );
void OnDataChanged( DataUpdateType_t updateType );
void Release( void );
private:
Vector SpotlightCurrentPos(void);
void SpotlightCreate(void);
void SpotlightDestroy(void);
// Computes render info for a spotlight
void ComputeRenderInfo();
private:
int m_nHaloIndex;
int m_nRotationAxis;
float m_flRotationSpeed;
bool m_bSpotlightOn;
bool m_bHasDynamicLight;
float m_flSpotlightMaxLength;
float m_flSpotlightGoalWidth;
float m_flHDRColorScale;
Vector m_vSpotlightTargetPos;
Vector m_vSpotlightCurrentPos;
Vector m_vSpotlightDir;
CHandle<C_Beam> m_hSpotlight;
float m_flSpotlightCurLength;
float m_flLightScale;
dlight_t* m_pDynamicLight;
float m_lastTime;
CSpotlightTraceCacheEntry *m_pCache;
};
IMPLEMENT_CLIENTCLASS_DT( C_BeamSpotLight, DT_BeamSpotlight, CBeamSpotlight )
RecvPropInt( RECVINFO(m_nHaloIndex) ),
RecvPropBool( RECVINFO(m_bSpotlightOn) ),
RecvPropBool( RECVINFO(m_bHasDynamicLight) ),
RecvPropFloat( RECVINFO(m_flSpotlightMaxLength) ),
RecvPropFloat( RECVINFO(m_flSpotlightGoalWidth) ),
RecvPropFloat( RECVINFO(m_flHDRColorScale) ),
RecvPropInt( RECVINFO(m_nRotationAxis) ),
RecvPropFloat( RECVINFO(m_flRotationSpeed) ),
END_RECV_TABLE()
LINK_ENTITY_TO_CLASS( beam_spotlight, C_BeamSpotLight );
//-----------------------------------------------------------------------------
C_BeamSpotLight::C_BeamSpotLight()
: m_vSpotlightTargetPos( vec3_origin )
, m_vSpotlightCurrentPos( vec3_origin )
, m_vSpotlightDir( vec3_origin )
, m_flSpotlightCurLength( 0.0f )
, m_flLightScale( 100.0f )
, m_pDynamicLight( NULL )
, m_lastTime( 0.0f )
, m_pCache(NULL)
{
}
C_BeamSpotLight::~C_BeamSpotLight()
{
delete[] m_pCache;
}
//-----------------------------------------------------------------------------
bool C_BeamSpotLight::ShouldDraw()
{
return false;
}
//-----------------------------------------------------------------------------
void C_BeamSpotLight::ClientThink( void )
{
float dt = gpGlobals->curtime - m_lastTime;
if ( !m_lastTime )
{
dt = 0.0f;
}
m_lastTime = gpGlobals->curtime;
// ---------------------------------------------------
// If I don't have a spotlight attempt to create one
// ---------------------------------------------------
if ( !m_hSpotlight )
{
if ( m_bSpotlightOn )
{
// Make the spotlight
SpotlightCreate();
}
else
{
SetNextClientThink( CLIENT_THINK_NEVER );
return;
}
}
else if ( !m_bSpotlightOn )
{
SpotlightDestroy();
SetNextClientThink( CLIENT_THINK_NEVER );
return;
}
// update rotation
if ( m_flRotationSpeed != 0.0f )
{
QAngle angles = GetAbsAngles();
angles[m_nRotationAxis] += m_flRotationSpeed * dt;
angles[m_nRotationAxis] = anglemod(angles[m_nRotationAxis]);
if ( !m_pCache )
{
m_pCache = new CSpotlightTraceCacheEntry[NUM_CACHE_ENTRIES];
}
SetAbsAngles( angles );
}
m_vSpotlightCurrentPos = SpotlightCurrentPos();
Assert( m_hSpotlight );
m_hSpotlight->SetStartPos( GetAbsOrigin() );
m_hSpotlight->SetEndPos( m_vSpotlightCurrentPos );
// Avoid sudden change in where beam fades out when cross disconinuities
Vector dir = m_vSpotlightCurrentPos - GetAbsOrigin();
float flBeamLength = VectorNormalize( dir );
m_flSpotlightCurLength = (0.60*m_flSpotlightCurLength) + (0.4*flBeamLength);
ComputeRenderInfo();
m_hSpotlight->RelinkBeam();
//NDebugOverlay::Cross3D(GetAbsOrigin(),Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1);
//NDebugOverlay::Cross3D(m_vSpotlightCurrentPos,Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1);
//NDebugOverlay::Cross3D(m_vSpotlightTargetPos,Vector(-5,-5,-5),Vector(5,5,5),255,0,0,true,0.1);
// Do we need to keep updating?
if ( !GetMoveParent() && m_flRotationSpeed == 0 )
{
// No reason to think again, we're not going to move unless there's a data change
SetNextClientThink( CLIENT_THINK_NEVER );
}
}
//-----------------------------------------------------------------------------
void C_BeamSpotLight::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
m_flSpotlightCurLength = m_flSpotlightMaxLength;
}
// On a data change always think again
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//------------------------------------------------------------------------------
void C_BeamSpotLight::Release()
{
SpotlightDestroy();
BaseClass::Release();
}
//------------------------------------------------------------------------------
void C_BeamSpotLight::SpotlightCreate(void)
{
m_vSpotlightTargetPos = SpotlightCurrentPos();
{
//C_Beam *beam = CBeam::BeamCreate( "sprites/spotlight.vmt", m_flSpotlightGoalWidth );
C_Beam *beam = C_Beam::BeamCreate( "sprites/glow_test02.vmt", m_flSpotlightGoalWidth );
// Beam only exists client side
ClientEntityList().AddNonNetworkableEntity( beam );
m_hSpotlight = beam;
}
// Set the temporary spawnflag on the beam so it doesn't save (we'll recreate it on restore)
m_hSpotlight->SetHDRColorScale( m_flHDRColorScale );
const color24 c = GetRenderColor();
m_hSpotlight->SetColor( c.r, c.g, c.b );
m_hSpotlight->SetHaloTexture(m_nHaloIndex);
m_hSpotlight->SetHaloScale(60);
m_hSpotlight->SetEndWidth(m_flSpotlightGoalWidth);
m_hSpotlight->SetBeamFlags( (FBEAM_SHADEOUT|FBEAM_NOTILE) );
m_hSpotlight->SetBrightness( 64 );
m_hSpotlight->SetNoise( 0 );
m_hSpotlight->PointsInit( GetAbsOrigin(), m_vSpotlightTargetPos );
}
//------------------------------------------------------------------------------
void C_BeamSpotLight::SpotlightDestroy(void)
{
if ( m_hSpotlight )
{
UTIL_Remove( m_hSpotlight );
m_hSpotlight.Term();
}
}
//------------------------------------------------------------------------------
Vector C_BeamSpotLight::SpotlightCurrentPos(void)
{
QAngle angles = GetAbsAngles();
GetVectors( &m_vSpotlightDir, NULL, NULL );
Vector position = GetAbsOrigin();
int cacheIndex = -1;
if ( m_pCache )
{
cacheIndex = int( angles[m_nRotationAxis] * float(NUM_CACHE_ENTRIES) * (1.0f / 360.0f)) & (NUM_CACHE_ENTRIES - 1);
if ( m_pCache[cacheIndex].IsValidFor(GetAbsOrigin()) )
{
return position + m_vSpotlightDir * m_pCache[cacheIndex].m_radius;
}
}
// Get beam end point. Only collide with solid objects, not npcs
trace_t tr;
UTIL_TraceLine( position, position + (m_vSpotlightDir * 2 * m_flSpotlightMaxLength), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
if ( cacheIndex >= 0 )
{
m_pCache[cacheIndex].Cache(position, tr);
}
return tr.endpos;
}
//-----------------------------------------------------------------------------
// Computes render info for a spotlight
//-----------------------------------------------------------------------------
void C_BeamSpotLight::ComputeRenderInfo()
{
// Fade out spotlight end if past max length.
if ( m_flSpotlightCurLength > 2*m_flSpotlightMaxLength )
{
SetRenderAlpha( 0 );
m_hSpotlight->SetFadeLength( m_flSpotlightMaxLength );
}
else if ( m_flSpotlightCurLength > m_flSpotlightMaxLength )
{
SetRenderAlpha( (1-((m_flSpotlightCurLength-m_flSpotlightMaxLength)/m_flSpotlightMaxLength)) );
m_hSpotlight->SetFadeLength( m_flSpotlightMaxLength );
}
else
{
SetRenderAlpha( 1.0 );
m_hSpotlight->SetFadeLength( m_flSpotlightCurLength );
}
// Adjust end width to keep beam width constant
float flNewWidth = m_flSpotlightGoalWidth * (m_flSpotlightCurLength / m_flSpotlightMaxLength);
flNewWidth = clamp(flNewWidth, 0, MAX_BEAM_WIDTH );
m_hSpotlight->SetEndWidth(flNewWidth);
if ( m_bHasDynamicLight )
{
// <<TODO>> - magic number 1.8 depends on sprite size
m_flLightScale = 1.8*flNewWidth;
if ( m_flLightScale > 0 )
{
const color24 c = GetRenderColor();
float a = GetRenderAlpha() / 255.0f;
ColorRGBExp32 color;
color.r = c.r * a;
color.g = c.g * a;
color.b = c.b * a;
color.exponent = 0;
if ( color.r == 0 && color.g == 0 && color.b == 0 )
return;
// Deal with the environment light
if ( !m_pDynamicLight || (m_pDynamicLight->key != index) )
{
m_pDynamicLight = effects->CL_AllocDlight( index );
assert (m_pDynamicLight);
}
//m_pDynamicLight->flags = DLIGHT_NO_MODEL_ILLUMINATION;
m_pDynamicLight->radius = m_flLightScale*3.0f;
m_pDynamicLight->origin = GetAbsOrigin() + Vector(0,0,5);
m_pDynamicLight->die = gpGlobals->curtime + 0.05f;
m_pDynamicLight->color = color;
}
}
}

View File

@@ -0,0 +1,92 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "model_types.h"
#include "vcollide.h"
#include "vcollide_parse.h"
#include "solidsetdefaults.h"
#include "bone_setup.h"
#include "engine/ivmodelinfo.h"
#include "physics.h"
#include "c_breakableprop.h"
#include "view.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
void RecvProxy_UnmodifiedQAngles( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
const float *v = pData->m_Value.m_Vector;
((float*)pOut)[0] = v[0];
((float*)pOut)[1] = v[1];
((float*)pOut)[2] = v[2];
}
IMPLEMENT_CLIENTCLASS_DT(C_BreakableProp, DT_BreakableProp, CBreakableProp)
RecvPropQAngles( RECVINFO( m_qPreferredPlayerCarryAngles ), 0, RecvProxy_UnmodifiedQAngles ),
RecvPropBool( RECVINFO( m_bClientPhysics ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BreakableProp::C_BreakableProp( void )
{
m_takedamage = DAMAGE_YES;
}
//-----------------------------------------------------------------------------
// Copy fade from another breakable prop
//-----------------------------------------------------------------------------
void C_BreakableProp::CopyFadeFrom( C_BreakableProp *pSource )
{
SetGlobalFadeScale( pSource->GetGlobalFadeScale() );
SetDistanceFade( pSource->GetMinFadeDist(), pSource->GetMaxFadeDist() );
}
void C_BreakableProp::OnDataChanged( DataUpdateType_t type )
{
BaseClass::OnDataChanged( type );
if ( m_bClientPhysics )
{
bool bCreate = (type == DATA_UPDATE_CREATED) ? true : false;
VPhysicsShadowDataChanged(bCreate, this);
}
}
//IPlayerPickupVPhysics
bool C_BreakableProp::HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer )
{
return (m_qPreferredPlayerCarryAngles.x < FLT_MAX);
}
QAngle C_BreakableProp::PreferredCarryAngles( void )
{
return (m_qPreferredPlayerCarryAngles.x < FLT_MAX) ? m_qPreferredPlayerCarryAngles : vec3_angle;
}
bool C_BreakableProp::ShouldPredict( void )
{
#ifdef PORTAL
C_BasePlayer *pPredOwner = GetPlayerHoldingEntity( this );
return (pPredOwner && pPredOwner->IsLocalPlayer()) ? true : BaseClass::ShouldPredict();
#else
return false;
#endif
}
C_BasePlayer *C_BreakableProp::GetPredictionOwner( void )
{
#ifdef PORTAL
return GetPlayerHoldingEntity( this );
#else
return NULL;
#endif
}

View File

@@ -0,0 +1,52 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_BREAKABLEPROP_H
#define C_BREAKABLEPROP_H
#ifdef _WIN32
#pragma once
#endif
#include "player_pickup.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_BreakableProp : public C_BaseAnimating, public CDefaultPlayerPickupVPhysics
{
public:
DECLARE_CLASS( C_BreakableProp, C_BaseAnimating );
DECLARE_CLIENTCLASS();
C_BreakableProp();
virtual bool IsProp( void ) const
{
return true;
};
//IPlayerPickupVPhysics
virtual bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer );
virtual QAngle PreferredCarryAngles( void );
virtual bool ShouldPredict( void );
virtual C_BasePlayer *GetPredictionOwner( void );
virtual bool PredictionErrorShouldResetLatchedForAllPredictables( void ) { return false; }
// Copy fade from another breakable prop
void CopyFadeFrom( C_BreakableProp *pSource );
virtual void OnDataChanged( DataUpdateType_t type );
const QAngle &GetNetworkedPreferredPlayerCarryAngles( void ) { return m_qPreferredPlayerCarryAngles; }
protected:
QAngle m_qPreferredPlayerCarryAngles;
private:
bool m_bClientPhysics;
};
#endif // C_BREAKABLEPROP_H

View File

@@ -0,0 +1,251 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Color correction entity with simple radial falloff
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_colorcorrection.h"
#include "filesystem.h"
#include "cdll_client_int.h"
#include "colorcorrectionmgr.h"
#include "materialsystem/MaterialSystemUtil.h"
#include "iclientmode.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static ConVar mat_colcorrection_disableentities( "mat_colcorrection_disableentities", "0", FCVAR_NONE, "Disable map color-correction entities" );
static ConVar mat_colcorrection_forceentitiesclientside( "mat_colcorrection_forceentitiesclientside", "0", FCVAR_CHEAT, "Forces color correction entities to be updated on the client" );
#ifdef CColorCorrection
#undef CColorCorrection
#endif
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrection, DT_ColorCorrection, CColorCorrection)
RecvPropVector( RECVINFO(m_vecOrigin) ),
RecvPropFloat( RECVINFO(m_minFalloff) ),
RecvPropFloat( RECVINFO(m_maxFalloff) ),
RecvPropFloat( RECVINFO(m_flCurWeight) ),
RecvPropFloat( RECVINFO(m_flMaxWeight) ),
RecvPropFloat( RECVINFO(m_flFadeInDuration) ),
RecvPropFloat( RECVINFO(m_flFadeOutDuration) ),
RecvPropString( RECVINFO(m_netLookupFilename) ),
RecvPropBool( RECVINFO(m_bEnabled) ),
RecvPropBool( RECVINFO(m_bMaster) ),
RecvPropBool( RECVINFO(m_bClientSide) ),
RecvPropBool( RECVINFO(m_bExclusive) )
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Constructor, destructor
//------------------------------------------------------------------------------
C_ColorCorrection::C_ColorCorrection()
{
m_minFalloff = -1.0f;
m_maxFalloff = -1.0f;
m_flFadeInDuration = 0.0f;
m_flFadeOutDuration = 0.0f;
m_flCurWeight = 0.0f;
m_flMaxWeight = 1.0f;
m_netLookupFilename[0] = '\0';
m_bEnabled = false;
m_bMaster = false;
m_bExclusive = false;
m_CCHandle = INVALID_CLIENT_CCHANDLE;
for ( int i = 0; i < MAX_SPLITSCREEN_PLAYERS; i++ )
{
m_bEnabledOnClient[i] = false;
m_flCurWeightOnClient[i] = 0.0f;
m_bFadingIn[i] = false;
m_flFadeStartWeight[i] = 0.0f;
m_flFadeStartTime[i] = 0.0f;
m_flFadeDuration[i] = 0.0f;
}
}
C_ColorCorrection::~C_ColorCorrection()
{
g_pColorCorrectionMgr->RemoveColorCorrectionEntity( this, m_CCHandle );
}
bool C_ColorCorrection::IsClientSide() const
{
return m_bClientSide || mat_colcorrection_forceentitiesclientside.GetBool();
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void C_ColorCorrection::OnDataChanged(DataUpdateType_t updateType)
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
{
// forming a unique name without extension
char cleanName[MAX_PATH];
V_StripExtension( m_netLookupFilename, cleanName, sizeof( cleanName ) );
char name[MAX_PATH];
Q_snprintf( name, MAX_PATH, "%s_%d", cleanName, entindex() );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrectionEntity( this, name, m_netLookupFilename );
}
}
}
//------------------------------------------------------------------------------
// We don't draw...
//------------------------------------------------------------------------------
bool C_ColorCorrection::ShouldDraw()
{
return false;
}
void C_ColorCorrection::Update( C_BasePlayer *pPlayer, float ccScale )
{
Assert( m_CCHandle != INVALID_CLIENT_CCHANDLE );
if ( mat_colcorrection_disableentities.GetInt() )
{
// Allow the colorcorrectionui panel (or user) to turn off color-correction entities
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, 0.0f, m_bExclusive );
return;
}
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
bool bEnabled = IsClientSide() ? m_bEnabledOnClient[nSlot] : m_bEnabled;
// fade weight on client
if ( IsClientSide() )
{
m_flCurWeightOnClient[nSlot] = Lerp( GetFadeRatio( nSlot ), m_flFadeStartWeight[nSlot], m_bFadingIn[nSlot] ? m_flMaxWeight : 0.0f );
}
float flCurWeight = IsClientSide() ? m_flCurWeightOnClient[nSlot] : m_flCurWeight;
if( !bEnabled && flCurWeight == 0.0f )
{
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, 0.0f, m_bExclusive );
return;
}
Vector playerOrigin = pPlayer->GetAbsOrigin();
float weight = 0;
if ( ( m_minFalloff != -1 ) && ( m_maxFalloff != -1 ) && m_minFalloff != m_maxFalloff )
{
float dist = (playerOrigin - m_vecOrigin).Length();
weight = (dist-m_minFalloff) / (m_maxFalloff-m_minFalloff);
if ( weight<0.0f ) weight = 0.0f;
if ( weight>1.0f ) weight = 1.0f;
}
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, flCurWeight * ( 1.0 - weight ) * ccScale, m_bExclusive );
}
void C_ColorCorrection::EnableOnClient( bool bEnable, bool bSkipFade )
{
if ( !IsClientSide() )
{
return;
}
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
if( m_bEnabledOnClient[nSlot] == bEnable )
{
return;
}
m_bFadingIn[nSlot] = bEnable;
m_bEnabledOnClient[nSlot] = bEnable;
// initialize countdown timer
m_flFadeStartWeight[nSlot] = m_flCurWeightOnClient[nSlot];
float flFadeTimeScale = 1.0f;
if ( m_flMaxWeight != 0.0f )
{
flFadeTimeScale = m_flCurWeightOnClient[nSlot] / m_flMaxWeight;
}
if ( m_bFadingIn[nSlot] )
{
flFadeTimeScale = 1.0f - flFadeTimeScale;
}
if ( bSkipFade )
{
flFadeTimeScale = 0.0f;
}
StartFade( nSlot, flFadeTimeScale * ( m_bFadingIn[nSlot] ? m_flFadeInDuration : m_flFadeOutDuration ) );
// update the clientside weight once here, in case the fade duration is 0
m_flCurWeightOnClient[nSlot] = Lerp( GetFadeRatio( nSlot ), m_flFadeStartWeight[nSlot], m_bFadingIn[nSlot] ? m_flMaxWeight : 0.0f );
}
Vector C_ColorCorrection::GetOrigin()
{
return m_vecOrigin;
}
float C_ColorCorrection::GetMinFalloff()
{
return m_minFalloff;
}
float C_ColorCorrection::GetMaxFalloff()
{
return m_maxFalloff;
}
void C_ColorCorrection::SetWeight( float fWeight )
{
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, fWeight, false );
}
void C_ColorCorrection::StartFade( int nSplitScreenSlot, float flDuration )
{
m_flFadeStartTime[nSplitScreenSlot] = gpGlobals->curtime;
m_flFadeDuration[nSplitScreenSlot] = MAX( flDuration, 0.0f );
}
float C_ColorCorrection::GetFadeRatio( int nSplitScreenSlot ) const
{
float flRatio = 1.0f;
if ( m_flFadeDuration[nSplitScreenSlot] != 0.0f )
{
flRatio = ( gpGlobals->curtime - m_flFadeStartTime[nSplitScreenSlot] ) / m_flFadeDuration[nSplitScreenSlot];
flRatio = clamp( flRatio, 0.0f, 1.0f );
}
return flRatio;
}
bool C_ColorCorrection::IsFadeTimeElapsed( int nSplitScreenSlot ) const
{
return ( ( gpGlobals->curtime - m_flFadeStartTime[nSplitScreenSlot] ) > m_flFadeDuration[nSplitScreenSlot] ) ||
( ( gpGlobals->curtime - m_flFadeStartTime[nSplitScreenSlot] ) < 0.0f );
}
#ifndef DOTA_DLL
void UpdateColorCorrectionEntities( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrection **pList, int listCount )
{
for ( int i = 0; i < listCount; i++ )
{
pList[i]->Update(pPlayer, ccScale);
}
}
#endif

View File

@@ -0,0 +1,76 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Color correction entity with simple radial falloff
//
// $NoKeywords: $
//===========================================================================//
#ifndef C_COLORCORRECTION_H
#define C_COLORCORRECTION_H
#ifdef _WIN32
#pragma once
#endif
#include "colorcorrectionmgr.h"
//------------------------------------------------------------------------------
// Purpose : Color correction entity with radial falloff
//------------------------------------------------------------------------------
class C_ColorCorrection : public C_BaseEntity
{
public:
DECLARE_CLASS( C_ColorCorrection, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_ColorCorrection();
virtual ~C_ColorCorrection();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
virtual void Update(C_BasePlayer *pPlayer, float ccScale);
bool IsMaster() const { return m_bMaster; }
bool IsClientSide() const;
bool IsExclusive() const { return m_bExclusive; }
void EnableOnClient( bool bEnable, bool bSkipFade = false );
Vector GetOrigin();
float GetMinFalloff();
float GetMaxFalloff();
void SetWeight( float fWeight );
protected:
void StartFade( int nSplitScreenSlot, float flDuration );
float GetFadeRatio( int nSplitScreenSlot ) const;
bool IsFadeTimeElapsed( int nSplitScreenSlot ) const;
Vector m_vecOrigin;
float m_minFalloff;
float m_maxFalloff;
float m_flFadeInDuration;
float m_flFadeOutDuration;
float m_flMaxWeight;
float m_flCurWeight; // networked from server
char m_netLookupFilename[MAX_PATH];
bool m_bEnabled; // networked from server
bool m_bMaster;
bool m_bClientSide;
bool m_bExclusive;
bool m_bEnabledOnClient[MAX_SPLITSCREEN_PLAYERS];
float m_flCurWeightOnClient[MAX_SPLITSCREEN_PLAYERS];
bool m_bFadingIn[MAX_SPLITSCREEN_PLAYERS];
float m_flFadeStartWeight[MAX_SPLITSCREEN_PLAYERS];
float m_flFadeStartTime[MAX_SPLITSCREEN_PLAYERS];
float m_flFadeDuration[MAX_SPLITSCREEN_PLAYERS];
ClientCCHandle_t m_CCHandle;
};
#endif

View File

@@ -0,0 +1,204 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Color correction entity.
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "filesystem.h"
#include "cdll_client_int.h"
#include "materialsystem/MaterialSystemUtil.h"
#include "colorcorrectionmgr.h"
#include "c_triggers.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//------------------------------------------------------------------------------
// FIXME: This really should inherit from something more lightweight
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Purpose : Shadow control entity
//------------------------------------------------------------------------------
class C_ColorCorrectionVolume : public C_BaseTrigger
{
public:
DECLARE_CLASS( C_ColorCorrectionVolume, C_BaseTrigger );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
C_ColorCorrectionVolume();
virtual ~C_ColorCorrectionVolume();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
void Update( C_BasePlayer *pPlayer, float ccScale );
void StartTouch( C_BaseEntity *pOther );
void EndTouch( C_BaseEntity *pOther );
private:
float m_LastEnterWeight;
float m_LastEnterTime;
float m_LastExitWeight;
float m_LastExitTime;
bool m_bEnabled;
float m_MaxWeight;
float m_FadeDuration;
float m_Weight;
char m_lookupFilename[MAX_PATH];
ClientCCHandle_t m_CCHandle;
};
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrectionVolume, DT_ColorCorrectionVolume, CColorCorrectionVolume)
RecvPropBool( RECVINFO(m_bEnabled) ),
RecvPropFloat( RECVINFO(m_MaxWeight) ),
RecvPropFloat( RECVINFO(m_FadeDuration) ),
RecvPropFloat( RECVINFO(m_Weight) ),
RecvPropString( RECVINFO(m_lookupFilename) ),
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_ColorCorrectionVolume )
DEFINE_PRED_FIELD( m_Weight, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()
//------------------------------------------------------------------------------
// Constructor, destructor
//------------------------------------------------------------------------------
C_ColorCorrectionVolume::C_ColorCorrectionVolume()
{
m_CCHandle = INVALID_CLIENT_CCHANDLE;
}
C_ColorCorrectionVolume::~C_ColorCorrectionVolume()
{
g_pColorCorrectionMgr->RemoveColorCorrectionVolume( this, m_CCHandle );
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void C_ColorCorrectionVolume::OnDataChanged(DataUpdateType_t updateType)
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
{
// forming a unique name without extension
char cleanName[MAX_PATH];
V_StripExtension( m_lookupFilename, cleanName, sizeof( cleanName ) );
char name[MAX_PATH];
Q_snprintf( name, MAX_PATH, "%s_%d", cleanName, entindex() );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrectionVolume( this, name, m_lookupFilename );
SetSolid( SOLID_BSP );
SetSolidFlags( FSOLID_TRIGGER | FSOLID_NOT_SOLID );
}
}
}
//------------------------------------------------------------------------------
// We don't draw...
//------------------------------------------------------------------------------
bool C_ColorCorrectionVolume::ShouldDraw()
{
return false;
}
//--------------------------------------------------------------------------------------------------------
void C_ColorCorrectionVolume::StartTouch( CBaseEntity *pEntity )
{
m_LastEnterTime = gpGlobals->curtime;
m_LastEnterWeight = m_Weight;
}
//--------------------------------------------------------------------------------------------------------
void C_ColorCorrectionVolume::EndTouch( CBaseEntity *pEntity )
{
m_LastExitTime = gpGlobals->curtime;
m_LastExitWeight = m_Weight;
}
void C_ColorCorrectionVolume::Update( C_BasePlayer *pPlayer, float ccScale )
{
if ( pPlayer )
{
bool isTouching = CollisionProp()->IsPointInBounds( pPlayer->EyePosition() );
bool wasTouching = m_LastEnterTime > m_LastExitTime;
if ( isTouching && !wasTouching )
{
StartTouch( pPlayer );
}
else if ( !isTouching && wasTouching )
{
EndTouch( pPlayer );
}
}
if( !m_bEnabled )
{
m_Weight = 0.0f;
}
else
{
if( m_LastEnterTime > m_LastExitTime )
{
// we most recently entered the volume
if( m_Weight < 1.0f )
{
float dt = gpGlobals->curtime - m_LastEnterTime;
float weight = m_LastEnterWeight + dt / ((1.0f-m_LastEnterWeight)*m_FadeDuration);
if( weight>1.0f )
weight = 1.0f;
m_Weight = weight;
}
}
else
{
// we most recently exitted the volume
if( m_Weight > 0.0f )
{
float dt = gpGlobals->curtime - m_LastExitTime;
float weight = (1.0f-m_LastExitWeight) + dt / (m_LastExitWeight*m_FadeDuration);
if( weight>1.0f )
weight = 1.0f;
m_Weight = 1.0f - weight;
}
}
}
// Vector entityPosition = GetAbsOrigin();
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_Weight * ccScale );
}
void UpdateColorCorrectionVolumes( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrectionVolume **pList, int listCount )
{
for ( int i = 0; i < listCount; i++ )
{
pList[i]->Update(pPlayer, ccScale);
}
}

View File

@@ -0,0 +1,239 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Dynamic light
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "dlight.h"
#include "iefx.h"
#include "iviewrender.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if HL2_EPISODIC
// In Episodic we unify the NO_WORLD_ILLUMINATION lights to use
// the more efficient elight structure instead. This should theoretically
// be extended to other projects but may have unintended consequences
// and bears more thorough testing.
//
// For an earlier iteration on this technique see changelist 214433,
// which had a specific flag for use of elights.
#define DLIGHT_NO_WORLD_USES_ELIGHT 1
#endif
//-----------------------------------------------------------------------------
// A dynamic light, with the goofy hack needed for spotlights
//-----------------------------------------------------------------------------
class C_DynamicLight : public C_BaseEntity
{
public:
DECLARE_CLASS( C_DynamicLight, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_DynamicLight();
public:
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
void ClientThink( void );
void Release( void );
unsigned char m_Flags;
unsigned char m_LightStyle;
float m_Radius;
int m_Exponent;
float m_InnerAngle;
float m_OuterAngle;
float m_SpotRadius;
private:
dlight_t* m_pDynamicLight;
dlight_t* m_pSpotlightEnd;
inline bool ShouldBeElight() { return (m_Flags & DLIGHT_NO_WORLD_ILLUMINATION); }
};
IMPLEMENT_CLIENTCLASS_DT(C_DynamicLight, DT_DynamicLight, CDynamicLight)
RecvPropInt (RECVINFO(m_Flags)),
RecvPropInt (RECVINFO(m_LightStyle)),
RecvPropFloat (RECVINFO(m_Radius)),
RecvPropInt (RECVINFO(m_Exponent)),
RecvPropFloat (RECVINFO(m_InnerAngle)),
RecvPropFloat (RECVINFO(m_OuterAngle)),
RecvPropFloat (RECVINFO(m_SpotRadius)),
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
C_DynamicLight::C_DynamicLight(void) : m_pSpotlightEnd(0), m_pDynamicLight(0)
{
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
void C_DynamicLight::OnDataChanged(DataUpdateType_t updateType)
{
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink(gpGlobals->curtime + 0.05);
}
BaseClass::OnDataChanged( updateType );
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
bool C_DynamicLight::ShouldDraw()
{
return false;
}
//------------------------------------------------------------------------------
// Purpose : Disable drawing of this light when entity perishes
//------------------------------------------------------------------------------
void C_DynamicLight::Release()
{
if (m_pDynamicLight)
{
m_pDynamicLight->die = gpGlobals->curtime;
m_pDynamicLight = 0;
}
if (m_pSpotlightEnd)
{
m_pSpotlightEnd->die = gpGlobals->curtime;
m_pSpotlightEnd = 0;
}
BaseClass::Release();
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
void C_DynamicLight::ClientThink(void)
{
Vector forward;
AngleVectors( GetAbsAngles(), &forward );
if ( (m_Flags & DLIGHT_NO_MODEL_ILLUMINATION) == 0 )
{
// Deal with the model light
if ( !m_pDynamicLight || (m_pDynamicLight->key != index) )
{
#if DLIGHT_NO_WORLD_USES_ELIGHT
m_pDynamicLight = ShouldBeElight() != 0
? effects->CL_AllocElight( index )
: effects->CL_AllocDlight( index );
#else
m_pDynamicLight = effects->CL_AllocDlight( index );
#endif
Assert (m_pDynamicLight);
m_pDynamicLight->minlight = 0;
}
m_pDynamicLight->style = m_LightStyle;
m_pDynamicLight->radius = m_Radius;
m_pDynamicLight->flags = m_Flags;
if ( m_OuterAngle > 0 )
m_pDynamicLight->flags |= DLIGHT_NO_WORLD_ILLUMINATION;
color24 c = GetRenderColor();
m_pDynamicLight->color.r = c.r;
m_pDynamicLight->color.g = c.g;
m_pDynamicLight->color.b = c.b;
m_pDynamicLight->color.exponent = m_Exponent; // this makes it match the world
m_pDynamicLight->origin = GetAbsOrigin();
m_pDynamicLight->m_InnerAngle = m_InnerAngle;
m_pDynamicLight->m_OuterAngle = m_OuterAngle;
m_pDynamicLight->die = gpGlobals->curtime + 1e6;
m_pDynamicLight->m_Direction = forward;
}
else
{
// In this case, the m_Flags could have changed; which is how we turn the light off
if (m_pDynamicLight)
{
m_pDynamicLight->die = gpGlobals->curtime;
m_pDynamicLight = 0;
}
}
#if DLIGHT_NO_WORLD_USES_ELIGHT
if (( m_OuterAngle > 0 ) && !ShouldBeElight())
#else
if (( m_OuterAngle > 0 ) && ((m_Flags & DLIGHT_NO_WORLD_ILLUMINATION) == 0))
#endif
{
// Raycast to where the endpoint goes
// Deal with the environment light
if ( !m_pSpotlightEnd || (m_pSpotlightEnd->key != -index) )
{
m_pSpotlightEnd = effects->CL_AllocDlight( -index );
Assert (m_pSpotlightEnd);
}
// Trace a line outward, don't use hitboxes (too slow)
Vector end;
VectorMA( GetAbsOrigin(), m_Radius, forward, end );
trace_t pm;
C_BaseEntity::PushEnableAbsRecomputations( false ); // HACK don't recompute positions while doing RayTrace
UTIL_TraceLine( GetAbsOrigin(), end, MASK_NPCWORLDSTATIC, NULL, COLLISION_GROUP_NONE, &pm );
C_BaseEntity::PopEnableAbsRecomputations();
VectorCopy( pm.endpos, m_pSpotlightEnd->origin );
if (pm.fraction == 1.0f)
{
m_pSpotlightEnd->die = gpGlobals->curtime;
m_pSpotlightEnd = 0;
}
else
{
float falloff = 1.0 - pm.fraction;
falloff *= falloff;
m_pSpotlightEnd->style = m_LightStyle;
m_pSpotlightEnd->flags = DLIGHT_NO_MODEL_ILLUMINATION | (m_Flags & DLIGHT_DISPLACEMENT_MASK);
m_pSpotlightEnd->radius = m_SpotRadius; // * falloff;
m_pSpotlightEnd->die = gpGlobals->curtime + 1e6;
color24 c = GetRenderColor();
m_pSpotlightEnd->color.r = c.r * falloff;
m_pSpotlightEnd->color.g = c.g * falloff;
m_pSpotlightEnd->color.b = c.b * falloff;
m_pSpotlightEnd->color.exponent = m_Exponent;
// For bumped lighting
m_pSpotlightEnd->m_Direction = forward;
// Update list of surfaces we influence
render->TouchLight( m_pSpotlightEnd );
}
}
else
{
// In this case, the m_Flags could have changed; which is how we turn the light off
if (m_pSpotlightEnd)
{
m_pSpotlightEnd->die = gpGlobals->curtime;
m_pSpotlightEnd = 0;
}
}
SetNextClientThink(gpGlobals->curtime + 0.001);
}

2670
game/client/c_effects.cpp Normal file

File diff suppressed because it is too large Load Diff

210
game/client/c_effects.h Normal file
View File

@@ -0,0 +1,210 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_EFFECTS_H
#define C_EFFECTS_H
#ifdef _WIN32
#pragma once
#endif
#include "cbase.h"
#include "precipitation_shared.h"
// Draw rain effects.
void DrawPrecipitation();
//-----------------------------------------------------------------------------
// Precipitation particle type
//-----------------------------------------------------------------------------
class CPrecipitationParticle
{
public:
Vector m_Pos;
Vector m_Velocity;
float m_SpawnTime; // Note: Tweak with this to change lifetime
float m_Mass;
float m_Ramp;
float m_flMaxLifetime;
int m_nSplitScreenPlayerSlot;
};
class CClient_Precipitation;
static CUtlVector<CClient_Precipitation*> g_Precipitations;
//===========
// Snow fall
//===========
class CSnowFallManager;
static CSnowFallManager *s_pSnowFallMgr[ MAX_SPLITSCREEN_PLAYERS ];
bool SnowFallManagerCreate( CClient_Precipitation *pSnowEntity );
void SnowFallManagerDestroy( void );
class AshDebrisEffect : public CSimpleEmitter
{
public:
explicit AshDebrisEffect( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
static AshDebrisEffect* Create( const char *pDebugName );
virtual float UpdateAlpha( const SimpleParticle *pParticle );
virtual float UpdateRoll( SimpleParticle *pParticle, float timeDelta );
private:
AshDebrisEffect( const AshDebrisEffect & );
};
//-----------------------------------------------------------------------------
// Precipitation blocker entity
//-----------------------------------------------------------------------------
class C_PrecipitationBlocker : public C_BaseEntity
{
public:
DECLARE_CLASS( C_PrecipitationBlocker, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_PrecipitationBlocker();
virtual ~C_PrecipitationBlocker();
};
//-----------------------------------------------------------------------------
// Precipitation base entity
//-----------------------------------------------------------------------------
class CClient_Precipitation : public C_BaseEntity
{
class CPrecipitationEffect;
friend class CClient_Precipitation::CPrecipitationEffect;
public:
DECLARE_CLASS( CClient_Precipitation, C_BaseEntity );
DECLARE_CLIENTCLASS();
CClient_Precipitation();
virtual ~CClient_Precipitation();
// Inherited from C_BaseEntity
virtual void Precache( );
virtual RenderableTranslucencyType_t ComputeTranslucencyType() { return RENDERABLE_IS_TRANSLUCENT; }
void Render();
// Computes where we're gonna emit
bool ComputeEmissionArea( Vector& origin, Vector2D& size, C_BaseCombatCharacter *pCharacter );
private:
// Creates a single particle
CPrecipitationParticle* CreateParticle();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink();
void Simulate( float dt );
// Renders the particle
void RenderParticle( CPrecipitationParticle* pParticle, CMeshBuilder &mb );
void CreateWaterSplashes();
// Emits the actual particles
void EmitParticles( float fTimeDelta );
// Gets the tracer width and speed
float GetWidth() const;
float GetLength() const;
float GetSpeed() const;
// Gets the remaining lifetime of the particle
float GetRemainingLifetime( CPrecipitationParticle* pParticle ) const;
// Computes the wind vector
static void ComputeWindVector( );
// simulation methods
bool SimulateRain( CPrecipitationParticle* pParticle, float dt );
bool SimulateSnow( CPrecipitationParticle* pParticle, float dt );
void CreateParticlePrecip( void );
void InitializeParticlePrecip( void );
void DispatchOuterParticlePrecip( int nSlot, C_BasePlayer *pPlayer, Vector vForward );
void DispatchInnerParticlePrecip( int nSlot, C_BasePlayer *pPlayer, Vector vForward );
void DestroyOuterParticlePrecip( int nSlot );
void DestroyInnerParticlePrecip( int nSlot );
void UpdateParticlePrecip( C_BasePlayer *pPlayer, int nSlot );
float GetDensity() { return m_flDensity; }
private:
void CreateAshParticle( void );
void CreateRainOrSnowParticle( const Vector &vSpawnPosition, const Vector &vEndPosition, const Vector &vVelocity ); // TERROR: adding end pos for lifetime calcs
// Information helpful in creating and rendering particles
IMaterial *m_MatHandle; // material used
float m_Color[4]; // precip color
float m_Lifetime; // Precip lifetime
float m_InitialRamp; // Initial ramp value
float m_Speed; // Precip speed
float m_Width; // Tracer width
float m_Remainder; // particles we should render next time
PrecipitationType_t m_nPrecipType; // Precip type
float m_flHalfScreenWidth; // Precalculated each frame.
float m_flDensity;
#ifdef INFESTED_DLL
int m_nSnowDustAmount;
#endif
// Some state used in rendering and simulation
// Used to modify the rain density and wind from the console
static ConVar s_raindensity;
static ConVar s_rainwidth;
static ConVar s_rainlength;
static ConVar s_rainspeed;
static Vector s_WindVector; // Stores the wind speed vector
CUtlLinkedList<CPrecipitationParticle> m_Particles;
CUtlVector<Vector> m_Splashes;
struct AshSplit_t
{
AshSplit_t() : m_bActiveAshEmitter( false ), m_vAshSpawnOrigin( 0, 0, 0 ), m_iAshCount( 0 )
{
}
CSmartPtr<AshDebrisEffect> m_pAshEmitter;
TimedEvent m_tAshParticleTimer;
TimedEvent m_tAshParticleTraceTimer;
bool m_bActiveAshEmitter;
Vector m_vAshSpawnOrigin;
int m_iAshCount;
};
protected:
AshSplit_t m_Ash[ MAX_SPLITSCREEN_PLAYERS ];
float m_flParticleInnerDist; //The distance at which to start drawing the inner system
char *m_pParticleInnerNearDef; //Name of the first inner system
char *m_pParticleInnerFarDef; //Name of the second inner system
char *m_pParticleOuterDef; //Name of the outer system
HPARTICLEFFECT m_pParticlePrecipInnerNear[ MAX_SPLITSCREEN_PLAYERS ];
HPARTICLEFFECT m_pParticlePrecipInnerFar[ MAX_SPLITSCREEN_PLAYERS ];
HPARTICLEFFECT m_pParticlePrecipOuter[ MAX_SPLITSCREEN_PLAYERS ];
TimedEvent m_tParticlePrecipTraceTimer[ MAX_SPLITSCREEN_PLAYERS ];
bool m_bActiveParticlePrecipEmitter[ MAX_SPLITSCREEN_PLAYERS ];
bool m_bParticlePrecipInitialized;
private:
CClient_Precipitation( const CClient_Precipitation & ); // not defined, not accessible
};
#endif // C_EFFECTS_H

View File

@@ -0,0 +1,788 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "iviewrender.h"
#include "view.h"
#include "studio.h"
#include "bone_setup.h"
#include "model_types.h"
#include "beamdraw.h"
#include "engine/ivdebugoverlay.h"
#include "iviewrender_beams.h"
#include "fx.h"
#include "IEffects.h"
#include "c_entitydissolve.h"
#include "movevars_shared.h"
#include "precache_register.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
ConVar cl_portal_use_new_dissolve( "cl_portal_use_new_dissolve", "1", FCVAR_CHEAT, "Use new dissolve effect" );
PRECACHE_REGISTER_BEGIN( GLOBAL, PrecacheEffectBuild )
PRECACHE( MATERIAL,"effects/tesla_glow_noz" )
PRECACHE( MATERIAL,"effects/spark" )
PRECACHE( MATERIAL,"effects/combinemuzzle2" )
PRECACHE( PARTICLE_SYSTEM, "dissolve" )
PRECACHE_REGISTER_END()
//-----------------------------------------------------------------------------
// Networking
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EntityDissolve, DT_EntityDissolve, CEntityDissolve )
RecvPropTime(RECVINFO(m_flStartTime)),
RecvPropFloat(RECVINFO(m_flFadeOutStart)),
RecvPropFloat(RECVINFO(m_flFadeOutLength)),
RecvPropFloat(RECVINFO(m_flFadeOutModelStart)),
RecvPropFloat(RECVINFO(m_flFadeOutModelLength)),
RecvPropFloat(RECVINFO(m_flFadeInStart)),
RecvPropFloat(RECVINFO(m_flFadeInLength)),
RecvPropInt(RECVINFO(m_nDissolveType)),
RecvPropVector( RECVINFO( m_vDissolverOrigin) ),
RecvPropInt( RECVINFO( m_nMagnitude ) ),
END_RECV_TABLE()
extern PMaterialHandle g_Material_Spark;
PMaterialHandle g_Material_AR2Glow = NULL;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CEG_NOINLINE C_EntityDissolve::C_EntityDissolve( void )
{
m_bLinkedToServerEnt = true;
CEG_PROTECT_MEMBER_FUNCTION( C_EntityDissolve_C_EntityDissolve );
m_pController = NULL;
m_bCoreExplode = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolve::GetRenderBounds( Vector& theMins, Vector& theMaxs )
{
if ( GetMoveParent() )
{
GetMoveParent()->GetRenderBounds( theMins, theMaxs );
}
else
{
theMins = GetAbsOrigin();
theMaxs = theMaxs;
}
}
//-----------------------------------------------------------------------------
// On data changed
//-----------------------------------------------------------------------------
void C_EntityDissolve::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
m_flNextSparkTime = m_flStartTime;
SetNextClientThink( CLIENT_THINK_ALWAYS );
if ( cl_portal_use_new_dissolve.GetBool() )
DispatchParticleEffect( "dissolve", PATTACH_ABSORIGIN_FOLLOW, GetMoveParent() );
}
}
//-----------------------------------------------------------------------------
// Cleanup
//-----------------------------------------------------------------------------
void C_EntityDissolve::UpdateOnRemove( void )
{
if ( m_pController )
{
physenv->DestroyMotionController( m_pController );
m_pController = NULL;
}
BaseClass::UpdateOnRemove();
}
//------------------------------------------------------------------------------
// Apply the forces to the entity
//------------------------------------------------------------------------------
IMotionEvent::simresult_e C_EntityDissolve::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular )
{
linear.Init();
angular.Init();
// Make it zero g
linear.z -= -1.02 * sv_gravity.GetFloat();
Vector vel;
AngularImpulse angVel;
pObject->GetVelocity( &vel, &angVel );
vel += linear * deltaTime; // account for gravity scale
Vector unitVel = vel;
Vector unitAngVel = angVel;
float speed = VectorNormalize( unitVel );
// float angSpeed = VectorNormalize( unitAngVel );
// float speedScale = 0.0;
// float angSpeedScale = 0.0;
float flLinearLimit = 50;
float flLinearLimitDelta = 40;
if ( speed > flLinearLimit )
{
float flDeltaVel = (flLinearLimit - speed) / deltaTime;
if ( flLinearLimitDelta != 0.0f )
{
float flMaxDeltaVel = -flLinearLimitDelta / deltaTime;
if ( flDeltaVel < flMaxDeltaVel )
{
flDeltaVel = flMaxDeltaVel;
}
}
VectorMA( linear, flDeltaVel, unitVel, linear );
}
return SIM_GLOBAL_ACCELERATION;
}
//-----------------------------------------------------------------------------
// Tesla effect
//-----------------------------------------------------------------------------
static void FX_BuildTesla( C_BaseEntity *pEntity, Vector &vecOrigin, Vector &vecEnd )
{
BeamInfo_t beamInfo;
beamInfo.m_pStartEnt = pEntity;
beamInfo.m_nStartAttachment = 0;
beamInfo.m_pEndEnt = NULL;
beamInfo.m_nEndAttachment = 0;
beamInfo.m_nType = TE_BEAMTESLA;
beamInfo.m_vecStart = vecOrigin;
beamInfo.m_vecEnd = vecEnd;
beamInfo.m_pszModelName = "sprites/lgtning.vmt";
beamInfo.m_flHaloScale = 0.0;
beamInfo.m_flLife = random->RandomFloat( 0.25f, 1.0f );
beamInfo.m_flWidth = random->RandomFloat( 8.0f, 14.0f );
beamInfo.m_flEndWidth = 1.0f;
beamInfo.m_flFadeLength = 0.5f;
beamInfo.m_flAmplitude = 24;
beamInfo.m_flBrightness = 255.0;
beamInfo.m_flSpeed = 150.0f;
beamInfo.m_nStartFrame = 0.0;
beamInfo.m_flFrameRate = 30.0;
beamInfo.m_flRed = 255.0;
beamInfo.m_flGreen = 255.0;
beamInfo.m_flBlue = 255.0;
beamInfo.m_nSegments = 18;
beamInfo.m_bRenderable = true;
beamInfo.m_nFlags = 0; //FBEAM_ONLYNOISEONCE;
beams->CreateBeamEntPoint( beamInfo );
}
//-----------------------------------------------------------------------------
// Purpose: Tesla effect
//-----------------------------------------------------------------------------
void C_EntityDissolve::BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset )
{
Vector vecOrigin;
QAngle vecAngles;
MatrixGetColumn( hitboxToWorld, 3, vecOrigin );
MatrixAngles( hitboxToWorld, vecAngles.Base() );
C_BaseEntity *pEntity = GetMoveParent();
// Make a couple of tries at it
int iTries = -1;
Vector vecForward;
trace_t tr;
do
{
iTries++;
// Some beams are deliberatly aimed around the point, the rest are random.
if ( !bRandom )
{
QAngle vecTemp = vecAngles;
vecTemp[YAW] += flYawOffset;
AngleVectors( vecTemp, &vecForward );
// Randomly angle it up or down
vecForward.z = RandomFloat( -1, 1 );
}
else
{
vecForward = RandomVector( -1, 1 );
}
UTIL_TraceLine( vecOrigin, vecOrigin + (vecForward * 192), MASK_SHOT, pEntity, COLLISION_GROUP_NONE, &tr );
} while ( tr.fraction >= 1.0 && iTries < 3 );
Vector vecEnd = tr.endpos - (vecForward * 8);
// Only spark & glow if we hit something
if ( tr.fraction < 1.0 )
{
if ( !EffectOccluded( tr.endpos ) )
{
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
// Move it towards the camera
Vector vecFlash = tr.endpos;
Vector vecForward;
AngleVectors( MainViewAngles(nSlot), &vecForward );
vecFlash -= (vecForward * 8);
g_pEffects->EnergySplash( vecFlash, -vecForward, false );
// End glow
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" );
pSimple->SetSortOrigin( vecFlash );
SimpleParticle *pParticle;
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/tesla_glow_noz" ), vecFlash );
if ( pParticle != NULL )
{
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = RandomFloat( 0.5, 1 );
pParticle->m_vecVelocity = vec3_origin;
Vector color( 1,1,1 );
float colorRamp = RandomFloat( 0.75f, 1.25f );
pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
pParticle->m_uchStartSize = RandomFloat( 6,13 );
pParticle->m_uchEndSize = pParticle->m_uchStartSize - 2;
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 10;
pParticle->m_flRoll = RandomFloat( 0,360 );
pParticle->m_flRollDelta = 0;
}
}
}
// Build the tesla
FX_BuildTesla( pEntity, vecOrigin, tr.endpos );
}
//-----------------------------------------------------------------------------
// Sorts the components of a vector
//-----------------------------------------------------------------------------
static inline void SortAbsVectorComponents( const Vector& src, int* pVecIdx )
{
Vector absVec( fabs(src[0]), fabs(src[1]), fabs(src[2]) );
int maxIdx = (absVec[0] > absVec[1]) ? 0 : 1;
if (absVec[2] > absVec[maxIdx])
{
maxIdx = 2;
}
// always choose something right-handed....
switch( maxIdx )
{
case 0:
pVecIdx[0] = 1;
pVecIdx[1] = 2;
pVecIdx[2] = 0;
break;
case 1:
pVecIdx[0] = 2;
pVecIdx[1] = 0;
pVecIdx[2] = 1;
break;
case 2:
pVecIdx[0] = 0;
pVecIdx[1] = 1;
pVecIdx[2] = 2;
break;
}
}
//-----------------------------------------------------------------------------
// Compute the bounding box's center, size, and basis
//-----------------------------------------------------------------------------
void C_EntityDissolve::ComputeRenderInfo( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld,
Vector *pVecAbsOrigin, Vector *pXVec, Vector *pYVec )
{
// Compute the center of the hitbox in worldspace
Vector vecHitboxCenter;
VectorAdd( pHitBox->bbmin, pHitBox->bbmax, vecHitboxCenter );
vecHitboxCenter *= 0.5f;
VectorTransform( vecHitboxCenter, hitboxToWorld, *pVecAbsOrigin );
// Get the object's basis
Vector vec[3];
MatrixGetColumn( hitboxToWorld, 0, vec[0] );
MatrixGetColumn( hitboxToWorld, 1, vec[1] );
MatrixGetColumn( hitboxToWorld, 2, vec[2] );
// vec[1] *= -1.0f;
Vector vecViewDir;
VectorSubtract( CurrentViewOrigin(), *pVecAbsOrigin, vecViewDir );
VectorNormalize( vecViewDir );
// Project the shadow casting direction into the space of the hitbox
Vector localViewDir;
localViewDir[0] = DotProduct( vec[0], vecViewDir );
localViewDir[1] = DotProduct( vec[1], vecViewDir );
localViewDir[2] = DotProduct( vec[2], vecViewDir );
// Figure out which vector has the largest component perpendicular
// to the view direction...
// Sort by how perpendicular it is
int vecIdx[3];
SortAbsVectorComponents( localViewDir, vecIdx );
// Here's our hitbox basis vectors; namely the ones that are
// most perpendicular to the view direction
*pXVec = vec[vecIdx[0]];
*pYVec = vec[vecIdx[1]];
// Project them into a plane perpendicular to the view direction
*pXVec -= vecViewDir * DotProduct( vecViewDir, *pXVec );
*pYVec -= vecViewDir * DotProduct( vecViewDir, *pYVec );
VectorNormalize( *pXVec );
VectorNormalize( *pYVec );
// Compute the hitbox size
Vector boxSize;
VectorSubtract( pHitBox->bbmax, pHitBox->bbmin, boxSize );
// We project the two longest sides into the vectors perpendicular
// to the projection direction, then add in the projection of the perp direction
Vector2D size( boxSize[vecIdx[0]], boxSize[vecIdx[1]] );
size.x *= fabs( DotProduct( vec[vecIdx[0]], *pXVec ) );
size.y *= fabs( DotProduct( vec[vecIdx[1]], *pYVec ) );
// Add the third component into x and y
size.x += boxSize[vecIdx[2]] * fabs( DotProduct( vec[vecIdx[2]], *pXVec ) );
size.y += boxSize[vecIdx[2]] * fabs( DotProduct( vec[vecIdx[2]], *pYVec ) );
// Bloat a bit, since the shadow wants to extend outside the model a bit
size *= 2.0f;
// Clamp the minimum size
Vector2DMax( size, Vector2D(10.0f, 10.0f), size );
// Factor the size into the xvec + yvec
(*pXVec) *= size.x * 0.5f;
(*pYVec) *= size.y * 0.5f;
}
//-----------------------------------------------------------------------------
// Sparks!
//-----------------------------------------------------------------------------
void C_EntityDissolve::DoSparks( mstudiohitboxset_t *set, matrix3x4_t *hitboxbones[MAXSTUDIOBONES] )
{
if ( m_flNextSparkTime > gpGlobals->curtime )
return;
float dt = m_flStartTime + m_flFadeOutStart - gpGlobals->curtime;
dt = clamp( dt, 0.0f, m_flFadeOutStart );
float flNextTime;
if (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL)
{
flNextTime = SimpleSplineRemapVal( dt, 0.0f, m_flFadeOutStart, 2.0f * TICK_INTERVAL, 0.4f );
}
else
{
// m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT);
flNextTime = SimpleSplineRemapVal( dt, 0.0f, m_flFadeOutStart, 0.3f, 1.0f );
}
m_flNextSparkTime = gpGlobals->curtime + flNextTime;
// Send out beams around us
int iNumBeamsAround = 2;
int iNumRandomBeams = 1;
int iTotalBeams = iNumBeamsAround + iNumRandomBeams;
float flYawOffset = RandomFloat(0,360);
for ( int i = 0; i < iTotalBeams; i++ )
{
int nHitbox = random->RandomInt( 0, set->numhitboxes - 1 );
mstudiobbox_t *pBox = set->pHitbox(nHitbox);
float flActualYawOffset = 0;
bool bRandom = ( i >= iNumBeamsAround );
if ( !bRandom )
{
flActualYawOffset = anglemod( flYawOffset + ((360 / iTotalBeams) * i) );
}
BuildTeslaEffect( pBox, *hitboxbones[pBox->bone], bRandom, flActualYawOffset );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolve::SetupEmitter( void )
{
if ( !m_pEmitter )
{
m_pEmitter = CSimpleEmitter::Create( "C_EntityDissolve" );
m_pEmitter->SetSortOrigin( GetAbsOrigin() );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolve::GetFadeInPercentage( void )
{
float dt = gpGlobals->curtime - m_flStartTime;
if ( dt > m_flFadeOutStart )
return 1.0f;
if ( dt < m_flFadeInStart )
return 0.0f;
if ( (dt > m_flFadeInStart) && (dt < m_flFadeInStart + m_flFadeInLength) )
{
dt -= m_flFadeInStart;
return ( dt / m_flFadeInLength );
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolve::GetFadeOutPercentage( void )
{
float dt = gpGlobals->curtime - m_flStartTime;
if ( dt < m_flFadeInStart )
return 1.0f;
if ( dt > m_flFadeOutStart )
{
dt -= m_flFadeOutStart;
RANDOM_CEG_TEST_SECRET();
if ( dt > m_flFadeOutLength )
return 0.0f;
return 1.0f - ( dt / m_flFadeOutLength );
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolve::GetModelFadeOutPercentage( void )
{
float dt = gpGlobals->curtime - m_flStartTime;
if ( dt < m_flFadeOutModelStart )
return 1.0f;
if ( dt > m_flFadeOutModelStart )
{
dt -= m_flFadeOutModelStart;
if ( dt > m_flFadeOutModelLength )
return 0.0f;
return 1.0f - ( dt / m_flFadeOutModelLength );
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolve::ClientThink( void )
{
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
if (!pAnimating)
return;
// NOTE: IsRagdoll means *client-side* ragdoll. We shouldn't be trying to fight
// the server ragdoll (or any server physics) on the client
if (( !m_pController ) && ( m_nDissolveType == ENTITY_DISSOLVE_NORMAL ) && pAnimating->IsRagdoll())
{
IPhysicsObject *ppList[VPHYSICS_MAX_OBJECT_LIST_COUNT];
int nCount = pAnimating->VPhysicsGetObjectList( ppList, ARRAYSIZE(ppList) );
if ( nCount > 0 )
{
m_pController = physenv->CreateMotionController( this );
for ( int i = 0; i < nCount; ++i )
{
m_pController->AttachObject( ppList[i], true );
}
}
}
color32 color;
color.r = color.g = color.b = ( 1.0f - GetFadeInPercentage() ) * 255.0f;
color.a = GetModelFadeOutPercentage() * 255.0f;
// Setup the entity fade
pAnimating->SetRenderMode( kRenderTransColor );
pAnimating->SetRenderColor( color.r, color.g, color.b );
pAnimating->SetRenderAlpha( color.a );
if ( GetModelFadeOutPercentage() <= 0.2f )
{
m_bCoreExplode = true;
}
// If we're dead, fade out
if ( GetFadeOutPercentage() <= 0.0f )
{
// Do NOT remove from the client entity list. It'll confuse the local network backdoor, and the entity will never get destroyed
// because when the server says to destroy it, the client won't be able to find it.
// ClientEntityList().RemoveEntity( GetClientHandle() );
::partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() );
RemoveFromLeafSystem();
//FIXME: Ick!
//Adrian: I'll assume we don't need the ragdoll either so I'll remove that too.
if ( m_bLinkedToServerEnt == false )
{
Release();
C_ClientRagdoll *pRagdoll = dynamic_cast <C_ClientRagdoll *> ( pAnimating );
if ( pRagdoll )
{
pRagdoll->ReleaseRagdoll();
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : flags -
// Output : int
//-----------------------------------------------------------------------------
int C_EntityDissolve::DrawModel( int flags, const RenderableInstance_t &instance )
{
if ( !cl_portal_use_new_dissolve.GetBool() )
{
// See if we should draw
if ( gpGlobals->frametime == 0 || m_bReadyToDraw == false )
return 0;
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
if ( pAnimating == NULL )
return 0;
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) == false )
return 0;
studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
if ( pStudioHdr == NULL )
return false;
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );
if ( set == NULL )
return false;
// Make sure the emitter is setup properly
SetupEmitter();
// Get fade percentages for the effect
float fadeInPerc = GetFadeInPercentage();
float fadeOutPerc = GetFadeOutPercentage();
float fadePerc = ( fadeInPerc >= 1.0f ) ? fadeOutPerc : fadeInPerc;
Vector vecSkew = vec3_origin;
// Do extra effects under certain circumstances
if ( ( fadePerc < 0.99f ) && ( (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) ) )
{
DoSparks( set, hitboxbones );
}
// Skew the particles in front or in back of their targets
vecSkew = CurrentViewForward() * ( 8.0f - ( ( 1.0f - fadePerc ) * 32.0f ) );
float spriteScale = ( ( gpGlobals->curtime - m_flStartTime ) / m_flFadeOutLength );
spriteScale = clamp( spriteScale, 0.75f, 1.0f );
// Cache off this material reference
if ( g_Material_Spark == NULL )
{
g_Material_Spark = ParticleMgr()->GetPMaterial( "effects/spark" );
}
if ( g_Material_AR2Glow == NULL )
{
g_Material_AR2Glow = ParticleMgr()->GetPMaterial( "effects/combinemuzzle2" );
}
SimpleParticle *sParticle;
for ( int i = 0; i < set->numhitboxes; ++i )
{
Vector vecAbsOrigin, xvec, yvec;
mstudiobbox_t *pBox = set->pHitbox(i);
ComputeRenderInfo( pBox, *hitboxbones[pBox->bone], &vecAbsOrigin, &xvec, &yvec );
Vector offset;
Vector xDir, yDir;
xDir = xvec;
float xScale = VectorNormalize( xDir ) * 0.75f;
yDir = yvec;
float yScale = VectorNormalize( yDir ) * 0.75f;
int numParticles = clamp( 3.0f * fadePerc, 0, 3 );
int iTempParts = 2;
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
numParticles = 15;
iTempParts = 20;
}
}
for ( int j = 0; j < iTempParts; j++ )
{
// Skew the origin
offset = xDir * Helper_RandomFloat( -xScale*0.5f, xScale*0.5f ) + yDir * Helper_RandomFloat( -yScale*0.5f, yScale*0.5f );
offset += vecSkew;
if ( random->RandomInt( 0, 2 ) != 0 )
continue;
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), g_Material_Spark, vecAbsOrigin + offset );
if ( sParticle == NULL )
return 1;
sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( 16.0f, 64.0f ) );
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
Vector vDirection = (vecAbsOrigin + offset) - m_vDissolverOrigin;
VectorNormalize( vDirection );
sParticle->m_vecVelocity = vDirection * m_nMagnitude;
}
}
if ( sParticle->m_vecVelocity.z > 0 )
{
sParticle->m_uchStartSize = random->RandomFloat( 4, 6 ) * spriteScale;
}
else
{
sParticle->m_uchStartSize = 2 * spriteScale;
}
sParticle->m_flDieTime = random->RandomFloat( 0.4f, 0.5f );
// If we're the last particles, last longer
if ( numParticles == 0 )
{
sParticle->m_flDieTime *= 2.0f;
sParticle->m_uchStartSize = 2 * spriteScale;
sParticle->m_flRollDelta = Helper_RandomFloat( -4.0f, 4.0f );
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
sParticle->m_flDieTime *= 2.0f;
sParticle->m_flRollDelta = Helper_RandomFloat( -1.0f, 1.0f );
}
}
}
else
{
sParticle->m_flRollDelta = Helper_RandomFloat( -8.0f, 8.0f );
}
sParticle->m_flLifetime = 0.0f;
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
float alpha = 255;
sParticle->m_uchColor[0] = alpha;
sParticle->m_uchColor[1] = alpha;
sParticle->m_uchColor[2] = alpha;
sParticle->m_uchStartAlpha = alpha;
sParticle->m_uchEndAlpha = 0;
sParticle->m_uchEndSize = 0;
}
for ( int j = 0; j < numParticles; j++ )
{
offset = xDir * Helper_RandomFloat( -xScale*0.5f, xScale*0.5f ) + yDir * Helper_RandomFloat( -yScale*0.5f, yScale*0.5f );
offset += vecSkew;
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), g_Material_AR2Glow, vecAbsOrigin + offset );
if ( sParticle == NULL )
return 1;
sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -64.0f, 128.0f ) );
sParticle->m_uchStartSize = random->RandomFloat( 8, 12 ) * spriteScale;
sParticle->m_flDieTime = 0.1f;
sParticle->m_flLifetime = 0.0f;
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
sParticle->m_flRollDelta = Helper_RandomFloat( -2.0f, 2.0f );
float alpha = 255;
sParticle->m_uchColor[0] = alpha;
sParticle->m_uchColor[1] = alpha;
sParticle->m_uchColor[2] = alpha;
sParticle->m_uchStartAlpha = alpha;
sParticle->m_uchEndAlpha = 0;
sParticle->m_uchEndSize = 0;
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
Vector vDirection = (vecAbsOrigin + offset) - m_vDissolverOrigin;
VectorNormalize( vDirection );
sParticle->m_vecVelocity = vDirection * m_nMagnitude;
sParticle->m_flDieTime = 0.5f;
}
}
}
}
}
return 1;
}

View File

@@ -0,0 +1,77 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef C_ENTITY_DISSOLVE_H
#define C_ENTITY_DISSOLVE_H
#include "cbase.h"
//-----------------------------------------------------------------------------
// Entity Dissolve, client-side implementation
//-----------------------------------------------------------------------------
class C_EntityDissolve : public C_BaseEntity, public IMotionEvent
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityDissolve, C_BaseEntity );
C_EntityDissolve( void );
// Inherited from C_BaseEntity
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
virtual bool ShouldDraw() { return true; }
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void UpdateOnRemove( void );
// Inherited from IMotionEvent
virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular );
void SetupEmitter( void );
void ClientThink( void );
void SetServerLinkState( bool state ) { m_bLinkedToServerEnt = state; }
float m_flStartTime;
float m_flFadeOutStart;
float m_flFadeOutLength;
float m_flFadeOutModelStart;
float m_flFadeOutModelLength;
float m_flFadeInStart;
float m_flFadeInLength;
int m_nDissolveType;
float m_flNextSparkTime;
Vector m_vDissolverOrigin;
int m_nMagnitude;
bool m_bCoreExplode;
protected:
float GetFadeInPercentage( void ); // Fade in amount (entity fading to black)
float GetFadeOutPercentage( void ); // Fade out amount (particles fading away)
float GetModelFadeOutPercentage( void );// Mode fade out amount
// Compute the bounding box's center, size, and basis
void ComputeRenderInfo( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld,
Vector *pVecAbsOrigin, Vector *pXVec, Vector *pYVec );
void BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset );
void DoSparks( mstudiohitboxset_t *set, matrix3x4_t *hitboxbones[MAXSTUDIOBONES] );
private:
CSmartPtr<CSimpleEmitter> m_pEmitter;
bool m_bLinkedToServerEnt;
IPhysicsMotionController *m_pController;
};
#endif // C_ENTITY_DISSOLVE_H

View File

@@ -0,0 +1,156 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_entityflame.h"
#include "particle_property.h"
#include "iefx.h"
#include "dlight.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Datadesc
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EntityFlame, DT_EntityFlame, CEntityFlame )
RecvPropEHandle(RECVINFO(m_hEntAttached)),
RecvPropBool(RECVINFO(m_bCheapEffect)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EntityFlame::C_EntityFlame( void ) : m_hEffect( NULL )
{
m_hOldAttached = NULL;
AddToEntityList( ENTITY_LIST_SIMULATE );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EntityFlame::~C_EntityFlame( void )
{
StopEffect();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlame::StopEffect( void )
{
if ( m_hEffect )
{
ParticleProp()->StopEmission( m_hEffect, true );
m_hEffect = NULL;
}
if ( m_hEntAttached )
{
m_hEntAttached->RemoveFlag( FL_ONFIRE );
m_hEntAttached->SetEffectEntity( NULL );
m_hEntAttached->StopSound( "General.BurningFlesh" );
m_hEntAttached->StopSound( "General.BurningObject" );
m_hEntAttached = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlame::UpdateOnRemove( void )
{
StopEffect();
BaseClass::UpdateOnRemove();
}
void C_EntityFlame::CreateEffect( void )
{
if ( m_hEffect )
{
m_hOldAttached = m_hEntAttached;
ParticleProp()->StopEmission( m_hEffect, true );
m_hEffect = NULL;
}
C_BaseEntity *pEntity = m_hEntAttached;
if ( pEntity && !pEntity->IsAbleToHaveFireEffect() )
return;
m_hEffect = ParticleProp()->Create( m_bCheapEffect ? "burning_gib_01" : "burning_character", PATTACH_ABSORIGIN_FOLLOW );
if ( m_hEffect )
{
m_hOldAttached = m_hEntAttached;
ParticleProp()->AddControlPoint( m_hEffect, 1, pEntity, PATTACH_ABSORIGIN_FOLLOW );
m_hEffect->SetControlPoint( 0, GetAbsOrigin() );
m_hEffect->SetControlPoint( 1, GetAbsOrigin() );
m_hEffect->SetControlPointEntity( 0, pEntity );
m_hEffect->SetControlPointEntity( 1, pEntity );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlame::OnDataChanged( DataUpdateType_t updateType )
{
if ( updateType == DATA_UPDATE_CREATED )
{
CreateEffect();
}
// FIXME: This is a bit of a shady path
if ( updateType == DATA_UPDATE_DATATABLE_CHANGED )
{
// If our owner changed, then recreate the effect
if ( m_hEntAttached != m_hOldAttached )
{
CreateEffect();
}
}
BaseClass::OnDataChanged( updateType );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_EntityFlame::Simulate( void )
{
if ( gpGlobals->frametime <= 0.0f )
return true;
#ifdef HL2_EPISODIC
if ( IsEffectActive(EF_BRIGHTLIGHT) || IsEffectActive(EF_DIMLIGHT) )
{
dlight_t *dl = effects->CL_AllocDlight( index );
dl->origin = GetAbsOrigin();
dl->origin[2] += 16;
dl->color.r = 254;
dl->color.g = 174;
dl->color.b = 10;
dl->radius = random->RandomFloat(400,431);
dl->die = gpGlobals->curtime + 0.001;
}
#endif // HL2_EPISODIC
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlame::ClientThink( void )
{
StopEffect();
Release();
}

View File

@@ -0,0 +1,43 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef C_ENTITY_FLAME_H
#define C_ENTITY_FLAME_H
#include "c_baseentity.h"
//
// Entity flame, client-side implementation
//
class C_EntityFlame : public C_BaseEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityFlame, C_BaseEntity );
C_EntityFlame( void );
virtual ~C_EntityFlame( void );
virtual bool Simulate( void );
virtual void UpdateOnRemove( void );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
EHANDLE m_hEntAttached; // The entity that we are burning (attached to).
private:
void CreateEffect( void );
void StopEffect( void );
CUtlReference<CNewParticleEffect> m_hEffect;
EHANDLE m_hOldAttached;
bool m_bCheapEffect;
};
#endif // C_ENTITY_FLAME_H

View File

@@ -0,0 +1,288 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_entityfreezing.h"
#include "studio.h"
#include "bone_setup.h"
#include "c_surfacerender.h"
#include "engine/ivdebugoverlay.h"
#include "dt_utlvector_recv.h"
#include "debugoverlay_shared.h"
#include "animation.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
ConVar cl_blobulator_freezing_max_metaball_radius( "cl_blobulator_freezing_max_metaball_radius",
#ifdef INFESTED_DLL
"25.0", // Don't need as much precision in Alien swarm because everything is zoomed out
#else
"12.0",
#endif
FCVAR_NONE, "Setting this can create more complex surfaces on large hitboxes at the cost of performance.", true, 12.0f, true, 100.0f );
//PRECACHE_REGISTER_BEGIN( GLOBAL, PrecacheEffectFreezing )
// PRECACHE( MATERIAL,"effects/tesla_glow_noz" )
// PRECACHE( MATERIAL,"effects/spark" )
// PRECACHE( MATERIAL,"effects/combinemuzzle2" )
//PRECACHE_REGISTER_END()
//-----------------------------------------------------------------------------
// Networking
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EntityFreezing, DT_EntityFreezing, CEntityFreezing )
RecvPropVector( RECVINFO(m_vFreezingOrigin) ),
RecvPropArray3( RECVINFO_ARRAY(m_flFrozenPerHitbox), RecvPropFloat( RECVINFO( m_flFrozenPerHitbox[0] ) ) ),
RecvPropFloat( RECVINFO(m_flFrozen) ),
RecvPropBool( RECVINFO(m_bFinishFreezing) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFreezing::GetRenderBounds( Vector& theMins, Vector& theMaxs )
{
if ( GetMoveParent() )
{
GetMoveParent()->GetRenderBounds( theMins, theMaxs );
}
else
{
theMins = GetAbsOrigin();
theMaxs = theMaxs;
}
}
//-----------------------------------------------------------------------------
// Yes we bloody are
//-----------------------------------------------------------------------------
RenderableTranslucencyType_t C_EntityFreezing::ComputeTranslucencyType( )
{
return RENDERABLE_IS_TRANSLUCENT;
}
//-----------------------------------------------------------------------------
// On data changed
//-----------------------------------------------------------------------------
void C_EntityFreezing::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFreezing::ClientThink( void )
{
#ifdef _PS3
__nop();
#elif defined(LINUX)
#elif defined( __clang__ )
asm("nop");
#elif defined( _WIN32 ) && !defined( WIN64 )
__asm nop;
#endif
//C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
//if (!pAnimating)
// return;
//color32 color = pAnimating->GetRenderColor();
//color.r = color.g = ( 1.0f - m_flFrozen ) * 255.0f;
//// Setup the entity fade
//pAnimating->SetRenderMode( kRenderTransColor );
//pAnimating->SetRenderColor( color.r, color.g, color.b, color.a );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : flags -
// Output : int
//-----------------------------------------------------------------------------
int C_EntityFreezing::DrawModel( int flags, const RenderableInstance_t &instance )
{
#ifdef USE_BLOBULATOR
// See if we should draw
if ( m_bReadyToDraw == false )
return 0;
// The parent needs to be a base animating
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
if ( pAnimating == NULL )
return 0;
// Make sure we have hitboxes
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) == false )
return 0;
studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
if ( pStudioHdr == NULL )
return 0;
int nEffectsHitboxSet = FindHitboxSetByName( pAnimating->GetModelPtr(), "effects" );
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( nEffectsHitboxSet != -1 ? nEffectsHitboxSet : pAnimating->GetHitboxSet() );
if ( !set )
return 0;
// FIXME: No idea how many particles we'll need, so let's start with 1000
g_SurfaceRenderParticles.SetCount( 1000 );
int iNumParticles = 0;
for ( int i = 0; i < set->numhitboxes; ++i )
{
mstudiobbox_t *pBox = set->pHitbox(i);
matrix3x4_t matBone = *hitboxbones[ pBox->bone ];
Vector vecHorizontal = pBox->bbmax - pBox->bbmin;
// Get the particle radius
float flShortestAxis = MIN( MIN( vecHorizontal.x, vecHorizontal.y ), vecHorizontal.z );
float flDiameter = clamp( flShortestAxis, 1.0f, cl_blobulator_freezing_max_metaball_radius.GetFloat() );
float flRadius = flDiameter * 0.5f;
float flVarience = flRadius * 0.25f;
float flRadiusIsoSurface = flRadius / 12.0f;
// Get the hitbox data
EntityFreezingHitboxBlobData_t *pHitboxBlobData = NULL;
if ( m_HitboxBlobData.Count() <= i )
{
// We don't have data for this hitbox yet, so build need relative point positions that are along its faces
int nNewHitboxBlobData = m_HitboxBlobData.AddToTail();
pHitboxBlobData = &(m_HitboxBlobData[ nNewHitboxBlobData ]);
// Start in the min corner
Vector vecStartPoint = pBox->bbmin + ReplicateToVector( flRadius * 0.5f );
Vector vecEndPoint = pBox->bbmax - ReplicateToVector( flRadius * 0.5f );
Vector vecPoint;
bool bEdgeX = true;
vecPoint.x = vecStartPoint.x;
// Loop across each axis
while ( vecPoint.x <= vecEndPoint.x )
{
bool bEdgeY = true;
vecPoint.y = vecStartPoint.y;
while ( vecPoint.y <= vecEndPoint.y )
{
bool bEdgeZ = true;
vecPoint.z = vecStartPoint.z;
while ( vecPoint.z <= vecEndPoint.z )
{
// Only add particles not in the middle of the box
if ( bEdgeX || bEdgeY || bEdgeZ )
{
int nNewPoint = pHitboxBlobData->m_vPoints.AddToTail();
pHitboxBlobData->m_vPoints[ nNewPoint ] = vecPoint + RandomVector( -flVarience, flVarience );
}
// Make sure the final particles don't stick out past the edge
bEdgeZ = ( vecPoint.z < vecEndPoint.z && ( ( !bEdgeX && !bEdgeY ) || vecPoint.z + flRadius >= vecEndPoint.z ) );
if ( bEdgeZ )
{
vecPoint.z = vecEndPoint.z;
}
else
{
vecPoint.z += flRadius;
}
}
// Make sure the final particles don't stick out past the edge
bEdgeY = ( vecPoint.y < vecEndPoint.y && vecPoint.y + flRadius >= vecEndPoint.y );
if ( bEdgeY )
{
vecPoint.y = vecEndPoint.y;
}
else
{
vecPoint.y += flRadius;
}
}
// Make sure the final particles don't stick out past the edge
bEdgeX = ( vecPoint.x < vecEndPoint.x && vecPoint.x + flRadius >= vecEndPoint.x );
if ( bEdgeX )
{
vecPoint.x = vecEndPoint.x;
}
else
{
vecPoint.x += flRadius;
}
}
}
else
{
pHitboxBlobData = &(m_HitboxBlobData[ i ]);
}
// Decide which of the hitbox points to draw based on how frozen the hitbox is and transform them into worldspace
for ( int nPoint = 0; nPoint < pHitboxBlobData->m_vPoints.Count() && iNumParticles < 1000; ++nPoint )
{
// Fast out if the min Z surrounding this hitbox is above the cut off height
Vector vecBoxAbsMins, vecBoxAbsMaxs;
TransformAABB( matBone, pBox->bbmin, pBox->bbmax, vecBoxAbsMins, vecBoxAbsMaxs );
if ( m_bFinishFreezing )
{
m_flFrozenPerHitbox[ i ] = MIN( 1.0f, m_flFrozenPerHitbox[ i ] + gpGlobals->frametime * 0.75f );
}
if ( m_flFrozenPerHitbox[ i ] <= 0.0f )
{
// No particles will be below the freezing line, skip this hitbox
continue;
}
float fCutOffHeight = vecBoxAbsMins.z + ( vecBoxAbsMaxs.z - vecBoxAbsMins.z ) * m_flFrozenPerHitbox[ i ];
// Get the point in worldspace
Vector vecTransformedPoint;
VectorTransform( pHitboxBlobData->m_vPoints[ nPoint ], matBone, vecTransformedPoint );
// Only add particles below this height and if it's not in the middle of the box
if ( vecTransformedPoint.z < fCutOffHeight )
{
ImpParticleWithOneInterpolant* imp_particle = &(g_SurfaceRenderParticles[ iNumParticles ]);
imp_particle->center = vecTransformedPoint;
imp_particle->setFieldScale( flRadiusIsoSurface );
imp_particle->interpolants1.set( 1.0f, 1.0f, 1.0f );
imp_particle->interpolants1[ 3 ] = 0.0f;
++iNumParticles;
}
}
}
g_SurfaceRenderParticles.SetCountNonDestructively( iNumParticles );
// Set up lighting
modelrender->SetupLighting( GetRenderOrigin() );
Surface_Draw( GetClientRenderable(), GetRenderOrigin(), materials->FindMaterial( "models/weapons/w_icegun/ice_surface", TEXTURE_GROUP_OTHER, true ), 6.5f );
#endif
return 1;
}

View File

@@ -0,0 +1,47 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ENTITY_FREEZING_H
#define C_ENTITY_FREEZING_H
#include "cbase.h"
struct EntityFreezingHitboxBlobData_t
{
CUtlVector<Vector> m_vPoints;
};
//-----------------------------------------------------------------------------
// Entity Dissolve, client-side implementation
//-----------------------------------------------------------------------------
class C_EntityFreezing : public C_BaseEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityFreezing, C_BaseEntity );
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
virtual RenderableTranslucencyType_t ComputeTranslucencyType( );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
virtual bool ShouldDraw() { return true; }
virtual void OnDataChanged( DataUpdateType_t updateType );
void ClientThink( void );
private:
Vector m_vFreezingOrigin;
float m_flFrozenPerHitbox[ 50 ];
float m_flFrozen;
bool m_bFinishFreezing;
CUtlVector<EntityFreezingHitboxBlobData_t> m_HitboxBlobData;
};
#endif // C_ENTITY_FREEZING_H

View File

@@ -0,0 +1,250 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "baseparticleentity.h"
#include "entityparticletrail_shared.h"
#include "particlemgr.h"
#include "particle_util.h"
#include "particles_simple.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Entity particle trail, client-side implementation
//-----------------------------------------------------------------------------
class C_EntityParticleTrail : public C_BaseParticleEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityParticleTrail, C_BaseParticleEntity );
C_EntityParticleTrail( );
~C_EntityParticleTrail( );
// C_BaseEntity
virtual void OnDataChanged( DataUpdateType_t updateType );
// IParticleEffect
void Update( float fTimeDelta );
virtual void RenderParticles( CParticleRenderIterator *pIterator );
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
private:
C_EntityParticleTrail( const C_EntityParticleTrail & ); // not defined, not accessible
void Start( );
void AddParticle( float flInitialDeltaTime, const Vector &vecMins, const Vector &vecMaxs, const matrix3x4_t &boxToWorld );
int m_iMaterialName;
EntityParticleTrailInfo_t m_Info;
EHANDLE m_hConstraintEntity;
PMaterialHandle m_hMaterial;
TimedEvent m_teParticleSpawn;
};
//-----------------------------------------------------------------------------
// Networking
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EntityParticleTrail, DT_EntityParticleTrail, CEntityParticleTrail )
RecvPropInt(RECVINFO(m_iMaterialName)),
RecvPropDataTable( RECVINFO_DT( m_Info ), 0, &REFERENCE_RECV_TABLE(DT_EntityParticleTrailInfo) ),
RecvPropEHandle(RECVINFO(m_hConstraintEntity)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EntityParticleTrail::C_EntityParticleTrail( void )
{
}
C_EntityParticleTrail::~C_EntityParticleTrail()
{
ParticleMgr()->RemoveEffect( &m_ParticleEffect );
}
//-----------------------------------------------------------------------------
// On data changed
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
Start( );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticleMgr -
// *pArgs -
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::Start( )
{
if( ParticleMgr()->AddEffect( &m_ParticleEffect, this ) == false )
return;
const char *pMaterialName = GetMaterialNameFromIndex( m_iMaterialName );
if ( !pMaterialName )
return;
m_hMaterial = ParticleMgr()->GetPMaterial( pMaterialName );
m_teParticleSpawn.Init( 150 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::AddParticle( float flInitialDeltaTime, const Vector &vecMins, const Vector &vecMaxs, const matrix3x4_t &boxToWorld )
{
// Select a random point somewhere in the hitboxes of the entity.
Vector vecLocalPosition, vecWorldPosition;
vecLocalPosition.x = Lerp( random->RandomFloat( 0.0f, 1.0f ), vecMins.x, vecMaxs.x );
vecLocalPosition.y = Lerp( random->RandomFloat( 0.0f, 1.0f ), vecMins.y, vecMaxs.y );
vecLocalPosition.z = Lerp( random->RandomFloat( 0.0f, 1.0f ), vecMins.z, vecMaxs.z );
VectorTransform( vecLocalPosition, boxToWorld, vecWorldPosition );
// Don't emit the particle unless it's inside the model
if ( m_hConstraintEntity.Get() )
{
Ray_t ray;
trace_t tr;
ray.Init( vecWorldPosition, vecWorldPosition );
enginetrace->ClipRayToEntity( ray, MASK_ALL, m_hConstraintEntity, &tr );
if ( !tr.startsolid )
return;
}
// Make a new particle
SimpleParticle *pParticle = (SimpleParticle *)m_ParticleEffect.AddParticle( sizeof(SimpleParticle), m_hMaterial );
if ( pParticle == NULL )
return;
pParticle->m_Pos = vecWorldPosition;
pParticle->m_flRoll = Helper_RandomInt( 0, 360 );
pParticle->m_flRollDelta = Helper_RandomFloat( -2.0f, 2.0f );
pParticle->m_flLifetime = flInitialDeltaTime;
pParticle->m_flDieTime = m_Info.m_flLifetime;
pParticle->m_uchColor[0] = 64;
pParticle->m_uchColor[1] = 140;
pParticle->m_uchColor[2] = 225;
pParticle->m_uchStartAlpha = Helper_RandomInt( 64, 64 );
pParticle->m_uchEndAlpha = 0;
pParticle->m_uchStartSize = m_Info.m_flStartSize;
pParticle->m_uchEndSize = m_Info.m_flEndSize;
pParticle->m_vecVelocity = vec3_origin;
VectorMA( pParticle->m_Pos, flInitialDeltaTime, pParticle->m_vecVelocity, pParticle->m_Pos );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : fTimeDelta -
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::Update( float fTimeDelta )
{
float tempDelta = fTimeDelta;
studiohdr_t *pStudioHdr;
mstudiohitboxset_t *set;
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
C_BaseEntity *pMoveParent = GetMoveParent();
if ( !pMoveParent )
return;
C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating();
if (!pAnimating)
goto trailNoHitboxes;
if ( !pAnimating->HitboxToWorldTransforms( hitboxbones ) )
goto trailNoHitboxes;
pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
if (!pStudioHdr)
goto trailNoHitboxes;
set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );
if ( !set )
goto trailNoHitboxes;
//Add new particles
while ( m_teParticleSpawn.NextEvent( tempDelta ) )
{
int nHitbox = random->RandomInt( 0, set->numhitboxes - 1 );
mstudiobbox_t *pBox = set->pHitbox(nHitbox);
AddParticle( tempDelta, pBox->bbmin, pBox->bbmax, *hitboxbones[pBox->bone] );
}
return;
trailNoHitboxes:
while ( m_teParticleSpawn.NextEvent( tempDelta ) )
{
AddParticle( tempDelta, pMoveParent->CollisionProp()->OBBMins(), pMoveParent->CollisionProp()->OBBMaxs(), pMoveParent->EntityToWorldTransform() );
}
}
inline void C_EntityParticleTrail::RenderParticles( CParticleRenderIterator *pIterator )
{
const SimpleParticle *pParticle = (const SimpleParticle*)pIterator->GetFirst();
while ( pParticle )
{
float t = pParticle->m_flLifetime / pParticle->m_flDieTime;
// Render
Vector tPos;
TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos );
float sortKey = tPos.z;
Vector color = Vector( pParticle->m_uchColor[0] / 255.0f, pParticle->m_uchColor[1] / 255.0f, pParticle->m_uchColor[2] / 255.0f );
float alpha = Lerp( t, pParticle->m_uchStartAlpha / 255.0f, pParticle->m_uchEndAlpha / 255.0f );
float flSize = Lerp( t, pParticle->m_uchStartSize, pParticle->m_uchEndSize );
// Render it
RenderParticle_ColorSize( pIterator->GetParticleDraw(), tPos, color, alpha, flSize );
pParticle = (const SimpleParticle*)pIterator->GetNext( sortKey );
}
}
inline void C_EntityParticleTrail::SimulateParticles( CParticleSimulateIterator *pIterator )
{
SimpleParticle *pParticle = (SimpleParticle*)pIterator->GetFirst();
while ( pParticle )
{
// Update position
float flTimeDelta = pIterator->GetTimeDelta();
pParticle->m_Pos += pParticle->m_vecVelocity * flTimeDelta;
// NOTE: I'm overloading "die time" to be the actual start time.
pParticle->m_flLifetime += flTimeDelta;
if ( pParticle->m_flLifetime >= pParticle->m_flDieTime )
pIterator->RemoveParticle( pParticle );
pParticle = (SimpleParticle*)pIterator->GetNext();
}
}

View File

@@ -0,0 +1,95 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Ambient light controller entity with simple radial falloff
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_spatialentity.h"
#include "spatialentitymgr.h"
#include "c_env_ambient_light.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static ConVar cl_ambient_light_disableentities( "cl_ambient_light_disableentities", "0", FCVAR_NONE, "Disable map ambient light entities." );
static CSpatialEntityMgr s_EnvAmbientLightMgr;
IMPLEMENT_CLIENTCLASS_DT( C_EnvAmbientLight, DT_EnvAmbientLight, CEnvAmbientLight )
RecvPropVector( RECVINFO_NAME( m_Value, m_vecColor ) ),
END_RECV_TABLE()
void C_EnvAmbientLight::ApplyAccumulation( void )
{
Vector rgbVal = BlendedValue();
static ConVarRef mat_ambient_light_r( "mat_ambient_light_r" );
static ConVarRef mat_ambient_light_g( "mat_ambient_light_g" );
static ConVarRef mat_ambient_light_b( "mat_ambient_light_b" );
if ( mat_ambient_light_r.IsValid() )
{
mat_ambient_light_r.SetValue( rgbVal.x );
}
if ( mat_ambient_light_g.IsValid() )
{
mat_ambient_light_g.SetValue( rgbVal.y );
}
if ( mat_ambient_light_b.IsValid() )
{
mat_ambient_light_b.SetValue( rgbVal.z );
}
}
void C_EnvAmbientLight::AddToPersonalSpatialEntityMgr( void )
{
s_EnvAmbientLightMgr.AddSpatialEntity( this );
}
void C_EnvAmbientLight::RemoveFromPersonalSpatialEntityMgr( void )
{
s_EnvAmbientLightMgr.RemoveSpatialEntity( this );
}
void C_EnvAmbientLight::SetColor( const Vector &vecColor, float flLerpTime )
{
if ( flLerpTime <= 0 )
{
m_Value = vecColor / 255.0f;
m_colorTimer.Invalidate();
return;
}
m_vecStartColor = m_Value;
m_vecTargetColor = vecColor / 255.0f;
m_colorTimer.Start( flLerpTime );
}
void C_EnvAmbientLight::ClientThink( void )
{
BaseClass::ClientThink();
if ( m_colorTimer.HasStarted() )
{
if ( m_colorTimer.IsElapsed() )
{
m_Value = m_vecTargetColor;
m_colorTimer.Invalidate();
}
else
{
m_Value = m_vecTargetColor - ( m_vecTargetColor - m_vecStartColor ) * m_colorTimer.GetRemainingRatio();
}
}
}

View File

@@ -0,0 +1,30 @@
#ifndef _INCLUDED_C_ENV_AMBIENT_LIGHT_H
#define _INCLUDED_C_ENV_AMBIENT_LIGHT_H
#include "c_spatialentity.h"
//------------------------------------------------------------------------------
// Purpose : Ambient light controller entity with radial falloff
//------------------------------------------------------------------------------
class C_EnvAmbientLight : public C_SpatialEntityTemplate<Vector>
{
public:
DECLARE_CLASS( C_EnvAmbientLight, C_SpatialEntityTemplate<Vector> );
DECLARE_CLIENTCLASS();
virtual void ApplyAccumulation( void );
virtual void ClientThink( void );
void SetColor( const Vector &vecColor, float flLerpTime = 0 );
Vector GetTargetColor() { return m_vecTargetColor * 255.0f; }
protected:
virtual void AddToPersonalSpatialEntityMgr( void );
virtual void RemoveFromPersonalSpatialEntityMgr( void );
Vector m_vecStartColor;
Vector m_vecTargetColor;
CountdownTimer m_colorTimer;
};
#endif // _INCLUDED_C_ENV_AMBIENT_LIGHT_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,208 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Directional lighting with cascaded shadow mapping entity.
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ENV_CASCADE_LIGHT_H
#define C_ENV_CASCADE_LIGHT_H
#include "c_baseplayer.h"
#include "csm_parallel_split.h"
//------------------------------------------------------------------------------
// Purpose: Directional lighting with cascaded shadow mapping entity.
//------------------------------------------------------------------------------
class C_CascadeLight : public C_BaseEntity
{
public:
DECLARE_CLASS( C_CascadeLight, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_CascadeLight();
virtual ~C_CascadeLight();
static C_CascadeLight *Get() { return m_pCascadeLight; }
virtual void Spawn();
virtual void Release();
virtual bool ShouldDraw();
virtual void ClientThink();
inline const Vector &GetShadowDirection() const { return m_shadowDirection; }
inline const Vector &GetEnvLightShadowDirection() const { return m_envLightShadowDirection; }
inline bool IsEnabled() const { return m_bEnabled; }
inline color32 GetColor() const { return m_LightColor; }
inline int GetColorScale() const { return m_LightColorScale; }
inline bool UseLightEnvAngles() const { return m_bUseLightEnvAngles; }
float GetMaxShadowDist() const { return m_flMaxShadowDist; }
private:
static C_CascadeLight *m_pCascadeLight;
Vector m_shadowDirection;
Vector m_envLightShadowDirection;
bool m_bEnabled;
bool m_bUseLightEnvAngles;
color32 m_LightColor;
int m_LightColorScale;
float m_flMaxShadowDist;
};
class CDebugPrimRenderer2D
{
public:
CDebugPrimRenderer2D();
void Clear();
// Normalized [0,1] coords, where (0,0) is upper left
void AddNormalizedLine2D( float sx, float sy, float ex, float ey, uint r, uint g, uint b );
// Screenspace (pixel) coords
void AddScreenspaceLine2D( float sx, float sy, float ex, float ey, uint r, uint g, uint b );
void AddScreenspaceRect2D( float sx, float sy, float ex, float ey, uint r, uint g, uint b );
void AddScreenspaceLineList2D( uint nCount, const Vector2D *pVerts, const VertexColor_t &color );
void AddScreenspaceWireframeFrustum2D( const VMatrix &xform, const VertexColor_t &color, bool bShowAxes );
void Render2D( );
void RenderScreenspaceDepthTexture( float sx, float sy, float ex, float ey, float su, float sv, float eu, float ev, CTextureReference &depthTex, float zLo, float zHi );
private:
class CDebugLine
{
public:
inline CDebugLine() { }
inline CDebugLine( const Vector2D &start, const Vector2D &end, uint r = 255, uint g = 255, uint b = 255, uint a = 255 ) { Init( start, end, r, g, b, a ); }
inline void Init( const Vector2D &start, const Vector2D &end, uint r = 255, uint g = 255, uint b = 255, uint a = 255 ) { m_EndPoints[0] = start; m_EndPoints[1] = end; m_nColor[0] = r; m_nColor[1] = g; m_nColor[2] = b; m_nColor[3] = a; }
Vector2D m_EndPoints[2]; // normalized [0,1] coordinates, (0,0) is top-left
uint8 m_nColor[4];
};
CUtlVector< CDebugLine > m_debugLines;
void RenderDebugLines2D( uint nNumLines, const CDebugLine *pLines );
};
class CCascadeLightManager : public CAutoGameSystemPerFrame
{
public:
CCascadeLightManager();
virtual ~CCascadeLightManager();
bool InitRenderTargets();
void ShutdownRenderTargets();
void LevelInitPreEntity();
void LevelInitPostEntity();
void LevelShutdownPreEntity();
void LevelShutdownPostEntity();
void Shutdown();
bool IsEnabled() const;
bool IsEnabledAndActive() const;
virtual void PreRender ();
void ComputeShadowDepthTextures( const CViewSetup &viewSetup, bool bSetup = false );
void UnlockAllShadowDepthTextures();
void BeginViewModelRendering();
void EndViewModelRendering();
void BeginReflectionView();
void EndReflectionView();
void Draw3DDebugInfo();
void Draw2DDebugInfo();
void DumpStatus();
CSMQualityMode_t GetCSMQualityMode();
public:
static void RotXPlusDown( const CCommand &args );
static void RotXPlusUp( const CCommand &args );
static void RotXNegDown( const CCommand &args );
static void RotXNegUp( const CCommand &args );
static void RotYPlusDown( const CCommand &args );
static void RotYPlusUp( const CCommand &args );
static void RotYNegDown( const CCommand &args );
static void RotYNegUp( const CCommand &args );
private:
class CFullCSMState
{
public:
CFullCSMState()
{
Clear();
}
inline void Clear()
{
V_memset( &m_sceneFrustum, 0, sizeof( m_sceneFrustum ) );
m_flSceneAspectRatio = 0.0f;
m_sceneWorldToView.Identity();
m_sceneViewToProj.Identity();
m_sceneWorldToProj.Identity();
m_CSMParallelSplit.Clear();
m_shadowDir.Init( 0, 0, -1.0f );
m_flMaxShadowDist = 0.0f;
m_flMaxVisibleDist = 0.0f;
m_nMaxCascadeSize = 0;
m_bValid = false;
}
void Update( const CViewSetup &viewSetup, const Vector &shadowDir, const color32 lightColor, const int lightColorScale, float flMaxShadowDist, float flMaxVisibleDist, uint nMaxCascadeSize, uint nAtlasFirstCascadeIndex, int nCSMQualityLevel, bool bSetAllCascadesToFirst );
bool IsValid() const { return m_CSMParallelSplit.IsValid() && m_CSMParallelSplit.GetLightState().m_nShadowCascadeSize; }
void Reset() { m_CSMParallelSplit.Reset(); }
CFrustum m_sceneFrustum;
float m_flSceneAspectRatio;
VMatrix m_sceneWorldToView, m_sceneViewToProj, m_sceneWorldToProj;
Vector m_shadowDir;
float m_flMaxShadowDist;
float m_flMaxVisibleDist;
uint m_nMaxCascadeSize;
CCSMParallelSplit m_CSMParallelSplit;
bool m_bValid;
};
void RenderViews( CFullCSMState &state, bool bIncludeViewModels );
int m_nDepthTextureResolution;
CSMQualityMode_t m_nCurRenderTargetQualityMode;
CFullCSMState m_curState;
CFullCSMState m_curViewModelState;
CFullCSMState m_capturedState;
CDebugPrimRenderer2D m_debugPrimRenderer;
bool m_bRenderTargetsAllocated;
CTextureReference m_ShadowDepthTexture;
CTextureReference m_DummyColorTexture;
float m_flRotX[2], m_flRotY[2];
bool m_bCSMIsActive;
bool m_bStateIsValid;
void DeinitRenderTargets();
void DrawTextDebugInfo();
Vector GetShadowDirection();
inline CFullCSMState &GetActiveState() { return m_capturedState.m_CSMParallelSplit.IsValid() ? m_capturedState : m_curState; }
};
extern CCascadeLightManager g_CascadeLightManager;
#endif // C_ENV_CASCADE_LIGHT_H

View File

@@ -0,0 +1,100 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
extern bool g_bDOFEnabled;
extern float g_flDOFNearBlurDepth;
extern float g_flDOFNearFocusDepth;
extern float g_flDOFFarFocusDepth;
extern float g_flDOFFarBlurDepth;
extern float g_flDOFNearBlurRadius;
extern float g_flDOFFarBlurRadius;
EHANDLE g_hDOFControllerInUse = INVALID_EHANDLE;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_EnvDOFController : public C_BaseEntity
{
DECLARE_CLASS( C_EnvDOFController, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_EnvDOFController();
~C_EnvDOFController();
virtual void OnDataChanged( DataUpdateType_t updateType );
private:
bool m_bDOFEnabled;
float m_flNearBlurDepth;
float m_flNearFocusDepth;
float m_flFarFocusDepth;
float m_flFarBlurDepth;
float m_flNearBlurRadius;
float m_flFarBlurRadius;
private:
C_EnvDOFController( const C_EnvDOFController & );
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvDOFController, DT_EnvDOFController, CEnvDOFController )
RecvPropInt( RECVINFO(m_bDOFEnabled) ),
RecvPropFloat( RECVINFO(m_flNearBlurDepth) ),
RecvPropFloat( RECVINFO(m_flNearFocusDepth) ),
RecvPropFloat( RECVINFO(m_flFarFocusDepth) ),
RecvPropFloat( RECVINFO(m_flFarBlurDepth) ),
RecvPropFloat( RECVINFO(m_flNearBlurRadius) ),
RecvPropFloat( RECVINFO(m_flFarBlurRadius) )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EnvDOFController::C_EnvDOFController( void )
: m_bDOFEnabled( true ),
m_flNearBlurDepth( 50.0f ),
m_flNearFocusDepth( 100.0f ),
m_flFarFocusDepth( 250.0f ),
m_flFarBlurDepth( 1000.0f ),
m_flNearBlurRadius( 0.0f ), // no near blur by default
m_flFarBlurRadius( 5.0f )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EnvDOFController::~C_EnvDOFController( void )
{
if ( g_hDOFControllerInUse == this )
{
g_bDOFEnabled = false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvDOFController::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
g_bDOFEnabled = m_bDOFEnabled && ( ( m_flNearBlurRadius > 0.0f ) || ( m_flFarBlurRadius > 0.0f ) );
g_flDOFNearBlurDepth = m_flNearBlurDepth;
g_flDOFNearFocusDepth = m_flNearFocusDepth;
g_flDOFFarFocusDepth = m_flFarFocusDepth;
g_flDOFFarBlurDepth = m_flFarBlurDepth;
g_flDOFNearBlurRadius = m_flNearBlurRadius;
g_flDOFFarBlurRadius = m_flFarBlurRadius;
g_hDOFControllerInUse = this;
}

View File

@@ -0,0 +1,52 @@
//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ====
//
// An entity that allows level designer control over the fog parameters.
//
//=============================================================================
#include "cbase.h"
#include "c_env_fog_controller.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_NETWORKCLASS_ALIASED( FogController, DT_FogController )
//-----------------------------------------------------------------------------
// Datatable
//-----------------------------------------------------------------------------
BEGIN_NETWORK_TABLE_NOBASE( CFogController, DT_FogController )
// fog data
RecvPropInt( RECVINFO( m_fog.enable ) ),
RecvPropInt( RECVINFO( m_fog.blend ) ),
RecvPropVector( RECVINFO( m_fog.dirPrimary ) ),
RecvPropInt( RECVINFO( m_fog.colorPrimary ), 0, RecvProxy_Int32ToColor32 ),
RecvPropInt( RECVINFO( m_fog.colorSecondary ), 0, RecvProxy_Int32ToColor32 ),
RecvPropFloat( RECVINFO( m_fog.start ) ),
RecvPropFloat( RECVINFO( m_fog.end ) ),
RecvPropFloat( RECVINFO( m_fog.farz ) ),
RecvPropFloat( RECVINFO( m_fog.maxdensity ) ),
RecvPropInt( RECVINFO( m_fog.colorPrimaryLerpTo ), 0, RecvProxy_Int32ToColor32 ),
RecvPropInt( RECVINFO( m_fog.colorSecondaryLerpTo ), 0, RecvProxy_Int32ToColor32 ),
RecvPropFloat( RECVINFO( m_fog.startLerpTo ) ),
RecvPropFloat( RECVINFO( m_fog.endLerpTo ) ),
RecvPropFloat( RECVINFO( m_fog.maxdensityLerpTo ) ),
RecvPropFloat( RECVINFO( m_fog.lerptime ) ),
RecvPropFloat( RECVINFO( m_fog.duration ) ),
RecvPropFloat( RECVINFO( m_fog.HDRColorScale ) ),
RecvPropFloat( RECVINFO( m_fog.ZoomFogScale ) ),
END_NETWORK_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_FogController::C_FogController()
{
// Make sure that old maps without fog fields don't get wacked out fog values.
m_fog.enable = false;
m_fog.maxdensity = 1.0f;
m_fog.HDRColorScale = 1.0f;
}

View File

@@ -0,0 +1,33 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ENV_FOG_CONTROLLER_H
#define C_ENV_FOG_CONTROLLER_H
#define CFogController C_FogController
//=============================================================================
//
// Class Fog Controller:
// Compares a set of integer inputs to the one main input
// Outputs true if they are all equivalant, false otherwise
//
class C_FogController : public C_BaseEntity
{
public:
DECLARE_NETWORKCLASS();
DECLARE_CLASS( C_FogController, C_BaseEntity );
C_FogController();
public:
fogparams_t m_fog;
};
#endif // C_ENV_FOG_CONTROLLER_H

View File

@@ -0,0 +1,304 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_baseanimating.h"
#include "particlemgr.h"
#include "materialsystem/imaterialvar.h"
#include "cl_animevent.h"
#include "particle_util.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// An entity which emits other entities at points
//-----------------------------------------------------------------------------
class C_EnvParticleScript : public C_BaseAnimating, public IParticleEffect
{
public:
DECLARE_CLASS( C_EnvParticleScript, C_BaseAnimating );
DECLARE_CLIENTCLASS();
C_EnvParticleScript();
// IParticleEffect overrides.
public:
virtual bool ShouldSimulate() const { return m_bSimulate; }
virtual void SetShouldSimulate( bool bSim ) { m_bSimulate = bSim; }
virtual void RenderParticles( CParticleRenderIterator *pIterator );
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
virtual const Vector &GetSortOrigin();
// C_BaseAnimating overrides
public:
// NOTE: Ths enclosed particle effect binding will do all the drawing
// But we have to return true, unlike other particle systems, for the animation events to work
virtual bool ShouldDraw() { return true; }
virtual int DrawModel( int flags, const RenderableInstance_t &instance ) { return 0; }
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
private:
// Creates, destroys particles attached to an attachment
void CreateParticle( const char *pAttachmentName, const char *pSpriteName );
void DestroyAllParticles( const char *pAttachmentName );
void DestroyAllParticles( );
private:
struct ParticleScriptParticle_t : public Particle
{
int m_nAttachment;
float m_flSize;
};
CParticleEffectBinding m_ParticleEffect;
float m_flMaxParticleSize;
int m_nOldSequence;
float m_flSequenceScale;
bool m_bSimulate;
};
REGISTER_EFFECT( C_EnvParticleScript );
//-----------------------------------------------------------------------------
// Datatable
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EnvParticleScript, DT_EnvParticleScript, CEnvParticleScript )
RecvPropFloat( RECVINFO(m_flSequenceScale) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
C_EnvParticleScript::C_EnvParticleScript()
{
m_flMaxParticleSize = 0.0f;
m_bSimulate = true;
}
//-----------------------------------------------------------------------------
// Check for changed sequence numbers
//-----------------------------------------------------------------------------
void C_EnvParticleScript::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_nOldSequence = GetSequence();
}
//-----------------------------------------------------------------------------
// Starts up the particle system
//-----------------------------------------------------------------------------
void C_EnvParticleScript::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if( updateType == DATA_UPDATE_CREATED )
{
ParticleMgr()->AddEffect( &m_ParticleEffect, this );
g_pClientLeafSystem->EnableRendering( RenderHandle(), false );
}
if ( m_nOldSequence != GetSequence() )
{
DestroyAllParticles();
}
}
//-----------------------------------------------------------------------------
// Creates, destroys particles attached to an attachment
//-----------------------------------------------------------------------------
void C_EnvParticleScript::CreateParticle( const char *pAttachmentName, const char *pSpriteName )
{
// Find the attachment
int nAttachment = LookupAttachment( pAttachmentName );
if ( nAttachment <= 0 )
return;
// Get the sprite materials
PMaterialHandle hMat = m_ParticleEffect.FindOrAddMaterial( pSpriteName );
ParticleScriptParticle_t *pParticle =
(ParticleScriptParticle_t*)m_ParticleEffect.AddParticle(sizeof(ParticleScriptParticle_t), hMat);
if ( pParticle == NULL )
return;
// Get the sprite size from the material's materialvars
bool bFound = false;
IMaterialVar *pMaterialVar = NULL;
IMaterial *pMaterial = ParticleMgr()->PMaterialToIMaterial( hMat );
if ( pMaterial )
{
pMaterialVar = pMaterial->FindVar( "$spritesize", &bFound, false );
}
if ( bFound )
{
pParticle->m_flSize = pMaterialVar->GetFloatValue();
}
else
{
pParticle->m_flSize = 100.0f;
}
// Make sure the particle cull size reflects our particles
if ( pParticle->m_flSize > m_flMaxParticleSize )
{
m_flMaxParticleSize = pParticle->m_flSize;
m_ParticleEffect.SetParticleCullRadius( m_flMaxParticleSize );
}
// Place the particle on the attachment specified
pParticle->m_nAttachment = nAttachment;
QAngle vecAngles;
GetAttachment( nAttachment, pParticle->m_Pos, vecAngles );
if ( m_flSequenceScale != 1.0f )
{
pParticle->m_Pos -= GetAbsOrigin();
pParticle->m_Pos *= m_flSequenceScale;
pParticle->m_Pos += GetAbsOrigin();
}
}
void C_EnvParticleScript::DestroyAllParticles( const char *pAttachmentName )
{
int nAttachment = LookupAttachment( pAttachmentName );
if ( nAttachment <= 0 )
return;
int nCount = m_ParticleEffect.GetNumActiveParticles();
Particle** ppParticles = (Particle**)stackalloc( nCount * sizeof(Particle*) );
int nActualCount = m_ParticleEffect.GetActiveParticleList( nCount, ppParticles );
Assert( nActualCount == nCount );
for ( int i = 0; i < nActualCount; ++i )
{
ParticleScriptParticle_t *pParticle = (ParticleScriptParticle_t*)ppParticles[i];
if ( pParticle->m_nAttachment == nAttachment )
{
// Mark for deletion
pParticle->m_nAttachment = -1;
}
}
}
void C_EnvParticleScript::DestroyAllParticles( )
{
int nCount = m_ParticleEffect.GetNumActiveParticles();
Particle** ppParticles = (Particle**)stackalloc( nCount * sizeof(Particle*) );
int nActualCount = m_ParticleEffect.GetActiveParticleList( nCount, ppParticles );
Assert( nActualCount == nCount );
for ( int i = 0; i < nActualCount; ++i )
{
ParticleScriptParticle_t *pParticle = (ParticleScriptParticle_t*)ppParticles[i];
// Mark for deletion
pParticle->m_nAttachment = -1;
}
}
//-----------------------------------------------------------------------------
// The animation events will create particles on the attachment points
//-----------------------------------------------------------------------------
void C_EnvParticleScript::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
// Handle events to create + destroy particles
switch( event )
{
case CL_EVENT_SPRITEGROUP_CREATE:
{
char pAttachmentName[256];
char pSpriteName[256];
int nArgs = sscanf( options, "%255s %255s", pAttachmentName, pSpriteName );
if ( nArgs == 2 )
{
CreateParticle( pAttachmentName, pSpriteName );
}
}
return;
case CL_EVENT_SPRITEGROUP_DESTROY:
{
char pAttachmentName[256];
int nArgs = sscanf( options, "%255s", pAttachmentName );
if ( nArgs == 1 )
{
DestroyAllParticles( pAttachmentName );
}
}
return;
}
// Fall back
BaseClass::FireEvent( origin, angles, event, options );
}
//-----------------------------------------------------------------------------
// Simulate the particles
//-----------------------------------------------------------------------------
void C_EnvParticleScript::RenderParticles( CParticleRenderIterator *pIterator )
{
const ParticleScriptParticle_t* pParticle = (const ParticleScriptParticle_t*)pIterator->GetFirst();
while ( pParticle )
{
Vector vecRenderPos;
TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, vecRenderPos );
float sortKey = vecRenderPos.z;
Vector color( 1, 1, 1 );
RenderParticle_ColorSize( pIterator->GetParticleDraw(), vecRenderPos, color, 1.0f, pParticle->m_flSize );
pParticle = (const ParticleScriptParticle_t*)pIterator->GetNext( sortKey );
}
}
void C_EnvParticleScript::SimulateParticles( CParticleSimulateIterator *pIterator )
{
ParticleScriptParticle_t* pParticle = (ParticleScriptParticle_t*)pIterator->GetFirst();
while ( pParticle )
{
// Here's how we retire particles
if ( pParticle->m_nAttachment == -1 )
{
pIterator->RemoveParticle( pParticle );
}
else
{
// Move the particle to the attachment point
QAngle vecAngles;
GetAttachment( pParticle->m_nAttachment, pParticle->m_Pos, vecAngles );
if ( m_flSequenceScale != 1.0f )
{
pParticle->m_Pos -= GetAbsOrigin();
pParticle->m_Pos *= m_flSequenceScale;
pParticle->m_Pos += GetAbsOrigin();
}
}
pParticle = (ParticleScriptParticle_t*)pIterator->GetNext();
}
}
const Vector &C_EnvParticleScript::GetSortOrigin()
{
return GetAbsOrigin();
}

View File

@@ -0,0 +1,495 @@
//====== Copyright © 1996-2003, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
#include "c_env_projectedtexture.h"
#include "shareddefs.h"
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
#include "view.h"
#include "iviewrender.h"
#include "view_shared.h"
#include "texture_group_names.h"
#include "tier0/icommandline.h"
#include "tier0/platform.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
float C_EnvProjectedTexture::m_flVisibleBBoxMinHeight = -FLT_MAX;
IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvProjectedTexture )
RecvPropEHandle( RECVINFO( m_hTargetEntity ) ),
RecvPropBool( RECVINFO( m_bState ) ),
RecvPropBool( RECVINFO( m_bAlwaysUpdate ) ),
RecvPropFloat( RECVINFO( m_flLightFOV ) ),
RecvPropBool( RECVINFO( m_bEnableShadows ) ),
RecvPropBool( RECVINFO( m_bSimpleProjection ) ),
RecvPropBool( RECVINFO( m_bLightOnlyTarget ) ),
RecvPropBool( RECVINFO( m_bLightWorld ) ),
RecvPropBool( RECVINFO( m_bCameraSpace ) ),
RecvPropFloat( RECVINFO( m_flBrightnessScale ) ),
RecvPropInt( RECVINFO( m_LightColor ), 0, RecvProxy_Int32ToColor32 ),
RecvPropFloat( RECVINFO( m_flColorTransitionTime ) ),
RecvPropFloat( RECVINFO( m_flAmbient ) ),
RecvPropString( RECVINFO( m_SpotlightTextureName ) ),
RecvPropInt( RECVINFO( m_nSpotlightTextureFrame ) ),
RecvPropFloat( RECVINFO( m_flNearZ ) ),
RecvPropFloat( RECVINFO( m_flFarZ ) ),
RecvPropInt( RECVINFO( m_nShadowQuality ) ),
RecvPropFloat( RECVINFO( m_flProjectionSize ) ),
RecvPropFloat( RECVINFO( m_flRotation ) ),
RecvPropInt( RECVINFO( m_iStyle ) ),
END_RECV_TABLE()
C_EnvProjectedTexture *C_EnvProjectedTexture::Create( )
{
C_EnvProjectedTexture *pEnt = new C_EnvProjectedTexture();
pEnt->m_flNearZ = 4.0f;
pEnt->m_flFarZ = 2000.0f;
// strcpy( pEnt->m_SpotlightTextureName, "particle/rj" );
pEnt->m_bLightWorld = true;
pEnt->m_bLightOnlyTarget = false;
pEnt->m_bSimpleProjection = true;
pEnt->m_nShadowQuality = 1;
pEnt->m_flLightFOV = 10.0f;
pEnt->m_LightColor.r = 255;
pEnt->m_LightColor.g = 255;
pEnt->m_LightColor.b = 255;
pEnt->m_LightColor.a = 255;
pEnt->m_bEnableShadows = false;
pEnt->m_flColorTransitionTime = 1.0f;
pEnt->m_bCameraSpace = false;
pEnt->SetAbsAngles( QAngle( 90, 0, 0 ) );
pEnt->m_bAlwaysUpdate = true;
pEnt->m_bState = true;
pEnt->m_flProjectionSize = 500.0f;
pEnt->m_flRotation = 0.0f;
return pEnt;
}
C_EnvProjectedTexture::C_EnvProjectedTexture( void )
{
m_LightHandle = CLIENTSHADOW_INVALID_HANDLE;
m_bForceUpdate = true;
m_pMaterial = NULL;
m_bIsCurrentlyProjected = false;
AddToEntityList( ENTITY_LIST_SIMULATE );
}
C_EnvProjectedTexture::~C_EnvProjectedTexture( void )
{
ShutDownLightHandle();
}
void C_EnvProjectedTexture::ShutDownLightHandle( void )
{
// Clear out the light
if( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
if ( m_bSimpleProjection == true )
{
g_pClientShadowMgr->DestroyProjection( m_LightHandle );
}
else
{
g_pClientShadowMgr->DestroyFlashlight( m_LightHandle );
}
m_LightHandle = CLIENTSHADOW_INVALID_HANDLE;
}
m_bIsCurrentlyProjected = false;
}
void C_EnvProjectedTexture::SetMaterial( IMaterial *pMaterial )
{
if ( pMaterial != m_ProjectedMaterial )
{
m_ProjectedMaterial.Init( pMaterial );
pMaterial->AddRef();
}
}
void C_EnvProjectedTexture::SetLightColor( byte r, byte g, byte b, byte a )
{
m_LightColor.r = r;
m_LightColor.g = g;
m_LightColor.b = b;
m_LightColor.a = a;
}
void C_EnvProjectedTexture::SetSize( float flSize )
{
m_flProjectionSize = flSize;
}
void C_EnvProjectedTexture::SetRotation( float flRotation )
{
m_flRotation = flRotation;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : updateType -
//-----------------------------------------------------------------------------
void C_EnvProjectedTexture::OnDataChanged( DataUpdateType_t updateType )
{
if ( updateType == DATA_UPDATE_CREATED )
{
Assert( m_SpotlightTexture.IsValid() == false );
m_SpotlightTexture.Init( m_SpotlightTextureName, TEXTURE_GROUP_OTHER, true );
m_ProjectedMaterial.Init( m_SpotlightTextureName, TEXTURE_GROUP_OTHER );
}
m_bForceUpdate = true;
UpdateLight();
BaseClass::OnDataChanged( updateType );
}
static ConVar asw_perf_wtf("asw_perf_wtf", "0", FCVAR_DEVELOPMENTONLY, "Disable updating of projected shadow textures from UpdateLight" );
extern ConVar r_flashlightenableculling;
bool C_EnvProjectedTexture::ShouldUpdate( void )
{
if ( !IsGameConsole() )
{
CPULevel_t nCPULevel = GetCPULevel();
bool bNoDraw = ( GetMinCPULevel() && GetMinCPULevel()-1 > nCPULevel );
bNoDraw = bNoDraw || ( GetMaxCPULevel() && GetMaxCPULevel()-1 < nCPULevel );
if ( bNoDraw )
return false;
GPULevel_t nGPULevel = GetGPULevel();
bNoDraw = ( GetMinGPULevel() && GetMinGPULevel()-1 > nGPULevel );
bNoDraw = bNoDraw || ( GetMaxGPULevel() && GetMaxGPULevel()-1 < nGPULevel );
if ( bNoDraw )
return false;
}
return true;
}
void C_EnvProjectedTexture::UpdateLight( void )
{
if ( !ShouldUpdate() )
{
if ( m_bIsCurrentlyProjected )
{
ShutDownLightHandle();
}
return;
}
VPROF("C_EnvProjectedTexture::UpdateLight");
bool bVisible = true;
Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b );
float flLinearFloatLightAlpha = m_LightColor.a;
if ( m_bAlwaysUpdate )
{
m_bForceUpdate = true;
}
if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha )
{
float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;
m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );
m_bForceUpdate = true;
}
if ( !m_bForceUpdate && r_flashlightenableculling.GetBool() )
{
bVisible = IsBBoxVisible();
}
if ( m_bState == false || !bVisible )
{
// Spotlight's extents aren't in view
ShutDownLightHandle();
return;
}
if ( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || m_bForceUpdate )
{
Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
FlashlightState_t state;
if ( m_hTargetEntity != NULL )
{
if ( m_bCameraSpace )
{
const QAngle &angles = GetLocalAngles();
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if( pPlayer )
{
const QAngle playerAngles = pPlayer->GetAbsAngles();
Vector vPlayerForward, vPlayerRight, vPlayerUp;
AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp );
matrix3x4_t mRotMatrix;
AngleMatrix( angles, mRotMatrix );
VectorITransform( vPlayerForward, mRotMatrix, vForward );
VectorITransform( vPlayerRight, mRotMatrix, vRight );
VectorITransform( vPlayerUp, mRotMatrix, vUp );
float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;
VectorNormalize( vForward );
VectorNormalize( vRight );
VectorNormalize( vUp );
}
}
else
{
vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
VectorNormalize( vForward );
// JasonM - unimplemented
Assert (0);
//Quaternion q = DirectionToOrientation( dir );
//
// JasonM - set up vRight, vUp
//
// VectorNormalize( vRight );
// VectorNormalize( vUp );
}
}
else
{
AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
}
state.m_fHorizontalFOVDegrees = m_flLightFOV;
state.m_fVerticalFOVDegrees = m_flLightFOV;
state.m_vecLightOrigin = vPos;
BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );
state.m_NearZ = m_flNearZ;
state.m_FarZ = m_flFarZ;
if ( r_flashlightenableculling.GetBool() )
{
// quickly check the proposed light's bbox against the view frustum to determine whether we
// should bother to create it, if it doesn't exist, or cull it, if it does.
#ifndef LINUX
#pragma message("OPTIMIZATION: this should be made SIMD")
#endif
// get the half-widths of the near and far planes,
// based on the FOV which is in degrees. Remember that
// on planet Valve, x is forward, y left, and z up.
const float tanHalfAngle = tan( m_flLightFOV * ( M_PI/180.0f ) * 0.5f );
const float halfWidthNear = tanHalfAngle * m_flNearZ;
const float halfWidthFar = tanHalfAngle * m_flFarZ;
// now we can build coordinates in local space: the near rectangle is eg
// (0, -halfWidthNear, -halfWidthNear), (0, halfWidthNear, -halfWidthNear),
// (0, halfWidthNear, halfWidthNear), (0, -halfWidthNear, halfWidthNear)
VectorAligned vNearRect[4] = {
VectorAligned( m_flNearZ, -halfWidthNear, -halfWidthNear), VectorAligned( m_flNearZ, halfWidthNear, -halfWidthNear),
VectorAligned( m_flNearZ, halfWidthNear, halfWidthNear), VectorAligned( m_flNearZ, -halfWidthNear, halfWidthNear)
};
VectorAligned vFarRect[4] = {
VectorAligned( m_flFarZ, -halfWidthFar, -halfWidthFar), VectorAligned( m_flFarZ, halfWidthFar, -halfWidthFar),
VectorAligned( m_flFarZ, halfWidthFar, halfWidthFar), VectorAligned( m_flFarZ, -halfWidthFar, halfWidthFar)
};
matrix3x4_t matOrientation( vForward, -vRight, vUp, vPos );
enum
{
kNEAR = 0,
kFAR = 1,
};
VectorAligned vOutRects[2][4];
for ( int i = 0 ; i < 4 ; ++i )
{
VectorTransform( vNearRect[i].Base(), matOrientation, vOutRects[0][i].Base() );
}
for ( int i = 0 ; i < 4 ; ++i )
{
VectorTransform( vFarRect[i].Base(), matOrientation, vOutRects[1][i].Base() );
}
// now take the min and max extents for the bbox, and see if it is visible.
Vector mins = **vOutRects;
Vector maxs = **vOutRects;
for ( int i = 1; i < 8 ; ++i )
{
VectorMin( mins, *(*vOutRects+i), mins );
VectorMax( maxs, *(*vOutRects+i), maxs );
}
#if 0 //for debugging the visibility frustum we just calculated
NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][1], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //first tri
NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][1], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //make it double sided
NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][3], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //second tri
NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][3], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //make it double sided
NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][1], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //first tri
NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][1], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //make it double sided
NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][3], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //second tri
NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][3], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //make it double sided
NDebugOverlay::Box( vec3_origin, mins, maxs, 0, 255, 0, 100, 0.0f );
#endif
bool bVisible = IsBBoxVisible( mins, maxs );
if (!bVisible)
{
// Spotlight's extents aren't in view
if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
ShutDownLightHandle();
}
return;
}
}
float flAlpha = m_flCurrentLinearFloatLightAlpha * ( 1.0f / 255.0f );
// Get the current light style value to throttle the brightness by
flAlpha *= engine->LightStyleValue( m_iStyle );
state.m_fQuadraticAtten = 0.0;
state.m_fLinearAtten = 100;
state.m_fConstantAtten = 0.0f;
state.m_FarZAtten = m_flFarZ;
state.m_fBrightnessScale = m_flBrightnessScale;
state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha;
state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha;
state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha;
state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
state.m_flShadowSlopeScaleDepthBias = g_pMaterialSystemHardwareConfig->GetShadowSlopeScaleDepthBias();
state.m_flShadowDepthBias = g_pMaterialSystemHardwareConfig->GetShadowDepthBias();
state.m_bEnableShadows = m_bEnableShadows;
extern ConVar r_flashlightdepthres;
state.m_flShadowMapResolution = r_flashlightdepthres.GetFloat();
if ( m_bSimpleProjection )
{
state.m_pSpotlightTexture = NULL;
state.m_pProjectedMaterial = m_ProjectedMaterial;
}
else
{
state.m_pSpotlightTexture = m_SpotlightTexture;
state.m_pProjectedMaterial = NULL;
}
state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
state.m_flProjectionSize = m_flProjectionSize;
state.m_flProjectionRotation = m_flRotation;
state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality
state.m_bShareBetweenSplitscreenPlayers = true; // projected flashlight entities should always be shared among players, because they live in a map.
if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE )
{
// Hack: env projected textures don't work like normal flashlights; they're not assigned to a given splitscreen slot,
// but the flashlight code requires this
HACK_GETLOCALPLAYER_GUARD( "Env projected texture" );
if ( m_bSimpleProjection == true )
{
m_LightHandle = g_pClientShadowMgr->CreateProjection( state );
}
else
{
m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state );
}
if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
{
m_bForceUpdate = false;
}
}
else
{
if ( m_bSimpleProjection == true )
{
g_pClientShadowMgr->UpdateProjectionState( m_LightHandle, state );
}
else
{
g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
}
m_bForceUpdate = false;
}
g_pClientShadowMgr->GetFrustumExtents( m_LightHandle, m_vecExtentsMin, m_vecExtentsMax );
m_vecExtentsMin = m_vecExtentsMin - GetAbsOrigin();
m_vecExtentsMax = m_vecExtentsMax - GetAbsOrigin();
}
if( m_bLightOnlyTarget )
{
g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity );
}
else
{
g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, INVALID_EHANDLE );
}
g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );
if ( !asw_perf_wtf.GetBool() && !m_bForceUpdate )
{
g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
}
m_bIsCurrentlyProjected = true;
}
bool C_EnvProjectedTexture::Simulate( void )
{
UpdateLight();
BaseClass::Simulate();
return true;
}
bool C_EnvProjectedTexture::IsBBoxVisible( Vector vecExtentsMin, Vector vecExtentsMax )
{
// Z position clamped to the min height (but must be less than the max)
float flVisibleBBoxMinHeight = MIN( vecExtentsMax.z - 1.0f, m_flVisibleBBoxMinHeight );
vecExtentsMin.z = MAX( vecExtentsMin.z, flVisibleBBoxMinHeight );
// Check if the bbox is in the view
return !engine->CullBox( vecExtentsMin, vecExtentsMax );
}

View File

@@ -0,0 +1,100 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ENVPROJECTED_TEXTURE_H
#define C_ENVPROJECTED_TEXTURE_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
#include "basetypes.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_EnvProjectedTexture : public C_BaseEntity
{
DECLARE_CLASS( C_EnvProjectedTexture, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
void SetMaterial( IMaterial *pMaterial );
void SetLightColor( byte r, byte g, byte b, byte a );
void SetSize( float flSize );
void SetRotation( float flRotation );
virtual void OnDataChanged( DataUpdateType_t updateType );
void ShutDownLightHandle( void );
virtual bool Simulate();
bool ShouldUpdate( void );
void UpdateLight( void );
C_EnvProjectedTexture();
~C_EnvProjectedTexture();
static void SetVisibleBBoxMinHeight( float flVisibleBBoxMinHeight ) { m_flVisibleBBoxMinHeight = flVisibleBBoxMinHeight; }
static float GetVisibleBBoxMinHeight( void ) { return m_flVisibleBBoxMinHeight; }
static C_EnvProjectedTexture *Create( );
private:
inline bool IsBBoxVisible( void );
bool IsBBoxVisible( Vector vecExtentsMin,
Vector vecExtentsMax );
ClientShadowHandle_t m_LightHandle;
bool m_bForceUpdate;
EHANDLE m_hTargetEntity;
bool m_bState;
bool m_bAlwaysUpdate;
float m_flLightFOV;
bool m_bEnableShadows;
bool m_bSimpleProjection;
bool m_bLightOnlyTarget;
bool m_bLightWorld;
bool m_bCameraSpace;
float m_flBrightnessScale;
color32 m_LightColor;
Vector m_CurrentLinearFloatLightColor;
float m_flCurrentLinearFloatLightAlpha;
float m_flColorTransitionTime;
float m_flAmbient;
float m_flNearZ;
float m_flFarZ;
char m_SpotlightTextureName[ MAX_PATH ];
CTextureReference m_SpotlightTexture;
CMaterialReference m_ProjectedMaterial;
int m_nSpotlightTextureFrame;
int m_nShadowQuality;
int m_iStyle;
bool m_bIsCurrentlyProjected;
// simple projection
IMaterial *m_pMaterial;
float m_flProjectionSize;
float m_flRotation;
Vector m_vecExtentsMin;
Vector m_vecExtentsMax;
static float m_flVisibleBBoxMinHeight;
};
bool C_EnvProjectedTexture::IsBBoxVisible( void )
{
return IsBBoxVisible( GetAbsOrigin() + m_vecExtentsMin, GetAbsOrigin() + m_vecExtentsMax );
}
#endif // C_ENV_PROJECTED_TEXTURE_H

View File

@@ -0,0 +1,311 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "shareddefs.h"
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
#include "view.h"
#include "iviewrender.h"
#include "view_shared.h"
#include "texture_group_names.h"
#include "tier0/icommandline.h"
#include "keyvalues.h"
#include "ScreenSpaceEffects.h"
#include "materialsystem/imaterialsystemhardwareconfig.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_EnvScreenOverlay : public C_BaseEntity
{
DECLARE_CLASS( C_EnvScreenOverlay, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
void PreDataUpdate( DataUpdateType_t updateType );
void PostDataUpdate( DataUpdateType_t updateType );
void HandleOverlaySwitch( void );
void StartOverlays( void );
void StopOverlays( void );
void StartCurrentOverlay( void );
void ClientThink( void );
protected:
char m_iszOverlayNames[ MAX_SCREEN_OVERLAYS ][255];
float m_flOverlayTimes[ MAX_SCREEN_OVERLAYS ];
float m_flStartTime;
int m_iDesiredOverlay;
bool m_bIsActive;
bool m_bWasActive;
int m_iCachedDesiredOverlay;
int m_iCurrentOverlay;
float m_flCurrentOverlayTime;
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenOverlay, DT_EnvScreenOverlay, CEnvScreenOverlay )
RecvPropArray( RecvPropString( RECVINFO( m_iszOverlayNames[0]) ), m_iszOverlayNames ),
RecvPropArray( RecvPropFloat( RECVINFO( m_flOverlayTimes[0] ) ), m_flOverlayTimes ),
RecvPropFloat( RECVINFO( m_flStartTime ) ),
RecvPropInt( RECVINFO( m_iDesiredOverlay ) ),
RecvPropBool( RECVINFO( m_bIsActive ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
// Input : updateType -
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::PreDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PreDataUpdate( updateType );
m_bWasActive = m_bIsActive;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
// If we have a start time now, start the overlays going
if ( m_bIsActive && m_flStartTime > 0 && view->GetScreenOverlayMaterial() == NULL )
{
StartOverlays();
}
if ( m_flStartTime == -1 )
{
StopOverlays();
}
HandleOverlaySwitch();
if ( updateType == DATA_UPDATE_CREATED &&
CommandLine()->FindParm( "-makereslists" ) )
{
for ( int i = 0; i < MAX_SCREEN_OVERLAYS; ++i )
{
if ( m_iszOverlayNames[ i ] && m_iszOverlayNames[ i ][ 0 ] )
{
materials->FindMaterial( m_iszOverlayNames[ i ], TEXTURE_GROUP_CLIENT_EFFECTS, false );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::StopOverlays( void )
{
SetNextClientThink( CLIENT_THINK_NEVER );
if ( m_bWasActive && !m_bIsActive )
{
view->SetScreenOverlayMaterial( NULL );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::StartOverlays( void )
{
m_iCurrentOverlay = 0;
m_flCurrentOverlayTime = 0;
m_iCachedDesiredOverlay = 0;
SetNextClientThink( CLIENT_THINK_ALWAYS );
StartCurrentOverlay();
HandleOverlaySwitch();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::HandleOverlaySwitch( void )
{
if( m_iCachedDesiredOverlay != m_iDesiredOverlay )
{
m_iCurrentOverlay = m_iDesiredOverlay;
m_iCachedDesiredOverlay = m_iDesiredOverlay;
StartCurrentOverlay();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::StartCurrentOverlay( void )
{
if ( m_iCurrentOverlay == MAX_SCREEN_OVERLAYS || !m_iszOverlayNames[m_iCurrentOverlay] || !m_iszOverlayNames[m_iCurrentOverlay][0] )
{
// Hit the end of our overlays, so stop.
m_flStartTime = 0;
StopOverlays();
return;
}
if ( m_flOverlayTimes[m_iCurrentOverlay] == -1 )
m_flCurrentOverlayTime = -1;
else
m_flCurrentOverlayTime = gpGlobals->curtime + m_flOverlayTimes[m_iCurrentOverlay];
// Bring up the current overlay
IMaterial *pMaterial = materials->FindMaterial( m_iszOverlayNames[m_iCurrentOverlay], TEXTURE_GROUP_CLIENT_EFFECTS, false );
if ( !IsErrorMaterial( pMaterial ) )
{
view->SetScreenOverlayMaterial( pMaterial );
}
else
{
Warning("env_screenoverlay couldn't find overlay %s.\n", m_iszOverlayNames[m_iCurrentOverlay] );
StopOverlays();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvScreenOverlay::ClientThink( void )
{
// If the current overlay's run out, go to the next one
if ( m_flCurrentOverlayTime != -1 && m_flCurrentOverlayTime < gpGlobals->curtime )
{
m_iCurrentOverlay++;
StartCurrentOverlay();
}
}
// Effect types
enum
{
SCREENEFFECT_EP2_ADVISOR_STUN,
SCREENEFFECT_EP1_INTRO,
SCREENEFFECT_EP2_GROGGY,
};
// ============================================================================
// Screenspace effect
// ============================================================================
class C_EnvScreenEffect : public C_BaseEntity
{
DECLARE_CLASS( C_EnvScreenEffect, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
virtual void ReceiveMessage( int classID, bf_read &msg );
private:
float m_flDuration;
int m_nType;
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenEffect, DT_EnvScreenEffect, CEnvScreenEffect )
RecvPropFloat( RECVINFO( m_flDuration ) ),
RecvPropInt( RECVINFO( m_nType ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
// Input : classID -
// &msg -
//-----------------------------------------------------------------------------
void C_EnvScreenEffect::ReceiveMessage( int classID, bf_read &msg )
{
// Make sure our IDs match
if ( classID != GetClientClass()->m_ClassID )
{
// Message is for subclass
BaseClass::ReceiveMessage( classID, msg );
return;
}
int messageType = msg.ReadByte();
switch( messageType )
{
// Effect turning on
case 0: // FIXME: Declare
{
// Create a keyvalue block to set these params
KeyValues *pKeys = new KeyValues( "keys" );
if ( pKeys == NULL )
return;
if ( m_nType == SCREENEFFECT_EP1_INTRO )
{
// Set our keys
pKeys->SetFloat( "duration", m_flDuration );
pKeys->SetInt( "fadeout", 0 );
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "episodic_intro", pKeys );
g_pScreenSpaceEffects->EnableScreenSpaceEffect( "episodic_intro" );
}
else if ( m_nType == SCREENEFFECT_EP2_ADVISOR_STUN )
{
// Set our keys
pKeys->SetFloat( "duration", m_flDuration );
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "episodic_stun", pKeys );
g_pScreenSpaceEffects->EnableScreenSpaceEffect( "episodic_stun" );
}
else if ( m_nType == SCREENEFFECT_EP2_GROGGY )
{
// Set our keys
pKeys->SetFloat( "duration", m_flDuration );
pKeys->SetInt( "fadeout", 0 );
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "ep2_groggy", pKeys );
g_pScreenSpaceEffects->EnableScreenSpaceEffect( "ep2_groggy" );
}
pKeys->deleteThis();
}
break;
// Effect turning off
case 1: // FIXME: Declare
if ( m_nType == SCREENEFFECT_EP1_INTRO )
{
// Create a keyvalue block to set these params
KeyValues *pKeys = new KeyValues( "keys" );
if ( pKeys == NULL )
return;
// Set our keys
pKeys->SetFloat( "duration", m_flDuration );
pKeys->SetInt( "fadeout", 1 );
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "episodic_intro", pKeys );
}
else if ( m_nType == SCREENEFFECT_EP2_ADVISOR_STUN )
{
g_pScreenSpaceEffects->DisableScreenSpaceEffect( "episodic_stun" );
}
else if ( m_nType == SCREENEFFECT_EP2_GROGGY )
{
// Create a keyvalue block to set these params
KeyValues *pKeys = new KeyValues( "keys" );
if ( pKeys == NULL )
return;
// Set our keys
pKeys->SetFloat( "duration", m_flDuration );
pKeys->SetInt( "fadeout", 1 );
g_pScreenSpaceEffects->SetScreenSpaceEffectParams( "ep2_groggy", pKeys );
}
break;
}
}

View File

@@ -0,0 +1,132 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
extern bool g_bUseCustomAutoExposureMin;
extern bool g_bUseCustomAutoExposureMax;
extern bool g_bUseCustomBloomScale;
extern float g_flCustomAutoExposureMin;
extern float g_flCustomAutoExposureMax;
extern float g_flCustomBloomScale;
extern float g_flCustomBloomScaleMinimum;
extern float g_flBloomExponent;
extern float g_flBloomSaturation;
extern float g_flTonemapPercentTarget;
extern float g_flTonemapPercentBrightPixels;
extern float g_flTonemapMinAvgLum;
extern float g_flTonemapRate;
EHANDLE g_hTonemapControllerInUse = INVALID_EHANDLE;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_EnvTonemapController : public C_BaseEntity
{
DECLARE_CLASS( C_EnvTonemapController, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_EnvTonemapController();
//private:
bool m_bUseCustomAutoExposureMin;
bool m_bUseCustomAutoExposureMax;
bool m_bUseCustomBloomScale;
float m_flCustomAutoExposureMin;
float m_flCustomAutoExposureMax;
float m_flCustomBloomScale;
float m_flCustomBloomScaleMinimum;
float m_flBloomExponent;
float m_flBloomSaturation;
float m_flTonemapPercentTarget;
float m_flTonemapPercentBrightPixels;
float m_flTonemapMinAvgLum;
float m_flTonemapRate;
private:
C_EnvTonemapController( const C_EnvTonemapController & );
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvTonemapController, DT_EnvTonemapController, CEnvTonemapController )
RecvPropInt( RECVINFO(m_bUseCustomAutoExposureMin) ),
RecvPropInt( RECVINFO(m_bUseCustomAutoExposureMax) ),
RecvPropInt( RECVINFO(m_bUseCustomBloomScale) ),
RecvPropFloat( RECVINFO(m_flCustomAutoExposureMin) ),
RecvPropFloat( RECVINFO(m_flCustomAutoExposureMax) ),
RecvPropFloat( RECVINFO(m_flCustomBloomScale) ),
RecvPropFloat( RECVINFO(m_flCustomBloomScaleMinimum) ),
RecvPropFloat( RECVINFO(m_flBloomExponent) ),
RecvPropFloat( RECVINFO(m_flBloomSaturation) ),
RecvPropFloat( RECVINFO(m_flTonemapPercentTarget) ),
RecvPropFloat( RECVINFO(m_flTonemapPercentBrightPixels) ),
RecvPropFloat( RECVINFO(m_flTonemapMinAvgLum) ),
RecvPropFloat( RECVINFO(m_flTonemapRate) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EnvTonemapController::C_EnvTonemapController( void )
{
m_bUseCustomAutoExposureMin = false;
m_bUseCustomAutoExposureMax = false;
m_bUseCustomBloomScale = false;
m_flCustomAutoExposureMin = 0;
m_flCustomAutoExposureMax = 0;
m_flCustomBloomScale = 0.0f;
m_flCustomBloomScaleMinimum = 0.0f;
m_flBloomExponent = 2.5f;
m_flBloomSaturation = 1.0f;
m_flTonemapPercentTarget = 65.0f;
m_flTonemapPercentBrightPixels = 2.0f;
m_flTonemapMinAvgLum = 3.0f;
m_flTonemapRate = 1.0f;
}
void GetTonemapSettingsFromEnvTonemapController( void )
{
C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
if ( localPlayer )
{
C_EnvTonemapController *tonemapController = dynamic_cast< C_EnvTonemapController * >(localPlayer->m_hTonemapController.Get());
if ( tonemapController != NULL )
{
g_bUseCustomAutoExposureMin = tonemapController->m_bUseCustomAutoExposureMin;
g_bUseCustomAutoExposureMax = tonemapController->m_bUseCustomAutoExposureMax;
g_bUseCustomBloomScale = tonemapController->m_bUseCustomBloomScale;
g_flCustomAutoExposureMin = tonemapController->m_flCustomAutoExposureMin;
g_flCustomAutoExposureMax = tonemapController->m_flCustomAutoExposureMax;
g_flCustomBloomScale = tonemapController->m_flCustomBloomScale;
g_flCustomBloomScaleMinimum = tonemapController->m_flCustomBloomScaleMinimum;
g_flBloomExponent = tonemapController->m_flBloomExponent;
g_flBloomSaturation = tonemapController->m_flBloomSaturation;
g_flTonemapPercentTarget = tonemapController->m_flTonemapPercentTarget;
g_flTonemapPercentBrightPixels = tonemapController->m_flTonemapPercentBrightPixels;
g_flTonemapMinAvgLum = tonemapController->m_flTonemapMinAvgLum;
g_flTonemapRate = tonemapController->m_flTonemapRate;
return;
}
}
g_bUseCustomAutoExposureMax = false;
g_bUseCustomBloomScale = false;
g_flBloomExponent = 2.5f;
g_flBloomSaturation = 1.0f;
g_flTonemapPercentTarget = 65.0f;
g_flTonemapPercentBrightPixels = 2.0f;
g_flTonemapMinAvgLum = 3.0f;
g_flTonemapRate = 1.0f;
}

View File

@@ -0,0 +1,264 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "iviewrender.h"
#include "precache_register.h"
#include "studio.h"
#include "bone_setup.h"
#include "engine/ivmodelinfo.h"
#include "c_fire_smoke.h"
#include "engine/IEngineSound.h"
#include "iefx.h"
#include "dlight.h"
#include "tier0/icommandline.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
PRECACHE_REGISTER_BEGIN( GLOBAL, SmokeStackMaterials )
PRECACHE( MATERIAL, "particle/SmokeStack" )
PRECACHE_REGISTER_END()
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pRecvProp -
// *pStruct -
// *pVarData -
// *pIn -
// objectID -
//-----------------------------------------------------------------------------
void RecvProxy_Scale( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_FireSmoke *pFireSmoke = (C_FireSmoke *) pStruct;
float scale = pData->m_Value.m_Float;
//If changed, update our internal information
if ( ( pFireSmoke->m_flScale != scale ) && ( pFireSmoke->m_flScaleEnd != scale ) )
{
pFireSmoke->m_flScaleStart = pFireSmoke->m_flScaleRegister;
pFireSmoke->m_flScaleEnd = scale;
}
pFireSmoke->m_flScale = scale;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pRecvProp -
// *pStruct -
// *pVarData -
// *pIn -
// objectID -
//-----------------------------------------------------------------------------
void RecvProxy_ScaleTime( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_FireSmoke *pFireSmoke = (C_FireSmoke *) pStruct;
float time = pData->m_Value.m_Float;
//If changed, update our internal information
//if ( pFireSmoke->m_flScaleTime != time )
{
if ( time == -1.0f )
{
pFireSmoke->m_flScaleTimeStart = Helper_GetTime()-1.0f;
pFireSmoke->m_flScaleTimeEnd = pFireSmoke->m_flScaleTimeStart;
}
else
{
pFireSmoke->m_flScaleTimeStart = Helper_GetTime();
pFireSmoke->m_flScaleTimeEnd = Helper_GetTime() + time;
}
}
pFireSmoke->m_flScaleTime = time;
}
//Receive datatable
IMPLEMENT_CLIENTCLASS_DT( C_FireSmoke, DT_FireSmoke, CFireSmoke )
RecvPropFloat( RECVINFO( m_flStartScale )),
RecvPropFloat( RECVINFO( m_flScale ), 0, RecvProxy_Scale ),
RecvPropFloat( RECVINFO( m_flScaleTime ), 0, RecvProxy_ScaleTime ),
RecvPropInt( RECVINFO( m_nFlags ) ),
RecvPropInt( RECVINFO( m_nFlameModelIndex ) ),
RecvPropInt( RECVINFO( m_nFlameFromAboveModelIndex ) ),
END_RECV_TABLE()
//==================================================
// C_FireSmoke
//==================================================
C_FireSmoke::C_FireSmoke()
{
}
C_FireSmoke::~C_FireSmoke()
{
// Shut down our effect if we have it
if ( m_hEffect )
{
m_hEffect->StopEmission(false, false , true);
m_hEffect = NULL;
}
}
#define FLAME_ALPHA_START 0.9f
#define FLAME_ALPHA_END 1.0f
#define FLAME_TRANS_START 0.75f
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FireSmoke::AddFlames( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_FireSmoke::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
Start();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FireSmoke::UpdateEffects( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_FireSmoke::ShouldDraw()
{
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FireSmoke::Start( void )
{
const char *lpszEffectName;
int nSize = (int) floor( m_flStartScale / 36.0f );
RANDOM_CEG_TEST_SECRET_PERIOD( 36, 67 );
switch ( nSize )
{
case 0:
lpszEffectName = ( m_nFlags & bitsFIRESMOKE_SMOKE ) ? "env_fire_tiny_smoke" : "env_fire_tiny";
break;
case 1:
lpszEffectName = ( m_nFlags & bitsFIRESMOKE_SMOKE ) ? "env_fire_small_smoke" : "env_fire_small";
break;
case 2:
lpszEffectName = ( m_nFlags & bitsFIRESMOKE_SMOKE ) ? "env_fire_medium_smoke" : "env_fire_medium";
break;
case 3:
default:
lpszEffectName = ( m_nFlags & bitsFIRESMOKE_SMOKE ) ? "env_fire_large_smoke" : "env_fire_large";
break;
}
// Create the effect of the correct size
m_hEffect = ParticleProp()->Create( lpszEffectName, PATTACH_ABSORIGIN );
}
//-----------------------------------------------------------------------------
// Purpose: FIXME: what's the right way to do this?
//-----------------------------------------------------------------------------
void C_FireSmoke::StartClientOnly( void )
{
Start();
ClientEntityList().AddNonNetworkableEntity( this );
CollisionProp()->CreatePartitionHandle();
AddEffects( EF_NORECEIVESHADOW | EF_NOSHADOW );
AddToLeafSystem();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FireSmoke::RemoveClientOnly(void)
{
ClientThinkList()->RemoveThinkable( GetClientHandle() );
// Remove from the client entity list.
ClientEntityList().RemoveEntity( GetClientHandle() );
::partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() );
RemoveFromLeafSystem();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FireSmoke::UpdateAnimation( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FireSmoke::UpdateFlames( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FireSmoke::UpdateScale( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FireSmoke::Update( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_FireSmoke::FindClipPlane( void )
{
}
//-----------------------------------------------------------------------------
// Purpose: Spawn smoke (...duh)
//-----------------------------------------------------------------------------
void C_FireSmoke::SpawnSmoke( void )
{
}

268
game/client/c_fire_smoke.h Normal file
View File

@@ -0,0 +1,268 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef C_FIRE_SMOKE_H
#define C_FIRE_SMOKE_H
#include "particles_simple.h"
#include "tempent.h"
#include "glow_overlay.h"
#include "view.h"
#include "particle_litsmokeemitter.h"
#include "tier1/utlobjectreference.h"
class CFireOverlay;
class C_FireSprite : public C_Sprite
{
DECLARE_CLASS( C_FireSprite, C_Sprite );
private:
virtual int DrawModel( int flags, const RenderableInstance_t &instance )
{
if ( m_bFadeFromAbove )
{
// The sprites become less visible the more you look down or up at them
Vector vToPos = GetLocalOrigin() - CurrentViewOrigin();
VectorNormalize( vToPos );
float fUpAmount = vToPos.z;
int iAlpha = 255;
if ( fUpAmount < -0.75f )
iAlpha = 0;
else if ( fUpAmount < -0.65f )
iAlpha = 255 - (int)( ( fUpAmount + 0.65f ) * 10.0f * -255.0f );
else if ( fUpAmount > 0.85f )
iAlpha = 0;
else if ( fUpAmount > 0.75f )
iAlpha = 255 - (int)( ( fUpAmount - 0.75f ) * 10.0f * 255.0f );
SetColor( iAlpha, iAlpha, iAlpha );
}
return BaseClass::DrawModel( flags, instance );
}
public:
Vector m_vecMoveDir;
bool m_bFadeFromAbove;
};
class C_FireFromAboveSprite : public C_Sprite
{
DECLARE_CLASS( C_FireFromAboveSprite, C_Sprite );
virtual int DrawModel( int flags, const RenderableInstance_t &instance )
{
// The sprites become more visible the more you look down or up at them
Vector vToPos = GetLocalOrigin() - CurrentViewOrigin();
VectorNormalize( vToPos );
float fUpAmount = vToPos.z;
int iAlpha = 0;
if ( fUpAmount < -0.85f )
iAlpha = 255;
else if ( fUpAmount < -0.65f )
iAlpha = (int)( ( fUpAmount + 0.65f ) * 5.0f * -255.0f );
else if ( fUpAmount > 0.75f )
iAlpha = 255;
else if ( fUpAmount > 0.55f )
iAlpha = (int)( ( fUpAmount - 0.55f ) * 5.0f * 255.0f );
SetColor( iAlpha, iAlpha, iAlpha );
return BaseClass::DrawModel( flags, instance );
}
};
#define NUM_CHILD_FLAMES 4
#define SMOKE_RISE_RATE 92.0f
#define SMOKE_LIFETIME 2.0f
#define EMBER_LIFETIME 2.0f
#define FLAME_CHILD_SPREAD 64.0f
#define FLAME_SOURCE_HEIGHT 128.0f
#define FLAME_FROM_ABOVE_SOURCE_HEIGHT 32.0f
//==================================================
// C_FireSmoke
//==================================================
//NOTENOTE: Mirrored in dlls/fire_smoke.h
#define bitsFIRESMOKE_NONE 0x00000000
#define bitsFIRESMOKE_ACTIVE 0x00000001
#define bitsFIRESMOKE_SMOKE 0x00000002
#define bitsFIRESMOKE_SMOKE_COLLISION 0x00000004
#define bitsFIRESMOKE_GLOW 0x00000008
#define bitsFIRESMOKE_VISIBLE_FROM_ABOVE 0x00000010
#define OVERLAY_MAX_VISIBLE_RANGE 512.0f
class C_FireSmoke : public C_BaseEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_FireSmoke, C_BaseEntity );
C_FireSmoke();
~C_FireSmoke();
void Start( void );
void StartClientOnly( void );
void RemoveClientOnly( void );
protected:
void Update( void );
void UpdateAnimation( void );
void UpdateScale( void );
void UpdateFlames( void );
void AddFlames( void );
void SpawnSmoke( void );
void FindClipPlane( void );
//C_BaseEntity
public:
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual bool ShouldDraw();
float GetScale( void ) const { return m_flScaleRegister; }
//From the server
public:
float m_flStartScale;
float m_flScale;
float m_flScaleTime;
int m_nFlags;
int m_nFlameModelIndex;
int m_nFlameFromAboveModelIndex;
//Client-side only
public:
float m_flScaleRegister;
float m_flScaleStart;
float m_flScaleEnd;
float m_flScaleTimeStart;
float m_flScaleTimeEnd;
float m_flChildFlameSpread;
VPlane m_planeClip;
float m_flClipPerc;
bool m_bClipTested;
bool m_bFadingOut;
protected:
void UpdateEffects( void );
//CSmartPtr<CEmberEffect> m_pEmberEmitter;
CSmartPtr<CLitSmokeEmitter> m_pSmokeEmitter;
C_FireSprite m_entFlames[NUM_CHILD_FLAMES];
C_FireFromAboveSprite m_entFlamesFromAbove[NUM_CHILD_FLAMES];
float m_entFlameScales[NUM_CHILD_FLAMES];
TimedEvent m_tParticleSpawn;
CFireOverlay *m_pFireOverlay;
// New Particle Fire Effect
CUtlReference<CNewParticleEffect> m_hEffect;
private:
C_FireSmoke( const C_FireSmoke & );
};
//Fire overlay
class CFireOverlay : public CGlowOverlay
{
public:
//Constructor
explicit CFireOverlay( C_FireSmoke *owner )
{
m_pOwner = owner;
m_flScale = 0.0f;
m_nGUID = random->RandomInt( -999999, 999999 );
}
//-----------------------------------------------------------------------------
// Purpose: Generate a flicker value
// Output : scalar value
//-----------------------------------------------------------------------------
float GetFlickerScale( void )
{
float result;
float time = Helper_GetTime() + m_nGUID;
result = sin( time * 1000.0f );
result += 0.5f * sin( time * 2000.0f );
result -= 0.5f * cos( time * 8000.0f );
return result;
}
//-----------------------------------------------------------------------------
// Purpose: Update the overlay
//-----------------------------------------------------------------------------
virtual bool Update( void )
{
if ( m_pOwner == NULL )
return false;
float scale = m_pOwner->GetScale();
float dscale = scale - m_flScale;
m_vPos[2] += dscale * FLAME_SOURCE_HEIGHT;
m_flScale = scale;
scale *= 0.75f;
float flickerScale = GetFlickerScale();
float newScale = scale + ( scale * flickerScale * 0.1f );
m_Sprites[0].m_flHorzSize = ( newScale * 0.2f ) + ( m_Sprites[0].m_flHorzSize * 0.8f );
m_Sprites[0].m_flVertSize = m_Sprites[0].m_flHorzSize * 1.5f;
float cameraDistance = ( CurrentViewOrigin() - (m_pOwner->GetAbsOrigin())).Length();
C_BasePlayer *local = C_BasePlayer::GetLocalPlayer();
if ( local )
{
cameraDistance *= local->GetFOVDistanceAdjustFactor();
}
if ( cameraDistance > OVERLAY_MAX_VISIBLE_RANGE )
cameraDistance = OVERLAY_MAX_VISIBLE_RANGE;
float alpha = 1.0f - ( cameraDistance / OVERLAY_MAX_VISIBLE_RANGE );
Vector newColor = m_vBaseColors[0] + ( m_vBaseColors[0] * flickerScale * 0.5f );
m_Sprites[0].m_vColor = ( newColor * 0.1f ) + ( m_Sprites[0].m_vColor * 0.9f ) * alpha;
return true;
}
public:
C_FireSmoke *m_pOwner;
Vector m_vBaseColors[MAX_SUN_LAYERS];
float m_flScale;
int m_nGUID;
};
#endif // C_FIRE_SMOKE_H

352
game/client/c_fish.cpp Normal file
View File

@@ -0,0 +1,352 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// c_fish.cpp
// Simple fish client-side logic
// Author: Michael S. Booth, April 2005
#include "cbase.h"
#include <bitbuf.h>
#include "engine/ivdebugoverlay.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern float UTIL_WaterLevel( const Vector &position, float minz, float maxz );
ConVar FishDebug( "fish_debug", "0", FCVAR_CHEAT, "Show debug info for fish" );
//-----------------------------------------------------------------------------
/**
* Client-side fish entity
*/
class C_Fish : public C_BaseAnimating
{
public:
DECLARE_CLASS( C_Fish, C_BaseAnimating );
DECLARE_CLIENTCLASS();
virtual void Spawn( void );
virtual void ClientThink();
virtual void OnDataChanged( DataUpdateType_t type );
private:
friend void RecvProxy_FishOriginX( const CRecvProxyData *pData, void *pStruct, void *pOut );
friend void RecvProxy_FishOriginY( const CRecvProxyData *pData, void *pStruct, void *pOut );
Vector m_pos; ///< local position
Vector m_vel; ///< local velocity
QAngle m_angles; ///< local angles
int m_localLifeState; ///< our version of m_lifeState
float m_deathDepth; ///< water depth when we died
float m_deathAngle; ///< angle to float at when dead
float m_buoyancy; ///< so each fish floats at a different rate when dead
CountdownTimer m_wiggleTimer; ///< for simulating swimming motions
float m_wigglePhase; ///< where in the wiggle sinusoid we are
float m_wiggleRate; ///< the speed of our wiggling
Vector m_actualPos; ///< position from server
QAngle m_actualAngles; ///< angles from server
Vector m_poolOrigin;
float m_waterLevel; ///< Z coordinate of water surface
bool m_gotUpdate; ///< true after we have received a network update
enum { MAX_ERROR_HISTORY = 20 };
float m_errorHistory[ MAX_ERROR_HISTORY ]; ///< error history samples
int m_errorHistoryIndex;
int m_errorHistoryCount;
float m_averageError;
};
//-----------------------------------------------------------------------------
void RecvProxy_FishOriginX( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_Fish *fish = (C_Fish *)pStruct;
float *out = (float *)pOut;
*out = pData->m_Value.m_Float + fish->m_poolOrigin.x;
}
void RecvProxy_FishOriginY( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
C_Fish *fish = (C_Fish *)pStruct;
float *out = (float *)pOut;
*out = pData->m_Value.m_Float + fish->m_poolOrigin.y;
}
IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_Fish, DT_CFish, CFish )
RecvPropVector( RECVINFO(m_poolOrigin) ),
RecvPropFloat( RECVINFO_NAME( m_actualPos.x, m_x ), 0, RecvProxy_FishOriginX ),
RecvPropFloat( RECVINFO_NAME( m_actualPos.y, m_y ), 0, RecvProxy_FishOriginY ),
RecvPropFloat( RECVINFO_NAME( m_actualPos.z, m_z ) ),
RecvPropFloat( RECVINFO_NAME( m_actualAngles.y, m_angle ) ),
RecvPropInt( RECVINFO(m_nModelIndex) ),
RecvPropInt( RECVINFO(m_lifeState) ),
RecvPropFloat( RECVINFO(m_waterLevel) ), ///< get this from the server in case we die when slightly out of the water due to error correction
END_RECV_TABLE()
//-----------------------------------------------------------------------------
void C_Fish::Spawn( void )
{
BaseClass::Spawn();
m_angles = QAngle( 0, 0, 0 );
m_actualAngles = m_angles;
m_vel = Vector( 0, 0, 0 );
m_gotUpdate = false;
m_localLifeState = LIFE_ALIVE;
m_buoyancy = RandomFloat( 0.4f, 1.0f );
m_errorHistoryIndex = 0;
m_errorHistoryCount = 0;
m_averageError = 0.0f;
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//-----------------------------------------------------------------------------
void C_Fish::ClientThink()
{
if (FishDebug.GetBool())
{
debugoverlay->AddLineOverlay( m_pos, m_actualPos, 255, 0, 0, true, 0.1f );
switch( m_localLifeState )
{
case LIFE_DYING:
debugoverlay->AddTextOverlay( m_pos, 0.1f, "DYING" );
break;
case LIFE_DEAD:
debugoverlay->AddTextOverlay( m_pos, 0.1f, "DEAD" );
break;
}
}
float deltaT = gpGlobals->frametime;
// check if we just died
if (m_localLifeState == LIFE_ALIVE && m_lifeState != LIFE_ALIVE)
{
// we have died
m_localLifeState = LIFE_DYING;
m_deathDepth = m_pos.z;
// determine surface float angle
m_deathAngle = RandomFloat( 87.0f, 93.0f ) * ((RandomInt( 0, 100 ) < 50) ? 1.0f : -1.0f);
}
switch( m_localLifeState )
{
case LIFE_DYING:
{
// depth parameter
float t = (m_pos.z - m_deathDepth) / (m_waterLevel - m_deathDepth);
t *= t;
// roll onto side
m_angles.z = m_deathAngle * t;
// float to surface
const float fudge = 2.0f;
if (m_pos.z < m_waterLevel - fudge)
{
m_vel.z += (1.0f - t) * m_buoyancy * deltaT;
}
else
{
m_localLifeState = LIFE_DEAD;
}
break;
}
case LIFE_DEAD:
{
// depth parameter
float t = (m_pos.z - m_deathDepth) / (m_waterLevel - m_deathDepth);
t *= t;
// roll onto side
m_angles.z = m_deathAngle * t;
// keep near water surface
const float sub = 0.5f;
m_vel.z += 10.0f * (m_waterLevel - m_pos.z - sub) * deltaT;
// bob on surface
const float rollAmp = 5.0f;
const float rollFreq = 2.33f;
m_angles.z += rollAmp * sin( rollFreq * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
const float rollAmp2 = 7.0f;
const float rollFreq2 = 4.0f;
m_angles.x += rollAmp2 * sin( rollFreq2 * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
const float bobAmp = 0.75f;
const float bobFreq = 4.0f;
m_vel.z += bobAmp * sin( bobFreq * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
const float bobAmp2 = 0.75f;
const float bobFreq2 = 3.333f;
m_vel.z += bobAmp2 * sin( bobFreq2 * (gpGlobals->curtime + 10.0f * entindex()) ) * deltaT;
// decay movement speed to zero
const float drag = 1.0f;
m_vel.z -= drag * m_vel.z * deltaT;
break;
}
case LIFE_ALIVE:
{
// use server-side Z coordinate directly
m_pos.z = m_actualPos.z;
// use server-side angles
m_angles = m_actualAngles;
// fishy wiggle based on movement
if (!m_wiggleTimer.IsElapsed())
{
float swimPower = 1.0f - (m_wiggleTimer.GetElapsedTime() / m_wiggleTimer.GetCountdownDuration());
const float amp = 6.0f * swimPower;
float wiggle = amp * sin( m_wigglePhase );
m_wigglePhase += m_wiggleRate * deltaT;
// wiggle decay
const float wiggleDecay = 5.0f;
m_wiggleRate -= wiggleDecay * deltaT;
m_angles.y += wiggle;
}
break;
}
}
// compute error between our local position and actual server position
Vector error = m_actualPos - m_pos;
error.z = 0.0f;
float errorLen = error.Length();
if (m_localLifeState == LIFE_ALIVE)
{
// if error is far above average, start swimming
const float wiggleThreshold = 2.0f;
if (errorLen - m_averageError > wiggleThreshold)
{
// if error is large, we must have started swimming
const float swimTime = 5.0f;
m_wiggleTimer.Start( swimTime );
m_wiggleRate = 2.0f * errorLen;
const float maxWiggleRate = 30.0f;
if (m_wiggleRate > maxWiggleRate)
{
m_wiggleRate = maxWiggleRate;
}
}
// update average error
m_errorHistory[ m_errorHistoryIndex++ ] = errorLen;
if (m_errorHistoryIndex >= MAX_ERROR_HISTORY)
{
m_errorHistoryIndex = 0;
m_errorHistoryCount = MAX_ERROR_HISTORY;
}
else if (m_errorHistoryCount < MAX_ERROR_HISTORY)
{
++m_errorHistoryCount;
}
m_averageError = 0.0f;
if (m_errorHistoryCount)
{
for( int r=0; r<m_errorHistoryCount; ++r )
{
m_averageError += m_errorHistory[r];
}
m_averageError /= (float)m_errorHistoryCount;
}
}
// keep fish motion smooth by correcting towards actual server position
// NOTE: This only tracks XY motion
const float maxError = 20.0f;
float errorT = errorLen / maxError;
if (errorT > 1.0f)
{
errorT = 1.0f;
}
// we want a nonlinear spring force for tracking
errorT *= errorT;
// as fish move faster, their error increases - use a stiffer spring when fast, and a weak one when slow
const float trackRate = 0.0f + errorT * 115.0f;
m_vel.x += trackRate * error.x * deltaT;
m_vel.y += trackRate * error.y * deltaT;
const float trackDrag = 2.0f + errorT * 6.0f;
m_vel.x -= trackDrag * m_vel.x * deltaT;
m_vel.y -= trackDrag * m_vel.y * deltaT;
// euler integration
m_pos += m_vel * deltaT;
SetNetworkOrigin( m_pos );
SetAbsOrigin( m_pos );
SetNetworkAngles( m_angles );
SetAbsAngles( m_angles );
}
//-----------------------------------------------------------------------------
void C_Fish::OnDataChanged( DataUpdateType_t type )
{
//if (!m_gotUpdate)
if (type == DATA_UPDATE_CREATED)
{
// initial update
m_gotUpdate = true;
m_pos = m_actualPos;
m_vel = Vector( 0, 0, 0 );
return;
}
}

View File

@@ -0,0 +1,305 @@
#include "cbase.h"
#include "forcefeedback.h"
#include "hud_macros.h"
#include "input.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
#define FF_CLIENT_FLAG 0x8000
class FFParams
{
public:
FORCEFEEDBACK_t m_nEffectType;
FFBaseParams_t m_BaseParams;
};
struct FFEffectInfo_t
{
FORCEFEEDBACK_t effectType;
char const *name;
};
#define DECLARE_FFEFFECT( name ) { name, #name }
static FFEffectInfo_t g_EffectTypes[] =
{
DECLARE_FFEFFECT( FORCE_FEEDBACK_SHOT_SINGLE ),
DECLARE_FFEFFECT( FORCE_FEEDBACK_SHOT_DOUBLE ),
DECLARE_FFEFFECT( FORCE_FEEDBACK_TAKEDAMAGE ),
DECLARE_FFEFFECT( FORCE_FEEDBACK_SCREENSHAKE ),
DECLARE_FFEFFECT( FORCE_FEEDBACK_SKIDDING ),
DECLARE_FFEFFECT( FORCE_FEEDBACK_BREAKING )
};
//-----------------------------------------------------------------------------
// Purpose:
// Input : effect -
// Output : char const
//-----------------------------------------------------------------------------
char const *NameForForceFeedbackEffect( FORCEFEEDBACK_t effect )
{
int c = ARRAYSIZE( g_EffectTypes );
if ( (int)effect < 0 || (int)effect >= c )
return "???";
const FFEffectInfo_t& info = g_EffectTypes[ (int)effect ];
Assert( info.effectType == effect );
return info.name;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *name -
// Output : FORCEFEEDBACK_t
//-----------------------------------------------------------------------------
FORCEFEEDBACK_t ForceFeedbackEffectForName( const char *name )
{
int c = ARRAYSIZE( g_EffectTypes );
for ( int i = 0 ; i < c; ++i )
{
const FFEffectInfo_t& info = g_EffectTypes[ i ];
if ( !Q_stricmp( info.name, name ) )
return info.effectType;
}
return ( FORCEFEEDBACK_t )-1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CForceFeedback : public IForceFeedback, public CAutoGameSystem
{
public:
virtual bool Init();
virtual void Shutdown();
// API
virtual void StopAllEffects( CBasePlayer *player );
virtual void StopEffect( CBasePlayer *player, FORCEFEEDBACK_t effect );
virtual void StartEffect( CBasePlayer *player, FORCEFEEDBACK_t effect, const FFBaseParams_t& params );
virtual void PauseAll( CBasePlayer *player );
virtual void ResumeAll( CBasePlayer *player );
void MsgFunc_ForceFeedback( bf_read &msg );
private:
void Internal_StopAllEffects();
void Internal_StopEffect( FORCEFEEDBACK_t effect );
void Internal_StartEffect( FORCEFEEDBACK_t, const FFBaseParams_t& params );
void Internal_PauseAll();
void Internal_ResumeAll();
};
static CForceFeedback g_ForceFeedbackSingleton;
IForceFeedback *forcefeedback = &g_ForceFeedbackSingleton;
//-----------------------------------------------------------------------------
// Purpose:
// Input : &msg -
//-----------------------------------------------------------------------------
void __MsgFunc_ForceFeedback( bf_read &msg )
{
g_ForceFeedbackSingleton.MsgFunc_ForceFeedback( msg );
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CForceFeedback::Init()
{
HOOK_MESSAGE( ForceFeedback );
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CForceFeedback::Shutdown()
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *player -
//-----------------------------------------------------------------------------
void CForceFeedback::StopAllEffects( CBasePlayer *player )
{
if ( !player )
return;
Internal_StopAllEffects();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *player -
// effect -
//-----------------------------------------------------------------------------
void CForceFeedback::StopEffect( CBasePlayer *player, FORCEFEEDBACK_t effect )
{
if ( !player )
return;
Internal_StopEffect( effect );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *player -
// effect -
// params -
//-----------------------------------------------------------------------------
void CForceFeedback::StartEffect( CBasePlayer *player, FORCEFEEDBACK_t effect, const FFBaseParams_t& params )
{
if ( !player )
{
return;
}
Internal_StartEffect( effect, params );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *player -
//-----------------------------------------------------------------------------
void CForceFeedback::PauseAll( CBasePlayer *player )
{
if ( !player )
return;
Internal_PauseAll();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *player -
//-----------------------------------------------------------------------------
void CForceFeedback::ResumeAll( CBasePlayer *player )
{
if ( !player )
return;
Internal_ResumeAll();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CForceFeedback::Internal_StopAllEffects()
{
input->ForceFeedback_StopAll();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : heffect -
//-----------------------------------------------------------------------------
void CForceFeedback::Internal_StopEffect( FORCEFEEDBACK_t effect )
{
input->ForceFeedback_Stop( effect );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : effect -
//-----------------------------------------------------------------------------
void CForceFeedback::Internal_StartEffect( FORCEFEEDBACK_t effect, const FFBaseParams_t& params)
{
char const *name = NameForForceFeedbackEffect( effect );
Msg( "Starting FF effect '%s'\n", name );
FFParams p;
p.m_nEffectType = effect;
p.m_BaseParams = params;
input->ForceFeedback_Start( effect, params );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CForceFeedback::Internal_PauseAll()
{
input->ForceFeedback_Pause();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CForceFeedback::Internal_ResumeAll()
{
input->ForceFeedback_Resume();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pszName -
// iSize -
// *pbuf -
//-----------------------------------------------------------------------------
void CForceFeedback::MsgFunc_ForceFeedback( bf_read &msg )
{
byte msgType = msg.ReadByte();
switch ( msgType )
{
default:
{
Warning( "Bad parse in MsgFunc_ForceFeedback!\n" );
}
break;
case FFMSG_STOPALL:
{
Internal_StopAllEffects();
}
break;
case FFMSG_START:
{
FORCEFEEDBACK_t effectType = (FORCEFEEDBACK_t)msg.ReadByte();
FFBaseParams_t params;
params.m_flDirection = 360.0f * ( (byte)msg.ReadByte() / 255.0f );
params.m_flDuration = (float)msg.ReadLong() / 1000.0f;
params.m_flGain = ( (byte)msg.ReadByte() / 255.0f );
params.m_nPriority = msg.ReadByte();
params.m_bSolo = msg.ReadByte() == 0 ? false : true;
if ( effectType >= 0 && effectType < NUM_FORCE_FEEDBACK_PRESETS )
{
Internal_StartEffect( effectType, params );
}
else
{
Warning( "Bad parse in MsgFunc_ForceFeedback, FFMSG_START (%i)!\n", effectType );
}
}
break;
case FFMSG_STOP:
{
FORCEFEEDBACK_t effectType = (FORCEFEEDBACK_t)msg.ReadByte();
Internal_StopEffect( effectType );
}
break;
case FFMSG_PAUSE:
{
Internal_PauseAll();
}
break;
case FFMSG_RESUME:
{
Internal_ResumeAll();
}
break;
}
}

View File

@@ -0,0 +1,132 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#include "cbase.h"
#include "view.h"
#include "model_types.h"
#include "ivrenderview.h"
#include "engine/ivmodelinfo.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define VIEWER_PADDING 80.0f
class C_FuncAreaPortalWindow : public C_BaseEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_FuncAreaPortalWindow, C_BaseEntity );
// Overrides.
public:
RenderableTranslucencyType_t ComputeTranslucencyType( void );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
virtual bool ShouldReceiveProjectedTextures( int flags );
private:
float GetDistanceBlend();
public:
float m_flFadeStartDist; // Distance at which it starts fading (when <= this, alpha=m_flTranslucencyLimit).
float m_flFadeDist; // Distance at which it becomes solid.
// 0-1 value - minimum translucency it's allowed to get to.
float m_flTranslucencyLimit;
int m_iBackgroundModelIndex;
};
IMPLEMENT_CLIENTCLASS_DT( C_FuncAreaPortalWindow, DT_FuncAreaPortalWindow, CFuncAreaPortalWindow )
RecvPropFloat( RECVINFO( m_flFadeStartDist ) ),
RecvPropFloat( RECVINFO( m_flFadeDist ) ),
RecvPropFloat( RECVINFO( m_flTranslucencyLimit ) ),
RecvPropInt( RECVINFO( m_iBackgroundModelIndex ) )
END_RECV_TABLE()
RenderableTranslucencyType_t C_FuncAreaPortalWindow::ComputeTranslucencyType( void )
{
return RENDERABLE_IS_TRANSLUCENT;
}
int C_FuncAreaPortalWindow::DrawModel( int flags, const RenderableInstance_t &instance )
{
if ( !m_bReadyToDraw )
return 0;
if( !GetModel() )
return 0;
// Make sure we're a brush model.
int modelType = modelinfo->GetModelType( GetModel() );
if( modelType != mod_brush )
return 0;
// Draw the fading version.
float flBlendAlpha = GetDistanceBlend();
if ( flBlendAlpha == 0.0f )
return 0;
render->SetBlend( flBlendAlpha );
DrawBrushModelMode_t mode = DBM_DRAW_ALL;
if ( flags & STUDIO_TWOPASS )
{
mode = ( flags & STUDIO_TRANSPARENCY ) ? DBM_DRAW_TRANSLUCENT_ONLY : DBM_DRAW_OPAQUE_ONLY;
}
render->DrawBrushModelEx(
this,
(model_t *)GetModel(),
GetAbsOrigin(),
GetAbsAngles(),
mode );
// Draw the optional foreground model next.
// Only use the alpha in the texture from the thing in the front.
if (m_iBackgroundModelIndex >= 0)
{
render->SetBlend( 1 );
model_t *pBackground = ( model_t * )modelinfo->GetModel( m_iBackgroundModelIndex );
if( pBackground && modelinfo->GetModelType( pBackground ) == mod_brush )
{
render->DrawBrushModelEx(
this,
pBackground,
GetAbsOrigin(),
GetAbsAngles(),
mode );
}
}
return 1;
}
float C_FuncAreaPortalWindow::GetDistanceBlend()
{
// Get the viewer's distance to us.
float flDist = CollisionProp()->CalcDistanceFromPoint( CurrentViewOrigin() );
C_BasePlayer *local = C_BasePlayer::GetLocalPlayer();
if ( local )
{
flDist *= local->GetFOVDistanceAdjustFactor();
}
return RemapValClamped( flDist, m_flFadeStartDist, m_flFadeDist, m_flTranslucencyLimit, 1 );
}
bool C_FuncAreaPortalWindow::ShouldReceiveProjectedTextures( int flags )
{
return false;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef C_FUNC_BREAKABLESURF_H
#define C_FUNC_BREAKABLESURF_H
#ifdef _WIN32
#pragma once
#endif
#include "iviewrender.h"
#include "proxyentity.h"
#define MAX_NUM_PANELS 16
#define NUM_EDGE_TYPES 4
#define NUM_EDGE_STYLES 3
extern IVDebugOverlay *debugoverlay;
enum WinSide_t
{
WIN_SIDE_BOTTOM,
WIN_SIDE_RIGHT,
WIN_SIDE_TOP,
WIN_SIDE_LEFT,
};
enum WinEdge_t
{
EDGE_NOT = -1, // No edge
EDGE_NONE, /* No edge on both sides /##\ */
EDGE_FULL, // Edge on both sides |##|
EDGE_LEFT, /* Edge is on left only |##\ */
EDGE_RIGHT, // Edge is on right only /##|
};
#define STYLE_HIGHLIGHT = -1;
//-----------------------------------------------------------------------------
// All the information associated with a particular handle
//-----------------------------------------------------------------------------
struct Panel_t
{
char m_nWidth;
char m_nHeight;
char m_nSide;
char m_nEdgeType;
char m_nStyle;
};
struct EdgeTexture_t
{
int m_nRenderIndex;
int m_nStyle;
CMaterialReference m_pMaterialEdge;
CTextureReference m_pMaterialEdgeTexture;
};
class C_BreakableSurface : public C_BaseEntity, public IBrushRenderer
{
public:
DECLARE_CLASS( C_BreakableSurface, C_BaseEntity );
DECLARE_DATADESC();
DECLARE_CLIENTCLASS();
int m_nNumWide;
int m_nNumHigh;
float m_flPanelWidth;
float m_flPanelHeight;
Vector m_vNormal;
Vector m_vCorner;
bool m_bIsBroken;
int m_nSurfaceType;
// This is the texture we're going to use to multiply by the cracked base texture
ITexture* m_pCurrentDetailTexture;
// Stores linked list of edges to render
CUtlLinkedList< Panel_t, unsigned short > m_RenderList;
C_BreakableSurface();
~C_BreakableSurface();
public:
void InitMaterial(WinEdge_t nEdgeType, int nEdgeStyle, char const* pMaterialName);
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
RenderableTranslucencyType_t ComputeTranslucencyType( void );
bool HavePanel(int nWidth, int nHeight);
bool RenderBrushModelSurface( IClientEntity* pBaseEntity, IBrushSurface* pBrushSurface );
int DrawModel( int flags, const RenderableInstance_t &instance );
void DrawSolidBlocks( IBrushSurface* pBrushSurface );
virtual void OnRestore();
virtual bool ShouldReceiveProjectedTextures( int flags );
private:
// One bit per pane
CNetworkArray( bool, m_RawPanelBitVec, MAX_NUM_PANELS * MAX_NUM_PANELS );
bool m_PrevRawPanelBitVec[ MAX_NUM_PANELS * MAX_NUM_PANELS ];
// 2 bits of flags and 2 bits of edge type
byte m_nPanelBits[MAX_NUM_PANELS][MAX_NUM_PANELS]; //UNDONE: allocate this dynamically?
CMaterialReference m_pMaterialBox;
EdgeTexture_t m_pSolid;
EdgeTexture_t m_pEdge[NUM_EDGE_TYPES][NUM_EDGE_STYLES];
inline bool InLegalRange(int nWidth, int nHeight);
inline bool IsPanelSolid(int nWidth, int nHeight);
inline bool IsPanelStale(int nWidth, int nHeight);
inline void SetPanelSolid(int nWidth, int nHeight, bool value);
inline void SetPanelStale(int nWidth, int nHeight, bool value);
void DrawOneEdge( IBrushSurface* pBrushSurface, IMesh* pMesh,
CMeshBuilder *pMeshBuilder, const Vector &vStartPos,
const Vector &vWStep, const Vector &vHstep, WinSide_t nEdge);
void DrawOneHighlight( IBrushSurface* pBrushSurface, IMesh* pMesh,
CMeshBuilder *pMeshBuilder, const Vector &vStartPos,
const Vector &vWStep, const Vector &vHstep, WinSide_t nEdge);
void DrawOneBlock(IBrushSurface* pBrushSurface, IMesh* pMesh,
CMeshBuilder *pMeshBuilder, const Vector &vPosition,
const Vector &vWidth, const Vector &vHeight);
void DrawRenderList( IBrushSurface* pBrushSurface);
void DrawRenderListHighlights( IBrushSurface* pBrushSurface );
int FindRenderPanel(int nWidth, int nHeight, WinSide_t nSide);
void AddToRenderList(int nWidth, int nHeight, WinSide_t nSide, WinEdge_t nEdgeType, int forceStyle);
int FindFirstRenderTexture(WinEdge_t nEdgeType, int nStyle);
inline void SetStyleType( int w, int h, int type )
{
Assert( type < NUM_EDGE_STYLES );
Assert( type >= 0 );
// Clear old value
m_nPanelBits[ w ][ h ] &= ( ~0x03 << 2 );
// Insert new value
m_nPanelBits[ w ][ h ] |= ( type << 2 );
}
inline int GetStyleType( int w, int h )
{
int value = m_nPanelBits[ w ][ h ];
value = ( value >> 2 ) & 0x03;
Assert( value < NUM_EDGE_STYLES );
return value;
}
// Gets at the cracked version of the material
void FindCrackedMaterial();
CMaterialReference m_pCrackedMaterial;
CTextureReference m_pMaterialBoxTexture;
void UpdateEdgeType(int nWidth, int nHeight, int forceStyle = -1 );
};
class CBreakableSurfaceProxy : public CEntityMaterialProxy
{
public:
CBreakableSurfaceProxy();
virtual ~CBreakableSurfaceProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( C_BaseEntity *pC_BaseEntity );
virtual IMaterial *GetMaterial();
private:
// get at the material whose texture we're going to steal
void AcquireSourceMaterial( C_BaseEntity* pEnt );
IMaterialVar* m_BaseTextureVar;
};
#endif // C_FUNC_BREAKABLESURF_H

View File

@@ -0,0 +1,17 @@
#include "cbase.h"
#include "c_func_brush.h"
#include "toolframework_client.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_FuncBrush, DT_FuncBrush, CFuncBrush )
END_RECV_TABLE()
void C_FuncBrush::OnDataChanged( DataUpdateType_t type )
{
BaseClass::OnDataChanged( type );
bool bCreate = (type == DATA_UPDATE_CREATED) ? true : false;
VPhysicsShadowDataChanged(bCreate, this);
}

View File

@@ -0,0 +1,24 @@
//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//=============================================================================//
#ifndef C_FUNC_BRUSH_H
#define C_FUNC_BRUSH_H
#ifdef _WIN32
#pragma once
#endif
class C_FuncBrush : public C_BaseEntity
{
public:
DECLARE_CLASS( C_FuncBrush, C_BaseEntity );
DECLARE_CLIENTCLASS();
void OnDataChanged( DataUpdateType_t type );
private:
};
#endif // C_FUNC_BRUSH_H

View File

@@ -0,0 +1,150 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "cbase.h"
#include "materialsystem/imaterialproxy.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "functionproxy.h"
#include <keyvalues.h>
#include "mathlib/vmatrix.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class C_FuncConveyor : public C_BaseEntity
{
public:
DECLARE_CLASS( C_FuncConveyor, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_FuncConveyor();
float GetConveyorSpeed() { return m_flConveyorSpeed; }
private:
float m_flConveyorSpeed;
};
IMPLEMENT_CLIENTCLASS_DT( C_FuncConveyor, DT_FuncConveyor, CFuncConveyor )
RecvPropFloat( RECVINFO( m_flConveyorSpeed ) ),
END_RECV_TABLE()
C_FuncConveyor::C_FuncConveyor()
{
m_flConveyorSpeed = 0.0;
}
class CConveyorMaterialProxy : public IMaterialProxy
{
public:
CConveyorMaterialProxy();
virtual ~CConveyorMaterialProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
virtual IMaterial *GetMaterial();
private:
C_BaseEntity *BindArgToEntity( void *pArg );
IMaterialVar *m_pTextureScrollVar;
};
CConveyorMaterialProxy::CConveyorMaterialProxy()
{
m_pTextureScrollVar = NULL;
}
CConveyorMaterialProxy::~CConveyorMaterialProxy()
{
}
bool CConveyorMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pScrollVarName = pKeyValues->GetString( "textureScrollVar" );
if( !pScrollVarName )
return false;
bool foundVar;
m_pTextureScrollVar = pMaterial->FindVar( pScrollVarName, &foundVar, false );
if( !foundVar )
return false;
return true;
}
C_BaseEntity *CConveyorMaterialProxy::BindArgToEntity( void *pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
return pRend->GetIClientUnknown()->GetBaseEntity();
}
void CConveyorMaterialProxy::OnBind( void *pC_BaseEntity )
{
if( !pC_BaseEntity )
return;
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
if ( !pEntity )
return;
C_FuncConveyor *pConveyor = dynamic_cast<C_FuncConveyor*>(pEntity);
if ( !pConveyor )
return;
if ( !m_pTextureScrollVar )
{
return;
}
float flConveyorSpeed = pConveyor->GetConveyorSpeed();
float flRate = abs( flConveyorSpeed ) / 128.0;
float flAngle = (flConveyorSpeed >= 0) ? 180 : 0;
float sOffset = gpGlobals->curtime * cos( flAngle * ( M_PI / 180.0f ) ) * flRate;
float tOffset = gpGlobals->curtime * sin( flAngle * ( M_PI / 180.0f ) ) * flRate;
// make sure that we are positive
if( sOffset < 0.0f )
{
sOffset += 1.0f + -( int )sOffset;
}
if( tOffset < 0.0f )
{
tOffset += 1.0f + -( int )tOffset;
}
// make sure that we are in a [0,1] range
sOffset = sOffset - ( int )sOffset;
tOffset = tOffset - ( int )tOffset;
if (m_pTextureScrollVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)
{
VMatrix mat;
MatrixBuildTranslation( mat, sOffset, tOffset, 0.0f );
m_pTextureScrollVar->SetMatrixValue( mat );
}
else
{
m_pTextureScrollVar->SetVecValue( sOffset, tOffset, 0.0f );
}
}
IMaterial *CConveyorMaterialProxy::GetMaterial()
{
return m_pTextureScrollVar ? m_pTextureScrollVar->GetOwningMaterial() : NULL;
}
EXPOSE_MATERIAL_PROXY( CConveyorMaterialProxy, ConveyorScroll );

367
game/client/c_func_dust.cpp Normal file
View File

@@ -0,0 +1,367 @@
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "fx.h"
#include "c_func_dust.h"
#include "func_dust_shared.h"
#include "c_te_particlesystem.h"
#include "env_wind_shared.h"
#include "engine/IEngineTrace.h"
#include "tier0/vprof.h"
#include "particles_ez.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_Func_Dust, DT_Func_Dust, CFunc_Dust )
RecvPropInt( RECVINFO(m_Color), 0, RecvProxy_Int32ToColor32 ),
RecvPropInt( RECVINFO(m_SpawnRate) ),
RecvPropFloat( RECVINFO(m_flSizeMin) ),
RecvPropFloat( RECVINFO(m_flSizeMax) ),
RecvPropInt( RECVINFO(m_LifetimeMin) ),
RecvPropInt( RECVINFO(m_LifetimeMax) ),
RecvPropInt( RECVINFO(m_DustFlags) ),
RecvPropInt( RECVINFO(m_SpeedMax) ),
RecvPropInt( RECVINFO(m_DistMax) ),
RecvPropInt( RECVINFO( m_nModelIndex ) ),
RecvPropFloat( RECVINFO( m_FallSpeed ) ),
RecvPropBool( RECVINFO( m_bAffectedByWind ) ),
RecvPropDataTable( RECVINFO_DT( m_Collision ), 0, &REFERENCE_RECV_TABLE(DT_CollisionProperty) ),
END_RECV_TABLE()
// ------------------------------------------------------------------------------------ //
// CDustEffect implementation.
// ------------------------------------------------------------------------------------ //
#define DUST_ACCEL 50
void CDustEffect::RenderParticles( CParticleRenderIterator *pIterator )
{
const CFuncDustParticle *pParticle = (const CFuncDustParticle*)pIterator->GetFirst();
while ( pParticle )
{
// Velocity.
float flAlpha;
if( m_pDust->m_DustFlags & DUSTFLAGS_FROZEN )
{
flAlpha = 1;
}
else
{
// Alpha.
float flAngle = (pParticle->m_flLifetime / pParticle->m_flDieTime) * M_PI * 2;
flAlpha = sin( flAngle - (M_PI * 0.5f) ) * 0.5f + 0.5f;
}
Vector tPos;
TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos );
float sortKey = (int) tPos.z;
if( -tPos.z <= m_pDust->m_DistMax )
{
flAlpha *= 1 + (tPos.z / m_pDust->m_DistMax);
// Draw it.
float flSize = pParticle->m_flSize;
if( m_pDust->m_DustFlags & DUSTFLAGS_SCALEMOTES )
flSize *= -tPos.z;
RenderParticle_Color255Size(
pIterator->GetParticleDraw(),
tPos,
Vector( m_pDust->m_Color.r, m_pDust->m_Color.g, m_pDust->m_Color.b ),
flAlpha * m_pDust->m_Color.a,
flSize
);
}
pParticle = (const CFuncDustParticle*)pIterator->GetNext( sortKey );
}
}
void CDustEffect::SimulateParticles( CParticleSimulateIterator *pIterator )
{
Vector vecWind;
if ( m_pDust->m_bAffectedByWind )
GetWindspeedAtTime( gpGlobals->curtime, vecWind );
else
vecWind = Vector( 0, 0, 0 );
CFuncDustParticle *pParticle = (CFuncDustParticle*)pIterator->GetFirst();
while ( pParticle )
{
// Velocity.
if( !(m_pDust->m_DustFlags & DUSTFLAGS_FROZEN) )
{
// Kill the particle?
pParticle->m_flLifetime += pIterator->GetTimeDelta();
if( pParticle->m_flLifetime >= pParticle->m_flDieTime )
{
pIterator->RemoveParticle( pParticle );
}
else
{
for ( int i = 0 ; i < 2 ; i++ )
{
if ( pParticle->m_vVelocity[i] < vecWind[i] )
{
pParticle->m_vVelocity[i] += ( gpGlobals->frametime * DUST_ACCEL );
// clamp
if ( pParticle->m_vVelocity[i] > vecWind[i] )
pParticle->m_vVelocity[i] = vecWind[i];
}
else if (pParticle->m_vVelocity[i] > vecWind[i] )
{
pParticle->m_vVelocity[i] -= ( gpGlobals->frametime * DUST_ACCEL );
// clamp.
if ( pParticle->m_vVelocity[i] < vecWind[i] )
pParticle->m_vVelocity[i] = vecWind[i];
}
}
// Apply velocity.
pParticle->m_Pos.MulAdd( pParticle->m_Pos, pParticle->m_vVelocity, pIterator->GetTimeDelta() );
}
}
pParticle = (CFuncDustParticle*)pIterator->GetNext();
}
}
// ------------------------------------------------------------------------------------ //
// C_Func_Dust implementation.
// ------------------------------------------------------------------------------------ //
C_Func_Dust::C_Func_Dust() : m_Effect( "C_Func_Dust" )
{
m_Effect.m_pDust = this;
m_Effect.SetDynamicallyAllocated( false ); // So it doesn't try to delete itself.
}
C_Func_Dust::~C_Func_Dust()
{
}
void C_Func_Dust::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if( updateType == DATA_UPDATE_CREATED )
{
m_hMaterial = m_Effect.GetPMaterial( "particle/sparkles" );
m_Effect.SetSortOrigin( WorldSpaceCenter( ) );
// Let us think each frame.
SetNextClientThink( CLIENT_THINK_ALWAYS );
// If we're setup to be frozen, just make a bunch of particles initially.
if( m_DustFlags & DUSTFLAGS_FROZEN )
{
for( int i=0; i < m_SpawnRate; i++ )
{
AttemptSpawnNewParticle();
}
}
}
m_Spawner.Init( m_SpawnRate ); // N particles per second
}
void C_Func_Dust::ClientThink()
{
// If frozen, don't make new particles.
if( m_DustFlags & DUSTFLAGS_FROZEN )
return;
// Spawn particles?
if( m_DustFlags & DUSTFLAGS_ON )
{
float flDelta = MIN( gpGlobals->frametime, 0.1f );
while( m_Spawner.NextEvent( flDelta ) )
{
AttemptSpawnNewParticle();
}
}
// Tell the particle manager our bbox.
Vector vWorldMins, vWorldMaxs;
CollisionProp()->WorldSpaceAABB( &vWorldMins, &vWorldMaxs );
vWorldMins -= Vector( m_flSizeMax, m_flSizeMax, m_flSizeMax );
vWorldMaxs += Vector( m_flSizeMax, m_flSizeMax, m_flSizeMax );
m_Effect.GetBinding().SetBBox( vWorldMins, vWorldMaxs );
}
bool C_Func_Dust::ShouldDraw()
{
return false;
}
void C_Func_Dust::AttemptSpawnNewParticle()
{
// Find a random spot inside our bmodel.
static int nTests=10;
for( int iTest=0; iTest < nTests; iTest++ )
{
Vector vPercent = RandomVector( 0, 1 );
Vector vTest = WorldAlignMins() + (WorldAlignMaxs() - WorldAlignMins()) * vPercent;
int contents = enginetrace->GetPointContents_Collideable( GetCollideable(), vTest );
if( contents & CONTENTS_SOLID )
{
CFuncDustParticle *pParticle = (CFuncDustParticle*)m_Effect.AddParticle( 10, m_hMaterial, vTest );
if( pParticle )
{
pParticle->m_vVelocity = RandomVector( -m_SpeedMax, m_SpeedMax );
pParticle->m_vVelocity.z -= m_FallSpeed;
pParticle->m_flLifetime = 0;
pParticle->m_flDieTime = RandomFloat( m_LifetimeMin, m_LifetimeMax );
if( m_DustFlags & DUSTFLAGS_SCALEMOTES )
pParticle->m_flSize = RandomFloat( m_flSizeMin/10000.0f, m_flSizeMax/10000.0f );
else
pParticle->m_flSize = RandomFloat( m_flSizeMin, m_flSizeMax );
pParticle->m_Color = m_Color;
}
break;
}
}
}
//
// Dust
//
//-----------------------------------------------------------------------------
// Spew out dust!
//-----------------------------------------------------------------------------
void FX_Dust( const Vector &vecOrigin, const Vector &vecDirection, float flSize, float flSpeed )
{
VPROF_BUDGET( "FX_Dust", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
int numPuffs = (flSize*0.5f);
if ( numPuffs < 1 )
numPuffs = 1;
if ( numPuffs > 32 )
numPuffs = 32;
float speed = flSpeed * 0.1f;
if ( speed < 0 )
speed = 1.0f;
if (speed > 48.0f )
speed = 48.0f;
//FIXME: Better sampling area
Vector offset = vecOrigin + ( vecDirection * flSize );
//Find area ambient light color and use it to tint smoke
Vector worldLight = WorldGetLightForPoint( offset, true );
// Throw puffs
SimpleParticle particle;
for ( int i = 0; i < numPuffs; i++ )
{
offset.Random( -(flSize*0.25f), flSize*0.25f );
offset += vecOrigin + ( vecDirection * flSize );
particle.m_Pos = offset;
particle.m_flLifetime = 0.0f;
particle.m_flDieTime = random->RandomFloat( 0.4f, 1.0f );
particle.m_vecVelocity = vecDirection * random->RandomFloat( speed*0.5f, speed ) * i;
particle.m_vecVelocity[2] = 0.0f;
int color = random->RandomInt( 48, 64 );
particle.m_uchColor[0] = (color+16) + ( worldLight[0] * (float) color );
particle.m_uchColor[1] = (color+8) + ( worldLight[1] * (float) color );
particle.m_uchColor[2] = color + ( worldLight[2] * (float) color );
particle.m_uchStartAlpha= random->RandomInt( 64, 128 );
particle.m_uchEndAlpha = 0;
particle.m_uchStartSize = random->RandomInt( 2, 8 );
particle.m_uchEndSize = random->RandomInt( 24, 48 );
particle.m_flRoll = random->RandomInt( 0, 360 );
particle.m_flRollDelta = random->RandomFloat( -0.5f, 0.5f );
AddSimpleParticle( &particle, g_Mat_DustPuff[random->RandomInt(0,1)] );
}
}
class C_TEDust: public C_TEParticleSystem
{
public:
DECLARE_CLASS( C_TEDust, C_TEParticleSystem );
DECLARE_CLIENTCLASS();
C_TEDust();
virtual ~C_TEDust();
public:
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual bool ShouldDraw() { return true; }
public:
float m_flSize;
float m_flSpeed;
Vector m_vecDirection;
protected:
void GetDustColor( Vector &color );
};
IMPLEMENT_CLIENTCLASS_EVENT_DT( C_TEDust, DT_TEDust, CTEDust )
RecvPropFloat(RECVINFO(m_flSize)),
RecvPropFloat(RECVINFO(m_flSpeed)),
RecvPropVector(RECVINFO(m_vecDirection)),
END_RECV_TABLE()
//==================================================
// C_TEDust
//==================================================
C_TEDust::C_TEDust()
{
}
C_TEDust::~C_TEDust()
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bNewEntity - whether or not to start a new entity
//-----------------------------------------------------------------------------
void C_TEDust::PostDataUpdate( DataUpdateType_t updateType )
{
FX_Dust( m_vecOrigin, m_vecDirection, m_flSize, m_flSpeed );
}
void TE_Dust( IRecipientFilter& filter, float delay,
const Vector &pos, const Vector &dir, float size, float speed )
{
FX_Dust( pos, dir, size, speed );
}

Some files were not shown because too many files have changed in this diff Show More