mirror of
https://github.com/celisej567/BCWSsrc.git
synced 2026-01-03 18:11:08 +03:00
1
This commit is contained in:
41
sp/src/game/client/ShaderEditor/ISEdit_ModelRender.h
Normal file
41
sp/src/game/client/ShaderEditor/ISEdit_ModelRender.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef IV_SHADEREDITOR_MRENDER
|
||||
#define IV_SHADEREDITOR_MRENDER
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef SHADER_EDITOR_DLL
|
||||
#include "../public/tier1/interface.h"
|
||||
#else
|
||||
#include "interface.h"
|
||||
#include "ShaderEditor/ShaderEditorSystem.h"
|
||||
#endif // NOT SHADER_EDITOR_DLL
|
||||
|
||||
|
||||
class ISEditModelRender
|
||||
{
|
||||
public:
|
||||
virtual bool LoadModel( const char *localPath ) = 0;
|
||||
virtual void DestroyModel() = 0;
|
||||
virtual void GetModelCenter( float *pFl3_ViewOffset ) = 0;
|
||||
|
||||
virtual int QuerySequences( char ***list ) = 0;
|
||||
virtual void SetSequence( const char *name ) = 0;
|
||||
|
||||
virtual void ExecRender() = 0;
|
||||
virtual void DoPostProc( int x, int y, int w, int h ) = 0;
|
||||
virtual int MaterialPicker( char ***szMat ) = 0;
|
||||
|
||||
virtual void DestroyCharPtrList( char ***szList ) = 0;
|
||||
};
|
||||
|
||||
|
||||
#ifdef SHADER_EDITOR_DLL
|
||||
extern ISEditModelRender *sEditMRender;
|
||||
#else
|
||||
class SEditModelRender;
|
||||
extern SEditModelRender *sEditMRender;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
128
sp/src/game/client/ShaderEditor/IVShaderEditor.h
Normal file
128
sp/src/game/client/ShaderEditor/IVShaderEditor.h
Normal file
@@ -0,0 +1,128 @@
|
||||
#ifndef IV_SHADEREDITOR
|
||||
#define IV_SHADEREDITOR
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif // _WIN32
|
||||
|
||||
#define pFnClCallback( x ) void(* x )( float *pfl4 )
|
||||
#define pFnClCallback_Declare( x ) void x( float *pfl4 )
|
||||
|
||||
#define pFnVrCallback( x ) void(* x )( bool * const pbOptions, int * const piOptions,\
|
||||
float * const pflOptions, char ** const pszOptions )
|
||||
#define pFnVrCallback_Declare( x ) void x( bool * const pbOptions, int * const piOptions,\
|
||||
float * const pflOptions, char ** const pszOptions )
|
||||
|
||||
#ifndef PROCSHADER_DLL
|
||||
|
||||
#ifdef SHADER_EDITOR_DLL
|
||||
#include "../public/tier1/interface.h"
|
||||
#include "view_shared.h"
|
||||
#else
|
||||
#include "interface.h"
|
||||
#include "ShaderEditor/ShaderEditorSystem.h"
|
||||
#endif // NOT SHADER_EDITOR_DLL
|
||||
|
||||
enum SEDIT_SKYMASK_MODE
|
||||
{
|
||||
SKYMASK_OFF = 0,
|
||||
SKYMASK_QUARTER, // render at 1/4 fb size where possible
|
||||
SKYMASK_FULL, // render at full fb size
|
||||
};
|
||||
|
||||
class CViewSetup_SEdit_Shared
|
||||
{
|
||||
public:
|
||||
CViewSetup_SEdit_Shared()
|
||||
{
|
||||
Q_memset( this, 0, sizeof( CViewSetup_SEdit_Shared ) );
|
||||
};
|
||||
CViewSetup_SEdit_Shared( const CViewSetup &o )
|
||||
{
|
||||
x = o.x;
|
||||
y = o.y;
|
||||
width = o.width;
|
||||
height = o.height;
|
||||
fov = o.fov;
|
||||
fovViewmodel = o.fovViewmodel;
|
||||
origin = o.origin;
|
||||
angles = o.angles;
|
||||
zNear = o.zNear;
|
||||
zFar = o.zFar;
|
||||
zNearViewmodel = o.zNearViewmodel;
|
||||
zFarViewmodel = o.zFarViewmodel;
|
||||
m_flAspectRatio = o.m_flAspectRatio;
|
||||
};
|
||||
int x,y,width,height;
|
||||
float fov,fovViewmodel;
|
||||
Vector origin;
|
||||
QAngle angles;
|
||||
float zNear,zFar,zNearViewmodel,zFarViewmodel;
|
||||
float m_flAspectRatio;
|
||||
};
|
||||
|
||||
|
||||
class IVShaderEditor : public IBaseInterface
|
||||
{
|
||||
public:
|
||||
virtual bool Init( CreateInterfaceFn appSystemFactory, CGlobalVarsBase *pGlobals,
|
||||
void *pSEditMRender,
|
||||
bool bCreateEditor, bool bEnablePrimaryDebug, int iSkymaskMode ) = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
virtual void PrecacheData() = 0;
|
||||
|
||||
// call before Init() to overwrite any paths, pass in NULL for the ones that shouldn't be overwritten
|
||||
virtual void OverridePaths( const char *pszWorkingDirectory,
|
||||
const char *pszCompilePath = NULL, // abs path to compiler binaries
|
||||
const char *pszLocalCompilePath = NULL, // local path to compiler binaries, relative to shader source directory
|
||||
const char *pszGamePath = NULL,
|
||||
const char *pszCanvas = NULL, // path to canvas files
|
||||
const char *pszShaderSource = NULL, // path to shader source files
|
||||
const char *pszDumps = NULL, // path to shader configuration files
|
||||
const char *pszUserFunctions = NULL, // path to custom function bodies
|
||||
const char *pszEditorRoot = NULL ) = 0; // path to 'shadereditorui' home directory
|
||||
|
||||
// update the lib
|
||||
virtual void OnFrame( float frametime ) = 0;
|
||||
virtual void OnPreRender( void *viewsetup ) = 0;
|
||||
virtual void OnSceneRender() = 0;
|
||||
virtual void OnUpdateSkymask(bool bCombineMode, int x, int y, int w, int h) = 0;
|
||||
virtual void OnPostRender( bool bUpdateFB ) = 0;
|
||||
|
||||
// data callbacks for hlsl constants
|
||||
virtual void RegisterClientCallback( const char *name, pFnClCallback(callback), int numComponents ) = 0;
|
||||
virtual void LockClientCallbacks() = 0;
|
||||
|
||||
// view render callbacks for post processing graphs
|
||||
virtual void RegisterViewRenderCallback( const char *pszVrCName, pFnVrCallback(callback),
|
||||
const char **pszBoolNames = NULL, const bool *pBoolDefaults = NULL, const int numBoolParams = 0,
|
||||
const char **pszIntNames = NULL, const int *pIntDefaults = NULL, const int numIntParams = 0,
|
||||
const char **pszFloatNames = NULL, const float *pFloatDefaults = NULL, const int numFloatParams = 0,
|
||||
const char **pszStringNames = NULL, const char **pStringDefaults = NULL, const int numStringParams = 0 ) = 0;
|
||||
virtual void LockViewRenderCallbacks() = 0;
|
||||
|
||||
// post processing effect manipulation (precached effects accessible)
|
||||
// the index becomes invalid when editing the precache list
|
||||
virtual int GetPPEIndex( const char *pszName ) = 0; // returns -1 when not found, case insensitive
|
||||
virtual bool IsPPEEnabled( const int &index ) = 0;
|
||||
virtual void SetPPEEnabled( const int &index, const bool &bEnabled ) = 0;
|
||||
virtual IMaterial *GetPPEMaterial( const int &index, const char *pszNodeName ) = 0;
|
||||
|
||||
// Draws a PPE graph right now or adds it to the render queue (r_queued_post_processing!)
|
||||
// Does not push a new RT but uses the current one
|
||||
// If you have 'during scene' nodes, make sure to call it twice in the appropriate places
|
||||
virtual void DrawPPEOnDemand( const int &index, const bool bInScene = false ) = 0;
|
||||
};
|
||||
|
||||
#define SHADEREDIT_INTERFACE_VERSION "ShaderEditor005"
|
||||
|
||||
#ifdef SHADER_EDITOR_DLL
|
||||
class ShaderEditorInterface;
|
||||
extern ShaderEditorInterface *shaderEdit;
|
||||
#else
|
||||
extern IVShaderEditor *shaderEdit;
|
||||
#endif // NOT SHADER_EDITOR_DLL
|
||||
|
||||
#endif // NOT PROCSHADER_DLL
|
||||
|
||||
#endif // NOT IV_SHADEREDITOR
|
||||
424
sp/src/game/client/ShaderEditor/SEdit_ModelRender.cpp
Normal file
424
sp/src/game/client/ShaderEditor/SEdit_ModelRender.cpp
Normal file
@@ -0,0 +1,424 @@
|
||||
// ******************************************************
|
||||
//
|
||||
// Purpose:
|
||||
// - Handles model rendering requests from the
|
||||
// shader editor library
|
||||
//
|
||||
// ******************************************************
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#include "vgui/iinput.h"
|
||||
#include "vgui_controls/controls.h"
|
||||
|
||||
#include "ShaderEditor/SEdit_ModelRender.h"
|
||||
#include "model_types.h"
|
||||
|
||||
#ifndef SOURCE_2006
|
||||
#include "viewpostprocess.h"
|
||||
#endif
|
||||
|
||||
#include "view.h"
|
||||
#include "input.h"
|
||||
|
||||
#include "beamdraw.h"
|
||||
|
||||
#ifdef SOURCE_2006
|
||||
void ScreenToWorld( int mousex, int mousey, float fov,
|
||||
const Vector& vecRenderOrigin,
|
||||
const QAngle& vecRenderAngles,
|
||||
Vector& vecPickingRay )
|
||||
{
|
||||
float dx, dy;
|
||||
float c_x, c_y;
|
||||
float dist;
|
||||
Vector vpn, vup, vright;
|
||||
|
||||
float scaled_fov = ScaleFOVByWidthRatio( fov, engine->GetScreenAspectRatio() * 0.75f );
|
||||
|
||||
c_x = ScreenWidth() / 2;
|
||||
c_y = ScreenHeight() / 2;
|
||||
|
||||
dx = (float)mousex - c_x;
|
||||
dy = c_y - (float)mousey;
|
||||
|
||||
float dist_denom = tan(M_PI * scaled_fov / 360.0f);
|
||||
dist = c_x / dist_denom;
|
||||
AngleVectors( vecRenderAngles, &vpn, &vright, &vup );
|
||||
vecPickingRay = vpn * dist + vright * ( dx ) + vup * ( dy );
|
||||
VectorNormalize( vecPickingRay );
|
||||
}
|
||||
#else
|
||||
extern void ScreenToWorld( int mousex, int mousey, float fov,
|
||||
const Vector& vecRenderOrigin,
|
||||
const QAngle& vecRenderAngles,
|
||||
Vector& vecPickingRay );
|
||||
#endif
|
||||
|
||||
SEditModelRender __g_ShaderEditorMReder( "ShEditMRender" );
|
||||
SEditModelRender *sEditMRender = &__g_ShaderEditorMReder;
|
||||
|
||||
SEditModelRender::SEditModelRender( char const *name ) : CAutoGameSystemPerFrame( name )
|
||||
{
|
||||
pModelInstance = NULL;
|
||||
m_iNumPoseParams = 0;
|
||||
DestroyModel();
|
||||
}
|
||||
SEditModelRender::~SEditModelRender()
|
||||
{
|
||||
DestroyModel();
|
||||
}
|
||||
|
||||
bool SEditModelRender::Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void SEditModelRender::Shutdown()
|
||||
{
|
||||
}
|
||||
void SEditModelRender::Update( float frametime )
|
||||
{
|
||||
if ( !IsModelReady() )
|
||||
return;
|
||||
|
||||
pModelInstance->StudioFrameAdvance();
|
||||
if ( pModelInstance->GetCycle() >= 1.0f )
|
||||
pModelInstance->SetCycle( pModelInstance->GetCycle() - 1.0f );
|
||||
}
|
||||
void SEditModelRender::LevelInitPostEntity()
|
||||
{
|
||||
ResetModel();
|
||||
}
|
||||
void SEditModelRender::LevelShutdownPostEntity()
|
||||
{
|
||||
ResetModel();
|
||||
}
|
||||
void SEditModelRender::ResetModel()
|
||||
{
|
||||
if ( !IsModelReady() )
|
||||
return;
|
||||
pModelInstance->m_flAnimTime = gpGlobals->curtime;
|
||||
pModelInstance->m_flOldAnimTime = gpGlobals->curtime;
|
||||
}
|
||||
bool SEditModelRender::IsModelReady()
|
||||
{
|
||||
if ( !pModelInstance )
|
||||
return false;
|
||||
|
||||
bool bValid = !!pModelInstance->GetModel();
|
||||
|
||||
if ( bValid && Q_strlen( m_szModelPath ) )
|
||||
{
|
||||
const model_t *pMdl = modelinfo ? modelinfo->FindOrLoadModel( m_szModelPath ) : NULL;
|
||||
if ( pMdl )
|
||||
pModelInstance->SetModelPointer( pMdl );
|
||||
bValid = !!pMdl;
|
||||
}
|
||||
|
||||
if ( !bValid )
|
||||
DestroyModel();
|
||||
|
||||
return bValid;
|
||||
}
|
||||
bool SEditModelRender::LoadModel( const char *localPath )
|
||||
{
|
||||
DestroyModel();
|
||||
|
||||
const model_t *mdl = modelinfo->FindOrLoadModel( localPath );
|
||||
if ( !mdl )
|
||||
return false;
|
||||
|
||||
Q_strcpy( m_szModelPath, localPath );
|
||||
|
||||
C_BaseFlex *pEnt = new C_BaseFlex();
|
||||
pEnt->InitializeAsClientEntity( NULL,
|
||||
#if SWARM_DLL
|
||||
false
|
||||
#else
|
||||
RENDER_GROUP_OPAQUE_ENTITY
|
||||
#endif
|
||||
);
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
pEnt->SetModelPointer( mdl );
|
||||
pEnt->Spawn();
|
||||
|
||||
pEnt->SetAbsAngles( vec3_angle );
|
||||
pEnt->SetAbsOrigin( vec3_origin );
|
||||
|
||||
pEnt->AddEffects( EF_NODRAW | EF_NOINTERP );
|
||||
pEnt->m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK;
|
||||
|
||||
// leave it alone.
|
||||
pEnt->RemoveFromLeafSystem();
|
||||
cl_entitylist->RemoveEntity( pEnt->GetRefEHandle() );
|
||||
pEnt->CollisionProp()->DestroyPartitionHandle();
|
||||
|
||||
CStudioHdr *pHdr = pEnt->GetModelPtr();
|
||||
m_iNumPoseParams = pHdr ? pHdr->GetNumPoseParameters() : 0;
|
||||
|
||||
pModelInstance = pEnt;
|
||||
return true;
|
||||
}
|
||||
void SEditModelRender::DestroyModel()
|
||||
{
|
||||
if ( pModelInstance )
|
||||
pModelInstance->Remove();
|
||||
|
||||
pModelInstance = NULL;
|
||||
m_szModelPath[0] = '\0';
|
||||
m_iNumPoseParams = 0;
|
||||
}
|
||||
void SEditModelRender::GetModelCenter( float *pFl3_ViewOffset )
|
||||
{
|
||||
Q_memset( pFl3_ViewOffset, 0, sizeof(float) * 3 );
|
||||
if ( IsModelReady() )
|
||||
{
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
if ( pModelInstance->GetModelPtr() )
|
||||
{
|
||||
const Vector &vecMin = pModelInstance->GetModelPtr()->hull_min();
|
||||
const Vector &vecMax = pModelInstance->GetModelPtr()->hull_max();
|
||||
Vector vecPos = ( vecMin + ( vecMax - vecMin ) * 0.5f );
|
||||
if ( pFl3_ViewOffset )
|
||||
Q_memcpy( pFl3_ViewOffset, vecPos.Base(), sizeof(float) * 3 );
|
||||
}
|
||||
}
|
||||
}
|
||||
void SEditModelRender::DestroyCharPtrList( char ***szList )
|
||||
{
|
||||
Assert( szList );
|
||||
if ( *szList )
|
||||
{
|
||||
delete [] (**szList);
|
||||
delete [] (*szList);
|
||||
*szList = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int SequenceSort( mstudioseqdesc_t *const *seq1, mstudioseqdesc_t *const *seq2 )
|
||||
{
|
||||
return Q_stricmp( ( *seq1 )->pszLabel(), ( *seq2 )->pszLabel() );
|
||||
}
|
||||
int SEditModelRender::QuerySequences( char ***list )
|
||||
{
|
||||
if ( !IsModelReady() )
|
||||
return 0;
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
CStudioHdr *pHdr = pModelInstance->GetModelPtr();
|
||||
if ( !pHdr )
|
||||
return 0;
|
||||
|
||||
CUtlVector< mstudioseqdesc_t* >hSeqs;
|
||||
for ( int i = 0; i < pHdr->GetNumSeq(); i++ )
|
||||
if ( !( pHdr->pSeqdesc( i ).flags & STUDIO_HIDDEN ) )
|
||||
hSeqs.AddToTail( &pHdr->pSeqdesc( i ) );
|
||||
|
||||
int numSequences = hSeqs.Count();
|
||||
|
||||
if ( !numSequences )
|
||||
return 0;
|
||||
|
||||
hSeqs.Sort( SequenceSort );
|
||||
|
||||
CUtlVector< const char* >hNameList;
|
||||
for ( int i = 0; i < numSequences; i++ )
|
||||
{
|
||||
const char *seqName = NULL;
|
||||
const mstudioseqdesc_t &seqPtr = *hSeqs[ i ];
|
||||
if ( seqPtr.pszLabel() )
|
||||
seqName = seqPtr.pszLabel();
|
||||
else
|
||||
seqName = "Unknown Sequence";
|
||||
|
||||
hNameList.AddToTail( seqName );
|
||||
}
|
||||
|
||||
*list = new char*[numSequences];
|
||||
|
||||
int iTotalLength = 0;
|
||||
for ( int i = 0; i < numSequences; i++ )
|
||||
iTotalLength += Q_strlen( hNameList[i] ) + 1;
|
||||
|
||||
**list = new char[ iTotalLength ];
|
||||
|
||||
int curpos = 0;
|
||||
for ( int i = 0; i < numSequences; i++ )
|
||||
{
|
||||
int curLength = Q_strlen( hNameList[i] ) + 1;
|
||||
(*list)[ i ] = **list + curpos;
|
||||
Q_strcpy( (*list)[ i ], hNameList[i] );
|
||||
curpos += curLength;
|
||||
}
|
||||
|
||||
hNameList.Purge();
|
||||
hSeqs.Purge();
|
||||
return numSequences;
|
||||
}
|
||||
void SEditModelRender::SetSequence( const char *name )
|
||||
{
|
||||
if ( !IsModelReady() )
|
||||
return;
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
pModelInstance->ResetSequence( pModelInstance->LookupSequence( name ) );
|
||||
}
|
||||
void SEditModelRender::ExecRender()
|
||||
{
|
||||
if ( !IsModelReady() )
|
||||
return;
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
for ( int i = 0; i < m_iNumPoseParams; i++ )
|
||||
pModelInstance->SetPoseParameter( i, 0 );
|
||||
|
||||
#if SWARM_DLL
|
||||
RenderableInstance_t instance;
|
||||
instance.m_nAlpha = 255;
|
||||
#endif
|
||||
pModelInstance->DrawModel( STUDIO_RENDER
|
||||
#if SWARM_DLL
|
||||
, instance
|
||||
#endif
|
||||
);
|
||||
}
|
||||
void SEditModelRender::DoPostProc( int x, int y, int w, int h )
|
||||
{
|
||||
#ifndef SOURCE_2006
|
||||
if ( view && view->GetPlayerViewSetup()->m_bDoBloomAndToneMapping )
|
||||
DoEnginePostProcessing( x, y, w, h, false, false );
|
||||
#endif
|
||||
}
|
||||
int SEditModelRender::MaterialPicker( char ***szMat )
|
||||
{
|
||||
int mx, my;
|
||||
#ifdef SOURCE_2006
|
||||
vgui::input()->GetCursorPos( mx, my );
|
||||
#else
|
||||
vgui::input()->GetCursorPosition( mx, my );
|
||||
#endif
|
||||
|
||||
Vector ray;
|
||||
const CViewSetup *pViewSetup = view->GetPlayerViewSetup();
|
||||
float ratio =engine->GetScreenAspectRatio(
|
||||
#if SWARM_DLL
|
||||
pViewSetup->width, pViewSetup->height
|
||||
#endif
|
||||
);
|
||||
|
||||
ratio = ( 1.0f / ratio ) * (4.0f/3.0f);
|
||||
float flFov = ScaleFOVByWidthRatio( pViewSetup->fov, ratio );
|
||||
ScreenToWorld( mx, my, flFov, pViewSetup->origin, pViewSetup->angles, ray );
|
||||
|
||||
Vector start = pViewSetup->origin;
|
||||
Vector end = start + ray * MAX_TRACE_LENGTH;
|
||||
trace_t tr;
|
||||
C_BaseEntity *pIgnore = input->CAM_IsThirdPerson() ? NULL : C_BasePlayer::GetLocalPlayer();
|
||||
UTIL_TraceLine( start, end, MASK_SOLID, pIgnore, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( !tr.DidHit() )
|
||||
return 0;
|
||||
|
||||
int numMaterials = 0;
|
||||
IMaterial **MatList = NULL;
|
||||
studiohdr_t *pSHdr = NULL;
|
||||
|
||||
if ( tr.DidHitWorld() )
|
||||
{
|
||||
if ( tr.hitbox == 0 )
|
||||
{
|
||||
Vector dummy;
|
||||
IMaterial *pMat = engine->TraceLineMaterialAndLighting( start, end, dummy, dummy );
|
||||
if ( pMat )
|
||||
{
|
||||
numMaterials = 1;
|
||||
MatList = new IMaterial*[1];
|
||||
MatList[0] = pMat;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ICollideable *prop = staticpropmgr->GetStaticPropByIndex( tr.hitbox - 1 );
|
||||
if ( prop )
|
||||
{
|
||||
IClientRenderable *pRenderProp = prop->GetIClientUnknown()->GetClientRenderable();
|
||||
if ( pRenderProp )
|
||||
{
|
||||
const model_t *pModel = pRenderProp->GetModel();
|
||||
if ( pModel )
|
||||
pSHdr = modelinfo->GetStudiomodel( pModel );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( tr.m_pEnt )
|
||||
{
|
||||
const model_t *pModel = tr.m_pEnt->GetModel();
|
||||
if ( pModel )
|
||||
pSHdr = modelinfo->GetStudiomodel( pModel );
|
||||
}
|
||||
|
||||
if ( pSHdr )
|
||||
{
|
||||
Assert( !numMaterials && !MatList );
|
||||
numMaterials = pSHdr->numtextures;
|
||||
const int numPaths = pSHdr->numcdtextures;
|
||||
|
||||
if ( numMaterials )
|
||||
{
|
||||
CUtlVector< IMaterial* >hValidMaterials;
|
||||
for ( int i = 0; i < numMaterials; i++ )
|
||||
{
|
||||
mstudiotexture_t *pStudioTex = pSHdr->pTexture( i );
|
||||
const char *matName = pStudioTex->pszName();
|
||||
|
||||
for ( int p = 0; p < numPaths; p++ )
|
||||
{
|
||||
char tmpPath[MAX_PATH];
|
||||
Q_snprintf( tmpPath, MAX_PATH, "%s%s\0", pSHdr->pCdtexture( p ), matName );
|
||||
Q_FixSlashes( tmpPath );
|
||||
IMaterial *pTempMat = materials->FindMaterial( tmpPath, TEXTURE_GROUP_MODEL );
|
||||
if ( !IsErrorMaterial( pTempMat ) )
|
||||
{
|
||||
hValidMaterials.AddToTail( pTempMat );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
numMaterials = hValidMaterials.Count();
|
||||
if ( numMaterials )
|
||||
{
|
||||
MatList = new IMaterial*[ numMaterials ];
|
||||
for ( int i = 0; i < numMaterials; i++ )
|
||||
MatList[i] = hValidMaterials[i];
|
||||
}
|
||||
|
||||
hValidMaterials.Purge();
|
||||
}
|
||||
}
|
||||
|
||||
*szMat = new char*[ numMaterials ];
|
||||
|
||||
int iTotalLength = 0;
|
||||
for ( int i = 0; i < numMaterials; i++ )
|
||||
iTotalLength += Q_strlen( MatList[i]->GetName() ) + 1;
|
||||
|
||||
**szMat = new char[ iTotalLength ];
|
||||
|
||||
int curpos = 0;
|
||||
for ( int i = 0; i < numMaterials; i++ )
|
||||
{
|
||||
const char *pszName = MatList[i]->GetName();
|
||||
|
||||
int curLength = Q_strlen( pszName ) + 1;
|
||||
(*szMat)[ i ] = **szMat + curpos;
|
||||
Q_strcpy( (*szMat)[ i ], pszName );
|
||||
curpos += curLength;
|
||||
}
|
||||
|
||||
if ( MatList )
|
||||
delete [] MatList;
|
||||
|
||||
return numMaterials;
|
||||
}
|
||||
48
sp/src/game/client/ShaderEditor/SEdit_ModelRender.h
Normal file
48
sp/src/game/client/ShaderEditor/SEdit_ModelRender.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef SHEDITMRENDER_H
|
||||
#define SHEDITMRENDER_H
|
||||
|
||||
#include "cbase.h"
|
||||
#include "ShaderEditor/ISEdit_ModelRender.h"
|
||||
|
||||
class C_BaseFlex_OverrideLod;
|
||||
|
||||
class SEditModelRender : public ISEditModelRender, public CAutoGameSystemPerFrame
|
||||
{
|
||||
public:
|
||||
SEditModelRender( char const *name );
|
||||
~SEditModelRender();
|
||||
|
||||
// autogamesystem
|
||||
virtual bool Init();
|
||||
virtual void Shutdown();
|
||||
virtual void Update( float frametime );
|
||||
|
||||
virtual void LevelInitPostEntity();
|
||||
virtual void LevelShutdownPostEntity();
|
||||
|
||||
// interface
|
||||
virtual bool LoadModel( const char *localPath );
|
||||
virtual void DestroyModel();
|
||||
virtual void GetModelCenter( float *pFl3_ViewOffset );
|
||||
|
||||
virtual int QuerySequences( char ***list );
|
||||
virtual void SetSequence( const char *name );
|
||||
|
||||
virtual void ExecRender();
|
||||
virtual void DoPostProc( int x, int y, int w, int h );
|
||||
|
||||
virtual int MaterialPicker( char ***szMat );
|
||||
|
||||
virtual void DestroyCharPtrList( char ***szList );
|
||||
|
||||
private:
|
||||
|
||||
bool IsModelReady();
|
||||
void ResetModel();
|
||||
|
||||
C_BaseFlex *pModelInstance;
|
||||
char m_szModelPath[MAX_PATH];
|
||||
int m_iNumPoseParams;
|
||||
};
|
||||
|
||||
#endif
|
||||
1625
sp/src/game/client/ShaderEditor/ShaderEditorSystem.cpp
Normal file
1625
sp/src/game/client/ShaderEditor/ShaderEditorSystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
59
sp/src/game/client/ShaderEditor/ShaderEditorSystem.h
Normal file
59
sp/src/game/client/ShaderEditor/ShaderEditorSystem.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef SHEDITSYSTEM_H
|
||||
#define SHEDITSYSTEM_H
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#include "datacache/imdlcache.h"
|
||||
|
||||
#include "iviewrender.h"
|
||||
#include "view_shared.h"
|
||||
#include "viewrender.h"
|
||||
|
||||
|
||||
class ShaderEditorHandler : public CAutoGameSystemPerFrame
|
||||
{
|
||||
public:
|
||||
ShaderEditorHandler( char const *name );
|
||||
~ShaderEditorHandler();
|
||||
|
||||
virtual bool Init();
|
||||
virtual void Shutdown();
|
||||
|
||||
virtual void Update( float frametime );
|
||||
virtual void PreRender();
|
||||
virtual void PostRender();
|
||||
|
||||
#ifdef SOURCE_2006
|
||||
void CustomViewRender( int *viewId, const VisibleFogVolumeInfo_t &fogVolumeInfo );
|
||||
#else
|
||||
void CustomViewRender( int *viewId, const VisibleFogVolumeInfo_t &fogVolumeInfo, const WaterRenderInfo_t &waterRenderInfo );
|
||||
#endif
|
||||
void CustomPostRender();
|
||||
void UpdateSkymask(bool bCombineMode, int x, int y, int w, int h);
|
||||
|
||||
const bool IsReady();
|
||||
int &GetViewIdForModify();
|
||||
const VisibleFogVolumeInfo_t &GetFogVolumeInfo();
|
||||
#ifndef SOURCE_2006
|
||||
const WaterRenderInfo_t &GetWaterRenderInfo();
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool m_bReady;
|
||||
|
||||
void RegisterCallbacks();
|
||||
void PrepareCallbackData();
|
||||
|
||||
void RegisterViewRenderCallbacks();
|
||||
|
||||
int *m_piCurrentViewId;
|
||||
VisibleFogVolumeInfo_t m_tFogVolumeInfo;
|
||||
#ifndef SOURCE_2006
|
||||
WaterRenderInfo_t m_tWaterRenderInfo;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern ShaderEditorHandler *g_ShaderEditorSystem;
|
||||
|
||||
|
||||
#endif
|
||||
251
sp/src/game/client/episodic/c_npc_advisor.cpp
Normal file
251
sp/src/game/client/episodic/c_npc_advisor.cpp
Normal file
@@ -0,0 +1,251 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Definition for client-side advisor.
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
|
||||
|
||||
#include "cbase.h"
|
||||
// this file contains the definitions for the message ID constants (eg ADVISOR_MSG_START_BEAM etc)
|
||||
#include "npc_advisor_shared.h"
|
||||
|
||||
#if NPC_ADVISOR_HAS_BEHAVIOR
|
||||
|
||||
#include "particles_simple.h"
|
||||
#include "citadel_effects_shared.h"
|
||||
#include "particles_attractor.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
|
||||
#include "c_ai_basenpc.h"
|
||||
#include "dlight.h"
|
||||
#include "iefx.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: unpack a networked entity index into a basehandle.
|
||||
//-----------------------------------------------------------------------------
|
||||
inline C_BaseEntity *IndexToEntity( int eindex )
|
||||
{
|
||||
return ClientEntityList().GetBaseEntityFromHandle(ClientEntityList().EntIndexToHandle(eindex));
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ADVISOR_ELIGHT_CVARS 1 // enable/disable tuning advisor elight with console variables
|
||||
|
||||
#if ADVISOR_ELIGHT_CVARS
|
||||
ConVar advisor_elight_e("advisor_elight_e","3");
|
||||
ConVar advisor_elight_rfeet("advisor_elight_rfeet","52");
|
||||
#endif
|
||||
|
||||
|
||||
/*! Client-side reflection of the advisor class.
|
||||
*/
|
||||
class C_NPC_Advisor : public C_AI_BaseNPC
|
||||
{
|
||||
DECLARE_CLASS( C_NPC_Advisor, C_AI_BaseNPC );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
public:
|
||||
// Server to client message received
|
||||
virtual void ReceiveMessage( int classID, bf_read &msg );
|
||||
virtual void ClientThink( void );
|
||||
|
||||
private:
|
||||
/*
|
||||
// broken into its own function so I can move it if necesasry
|
||||
void Initialize();
|
||||
*/
|
||||
|
||||
// start/stop beam particle effect from me to a pelting object
|
||||
void StartBeamFX( C_BaseEntity *pOnEntity );
|
||||
void StopBeamFX( C_BaseEntity *pOnEntity );
|
||||
|
||||
void StartElight();
|
||||
void StopElight();
|
||||
|
||||
int m_ElightKey; // test using an elight to make the escape sequence more visible. 0 is invalid.
|
||||
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_NPC_Advisor, DT_NPC_Advisor, CNPC_Advisor )
|
||||
|
||||
END_RECV_TABLE()
|
||||
|
||||
// Server to client message received
|
||||
void C_NPC_Advisor::ReceiveMessage( int classID, bf_read &msg )
|
||||
{
|
||||
if ( classID != GetClientClass()->m_ClassID )
|
||||
{
|
||||
// message is for subclass
|
||||
BaseClass::ReceiveMessage( classID, msg );
|
||||
return;
|
||||
}
|
||||
|
||||
int messageType = msg.ReadByte();
|
||||
switch( messageType )
|
||||
{
|
||||
case ADVISOR_MSG_START_BEAM:
|
||||
{
|
||||
int eindex = msg.ReadLong();
|
||||
StartBeamFX(IndexToEntity(eindex));
|
||||
}
|
||||
break;
|
||||
|
||||
case ADVISOR_MSG_STOP_BEAM:
|
||||
{
|
||||
int eindex = msg.ReadLong();
|
||||
StopBeamFX(IndexToEntity(eindex));
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case ADVISOR_MSG_STOP_ALL_BEAMS:
|
||||
{
|
||||
ParticleProp()->StopEmission();
|
||||
}
|
||||
break;
|
||||
case ADVISOR_MSG_START_ELIGHT:
|
||||
{
|
||||
StartElight();
|
||||
}
|
||||
break;
|
||||
case ADVISOR_MSG_STOP_ELIGHT:
|
||||
{
|
||||
StopElight();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertMsg1( false, "Received unknown message %d", messageType);
|
||||
}
|
||||
}
|
||||
|
||||
/// only use of the clientthink on the advisor is to update the elight
|
||||
void C_NPC_Advisor::ClientThink( void )
|
||||
{
|
||||
// if the elight has gone away, bail out
|
||||
if (m_ElightKey == 0)
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||
return;
|
||||
}
|
||||
|
||||
// get the elight
|
||||
dlight_t * el = effects->GetElightByKey(m_ElightKey);
|
||||
if (!el)
|
||||
{
|
||||
// the elight has been invalidated. bail out.
|
||||
m_ElightKey = 0;
|
||||
|
||||
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
el->origin = WorldSpaceCenter();
|
||||
|
||||
#if ADVISOR_ELIGHT_CVARS
|
||||
el->color.exponent = advisor_elight_e.GetFloat();
|
||||
el->radius = advisor_elight_rfeet.GetFloat() * 12.0f;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Create a telekinetic beam effect from my head to an object
|
||||
// TODO: use a point attachment.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Advisor::StartBeamFX( C_BaseEntity *pOnEntity )
|
||||
{
|
||||
Assert(pOnEntity);
|
||||
if (!pOnEntity)
|
||||
return;
|
||||
|
||||
CNewParticleEffect *pEffect = ParticleProp()->Create( "Advisor_Psychic_Beam", PATTACH_ABSORIGIN_FOLLOW );
|
||||
|
||||
Assert(pEffect);
|
||||
if (!pEffect) return;
|
||||
|
||||
ParticleProp()->AddControlPoint( pEffect, 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// terminate a telekinetic beam effect from my head to an object
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Advisor::StopBeamFX( C_BaseEntity *pOnEntity )
|
||||
{
|
||||
Assert(pOnEntity);
|
||||
if (!pOnEntity)
|
||||
return;
|
||||
|
||||
ParticleProp()->StopParticlesInvolving( pOnEntity );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void C_NPC_Advisor::StartElight()
|
||||
{
|
||||
AssertMsg(m_ElightKey == 0 , "Advisor trying to create new elight on top of old one!");
|
||||
if ( m_ElightKey != 0 )
|
||||
{
|
||||
Warning("Advisor tried to start his elight when it was already one.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ElightKey = LIGHT_INDEX_TE_DYNAMIC + this->entindex();
|
||||
dlight_t * el = effects->CL_AllocElight( m_ElightKey );
|
||||
|
||||
if ( el )
|
||||
{
|
||||
// create an elight on top of me
|
||||
el->origin = this->WorldSpaceCenter();
|
||||
|
||||
el->color.r = 235;
|
||||
el->color.g = 255;
|
||||
el->color.b = 255;
|
||||
el->color.exponent = 3;
|
||||
|
||||
el->radius = 52*12;
|
||||
el->decay = 0.0f;
|
||||
el->die = gpGlobals->curtime + 2000.0f; // 1000 just means " a long time "
|
||||
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
else
|
||||
{ // null out the light value
|
||||
m_ElightKey = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_NPC_Advisor::StopElight()
|
||||
{
|
||||
AssertMsg( m_ElightKey != 0, "Advisor tried to stop elight when none existed!");
|
||||
dlight_t * el;
|
||||
// note: the following conditional sets el if not short-circuited
|
||||
if ( m_ElightKey == 0 || (el = effects->GetElightByKey(m_ElightKey)) == NULL )
|
||||
{
|
||||
Warning("Advisor tried to stop its elight when it had none.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// kill the elight by setting the die value to now
|
||||
el->die = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/******************************************************
|
||||
* Tenser, said the Tensor. *
|
||||
* Tenser, said the Tensor. *
|
||||
* Tension, apprehension and dissension have begun. *
|
||||
******************************************************/
|
||||
167
sp/src/game/client/episodic/c_npc_puppet.cpp
Normal file
167
sp/src/game/client/episodic/c_npc_puppet.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_ai_basenpc.h"
|
||||
#include "bone_setup.h"
|
||||
|
||||
// Must be the last file included
|
||||
#include "memdbgon.h"
|
||||
|
||||
|
||||
extern ConVar r_sequence_debug;
|
||||
|
||||
class C_NPC_Puppet : public C_AI_BaseNPC
|
||||
{
|
||||
DECLARE_CLASS( C_NPC_Puppet, C_AI_BaseNPC );
|
||||
public:
|
||||
|
||||
virtual void ClientThink( void );
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual void BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed );
|
||||
virtual void AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime );
|
||||
|
||||
EHANDLE m_hAnimationTarget;
|
||||
int m_nTargetAttachment;
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_NPC_Puppet, DT_NPC_Puppet, CNPC_Puppet )
|
||||
RecvPropEHandle( RECVINFO(m_hAnimationTarget) ),
|
||||
RecvPropInt( RECVINFO(m_nTargetAttachment) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Puppet::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: We need to slam our position!
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Puppet::BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed )
|
||||
{
|
||||
if ( m_hAnimationTarget && m_nTargetAttachment != -1 )
|
||||
{
|
||||
C_BaseAnimating *pTarget = m_hAnimationTarget->GetBaseAnimating();
|
||||
if ( pTarget )
|
||||
{
|
||||
matrix3x4_t matTarget;
|
||||
pTarget->GetAttachment( m_nTargetAttachment, matTarget );
|
||||
|
||||
MatrixCopy( matTarget, GetBoneForWrite( 0 ) );
|
||||
boneComputed.ClearAll(); // FIXME: Why is this calculated already?
|
||||
boneComputed.MarkBone( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
// Call the baseclass
|
||||
BaseClass::BuildTransformations( pStudioHdr, pos, q, cameraTransform, boneMask, boneComputed );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Puppet::ClientThink( void )
|
||||
{
|
||||
if ( m_hAnimationTarget == NULL )
|
||||
return;
|
||||
|
||||
C_BaseAnimating *pTarget = m_hAnimationTarget->GetBaseAnimating();
|
||||
if ( pTarget == NULL )
|
||||
return;
|
||||
|
||||
int nTargetSequence = pTarget->GetSequence();
|
||||
const char *pSequenceName = pTarget->GetSequenceName( nTargetSequence );
|
||||
|
||||
int nSequence = LookupSequence( pSequenceName );
|
||||
if ( nSequence >= 0 )
|
||||
{
|
||||
if ( nSequence != GetSequence() )
|
||||
{
|
||||
SetSequence( nSequence );
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
SetCycle( pTarget->GetCycle() );
|
||||
SetPlaybackRate( pTarget->GetPlaybackRate() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Puppet::AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime )
|
||||
{
|
||||
if ( m_hAnimationTarget == NULL )
|
||||
return;
|
||||
|
||||
C_BaseAnimatingOverlay *pTarget = dynamic_cast<C_BaseAnimatingOverlay *>( m_hAnimationTarget->GetBaseAnimating() );
|
||||
if ( pTarget == NULL )
|
||||
return;
|
||||
|
||||
// resort the layers
|
||||
int layer[MAX_OVERLAYS];
|
||||
int i;
|
||||
for (i = 0; i < MAX_OVERLAYS; i++)
|
||||
{
|
||||
layer[i] = MAX_OVERLAYS;
|
||||
}
|
||||
for (i = 0; i < pTarget->m_AnimOverlay.Count(); i++)
|
||||
{
|
||||
if (pTarget->m_AnimOverlay[i].m_nOrder < MAX_OVERLAYS)
|
||||
{
|
||||
layer[pTarget->m_AnimOverlay[i].m_nOrder] = i;
|
||||
}
|
||||
}
|
||||
|
||||
int j;
|
||||
for (j = 0; j < MAX_OVERLAYS; j++)
|
||||
{
|
||||
i = layer[ j ];
|
||||
if (i < pTarget->m_AnimOverlay.Count())
|
||||
{
|
||||
float fWeight = pTarget->m_AnimOverlay[i].m_flWeight;
|
||||
|
||||
if (fWeight > 0)
|
||||
{
|
||||
const char *pSequenceName = pTarget->GetSequenceName( pTarget->m_AnimOverlay[i].m_nSequence );
|
||||
|
||||
int nSequence = LookupSequence( pSequenceName );
|
||||
if ( nSequence >= 0 )
|
||||
{
|
||||
float fCycle = pTarget->m_AnimOverlay[ i ].m_flCycle;
|
||||
|
||||
fCycle = ClampCycle( fCycle, IsSequenceLooping( nSequence ) );
|
||||
|
||||
if (fWeight > 1)
|
||||
fWeight = 1;
|
||||
|
||||
boneSetup.AccumulatePose( pos, q, nSequence, fCycle, fWeight, currentTime, NULL );
|
||||
|
||||
#if _DEBUG
|
||||
if (Q_stristr( boneSetup.GetStudioHdr()->pszName(), r_sequence_debug.GetString()) != NULL)
|
||||
{
|
||||
DevMsgRT( "%6.2f : %30s : %5.3f : %4.2f : %1d\n", currentTime, boneSetup.GetStudioHdr()->pSeqdesc( nSequence ).pszLabel(), fCycle, fWeight, i );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
142
sp/src/game/client/episodic/c_prop_coreball.cpp
Normal file
142
sp/src/game/client/episodic/c_prop_coreball.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
class C_PropCoreBall : public C_BaseAnimating
|
||||
{
|
||||
DECLARE_CLASS( C_PropCoreBall, C_BaseAnimating );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
public:
|
||||
|
||||
C_PropCoreBall();
|
||||
|
||||
void ApplyBoneMatrixTransform( matrix3x4_t& transform );
|
||||
|
||||
float m_flScaleX;
|
||||
float m_flScaleY;
|
||||
float m_flScaleZ;
|
||||
|
||||
float m_flLerpTimeX;
|
||||
float m_flLerpTimeY;
|
||||
float m_flLerpTimeZ;
|
||||
|
||||
float m_flGoalTimeX;
|
||||
float m_flGoalTimeY;
|
||||
float m_flGoalTimeZ;
|
||||
|
||||
float m_flCurrentScale[3];
|
||||
bool m_bRunningScale[3];
|
||||
float m_flTargetScale[3];
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
void RecvProxy_ScaleX( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
C_PropCoreBall *pCoreData = (C_PropCoreBall *) pStruct;
|
||||
|
||||
pCoreData->m_flScaleX = pData->m_Value.m_Float;
|
||||
|
||||
if ( pCoreData->m_bRunningScale[0] == true )
|
||||
{
|
||||
pCoreData->m_flTargetScale[0] = pCoreData->m_flCurrentScale[0];
|
||||
}
|
||||
}
|
||||
|
||||
void RecvProxy_ScaleY( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
C_PropCoreBall *pCoreData = (C_PropCoreBall *) pStruct;
|
||||
|
||||
pCoreData->m_flScaleY = pData->m_Value.m_Float;
|
||||
|
||||
if ( pCoreData->m_bRunningScale[1] == true )
|
||||
{
|
||||
pCoreData->m_flTargetScale[1] = pCoreData->m_flCurrentScale[1];
|
||||
}
|
||||
}
|
||||
|
||||
void RecvProxy_ScaleZ( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
C_PropCoreBall *pCoreData = (C_PropCoreBall *) pStruct;
|
||||
|
||||
pCoreData->m_flScaleZ = pData->m_Value.m_Float;
|
||||
|
||||
if ( pCoreData->m_bRunningScale[2] == true )
|
||||
{
|
||||
pCoreData->m_flTargetScale[2] = pCoreData->m_flCurrentScale[2];
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_PropCoreBall, DT_PropCoreBall, CPropCoreBall )
|
||||
RecvPropFloat( RECVINFO( m_flScaleX ), 0, RecvProxy_ScaleX ),
|
||||
RecvPropFloat( RECVINFO( m_flScaleY ), 0, RecvProxy_ScaleY ),
|
||||
RecvPropFloat( RECVINFO( m_flScaleZ ), 0, RecvProxy_ScaleZ ),
|
||||
|
||||
RecvPropFloat( RECVINFO( m_flLerpTimeX ) ),
|
||||
RecvPropFloat( RECVINFO( m_flLerpTimeY ) ),
|
||||
RecvPropFloat( RECVINFO( m_flLerpTimeZ ) ),
|
||||
|
||||
RecvPropFloat( RECVINFO( m_flGoalTimeX ) ),
|
||||
RecvPropFloat( RECVINFO( m_flGoalTimeY ) ),
|
||||
RecvPropFloat( RECVINFO( m_flGoalTimeZ ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
BEGIN_DATADESC( C_PropCoreBall )
|
||||
DEFINE_AUTO_ARRAY( m_flTargetScale, FIELD_FLOAT ),
|
||||
DEFINE_AUTO_ARRAY( m_bRunningScale, FIELD_BOOLEAN ),
|
||||
END_DATADESC()
|
||||
|
||||
C_PropCoreBall::C_PropCoreBall( void )
|
||||
{
|
||||
m_flTargetScale[0] = 1.0f;
|
||||
m_flTargetScale[1] = 1.0f;
|
||||
m_flTargetScale[2] = 1.0f;
|
||||
|
||||
m_bRunningScale[0] = false;
|
||||
m_bRunningScale[1] = false;
|
||||
m_bRunningScale[2] = false;
|
||||
}
|
||||
|
||||
void C_PropCoreBall::ApplyBoneMatrixTransform( matrix3x4_t& transform )
|
||||
{
|
||||
BaseClass::ApplyBoneMatrixTransform( transform );
|
||||
|
||||
float flVal[3] = { m_flTargetScale[0], m_flTargetScale[1], m_flTargetScale[2] };
|
||||
float *flTargetScale[3] = { &m_flTargetScale[0], &m_flTargetScale[1], &m_flTargetScale[2] };
|
||||
float flScale[3] = { m_flScaleX, m_flScaleY, m_flScaleZ };
|
||||
float flLerpTime[3] = { m_flLerpTimeX, m_flLerpTimeY, m_flLerpTimeZ };
|
||||
float flGoalTime[3] = { m_flGoalTimeX, m_flGoalTimeY, m_flGoalTimeZ };
|
||||
bool *bRunning[3] = { &m_bRunningScale[0], &m_bRunningScale[1], &m_bRunningScale[2] };
|
||||
|
||||
for ( int i = 0; i < 3; i++ )
|
||||
{
|
||||
if ( *flTargetScale[i] != flScale[i] )
|
||||
{
|
||||
float deltaTime = (float)( gpGlobals->curtime - flGoalTime[i]) / flLerpTime[i];
|
||||
float flRemapVal = SimpleSplineRemapVal( deltaTime, 0.0f, 1.0f, *flTargetScale[i], flScale[i] );
|
||||
|
||||
*bRunning[i] = true;
|
||||
|
||||
if ( deltaTime >= 1.0f )
|
||||
{
|
||||
*flTargetScale[i] = flScale[i];
|
||||
*bRunning[i] = false;
|
||||
}
|
||||
|
||||
flVal[i] = flRemapVal;
|
||||
m_flCurrentScale[i] = flVal[i];
|
||||
}
|
||||
}
|
||||
|
||||
VectorScale( transform[0], flVal[0], transform[0] );
|
||||
VectorScale( transform[1], flVal[1], transform[1] );
|
||||
VectorScale( transform[2], flVal[2], transform[2] );
|
||||
}
|
||||
196
sp/src/game/client/episodic/c_prop_scalable.cpp
Normal file
196
sp/src/game/client/episodic/c_prop_scalable.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
class C_PropScalable : public C_BaseAnimating
|
||||
{
|
||||
DECLARE_CLASS( C_PropScalable, C_BaseAnimating );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
public:
|
||||
|
||||
C_PropScalable();
|
||||
|
||||
virtual void ApplyBoneMatrixTransform( matrix3x4_t& transform );
|
||||
virtual void GetRenderBounds( Vector &theMins, Vector &theMaxs );
|
||||
|
||||
// Must be available to proxy functions
|
||||
float m_flScaleX;
|
||||
float m_flScaleY;
|
||||
float m_flScaleZ;
|
||||
|
||||
float m_flLerpTimeX;
|
||||
float m_flLerpTimeY;
|
||||
float m_flLerpTimeZ;
|
||||
|
||||
float m_flGoalTimeX;
|
||||
float m_flGoalTimeY;
|
||||
float m_flGoalTimeZ;
|
||||
|
||||
float m_flCurrentScale[3];
|
||||
bool m_bRunningScale[3];
|
||||
float m_flTargetScale[3];
|
||||
|
||||
private:
|
||||
|
||||
void CalculateScale( void );
|
||||
float m_nCalcFrame; // Frame the last calculation was made at
|
||||
};
|
||||
|
||||
void RecvProxy_ScaleX( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
C_PropScalable *pCoreData = (C_PropScalable *) pStruct;
|
||||
|
||||
pCoreData->m_flScaleX = pData->m_Value.m_Float;
|
||||
|
||||
if ( pCoreData->m_bRunningScale[0] == true )
|
||||
{
|
||||
pCoreData->m_flTargetScale[0] = pCoreData->m_flCurrentScale[0];
|
||||
}
|
||||
}
|
||||
|
||||
void RecvProxy_ScaleY( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
C_PropScalable *pCoreData = (C_PropScalable *) pStruct;
|
||||
|
||||
pCoreData->m_flScaleY = pData->m_Value.m_Float;
|
||||
|
||||
if ( pCoreData->m_bRunningScale[1] == true )
|
||||
{
|
||||
pCoreData->m_flTargetScale[1] = pCoreData->m_flCurrentScale[1];
|
||||
}
|
||||
}
|
||||
|
||||
void RecvProxy_ScaleZ( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
C_PropScalable *pCoreData = (C_PropScalable *) pStruct;
|
||||
|
||||
pCoreData->m_flScaleZ = pData->m_Value.m_Float;
|
||||
|
||||
if ( pCoreData->m_bRunningScale[2] == true )
|
||||
{
|
||||
pCoreData->m_flTargetScale[2] = pCoreData->m_flCurrentScale[2];
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_PropScalable, DT_PropScalable, CPropScalable )
|
||||
RecvPropFloat( RECVINFO( m_flScaleX ), 0, RecvProxy_ScaleX ),
|
||||
RecvPropFloat( RECVINFO( m_flScaleY ), 0, RecvProxy_ScaleY ),
|
||||
RecvPropFloat( RECVINFO( m_flScaleZ ), 0, RecvProxy_ScaleZ ),
|
||||
|
||||
RecvPropFloat( RECVINFO( m_flLerpTimeX ) ),
|
||||
RecvPropFloat( RECVINFO( m_flLerpTimeY ) ),
|
||||
RecvPropFloat( RECVINFO( m_flLerpTimeZ ) ),
|
||||
|
||||
RecvPropFloat( RECVINFO( m_flGoalTimeX ) ),
|
||||
RecvPropFloat( RECVINFO( m_flGoalTimeY ) ),
|
||||
RecvPropFloat( RECVINFO( m_flGoalTimeZ ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
BEGIN_DATADESC( C_PropScalable )
|
||||
DEFINE_AUTO_ARRAY( m_flTargetScale, FIELD_FLOAT ),
|
||||
DEFINE_AUTO_ARRAY( m_bRunningScale, FIELD_BOOLEAN ),
|
||||
END_DATADESC()
|
||||
|
||||
C_PropScalable::C_PropScalable( void )
|
||||
{
|
||||
m_flTargetScale[0] = 1.0f;
|
||||
m_flTargetScale[1] = 1.0f;
|
||||
m_flTargetScale[2] = 1.0f;
|
||||
|
||||
m_bRunningScale[0] = false;
|
||||
m_bRunningScale[1] = false;
|
||||
m_bRunningScale[2] = false;
|
||||
|
||||
m_nCalcFrame = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Calculates the scake of the object once per frame
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropScalable::CalculateScale( void )
|
||||
{
|
||||
// Don't bother to calculate this for a second time in the same frame
|
||||
if ( m_nCalcFrame == gpGlobals->framecount )
|
||||
return;
|
||||
|
||||
// Mark that we cached this value for the frame
|
||||
m_nCalcFrame = gpGlobals->framecount;
|
||||
|
||||
float flVal[3] = { m_flTargetScale[0], m_flTargetScale[1], m_flTargetScale[2] };
|
||||
float *flTargetScale[3] = { &m_flTargetScale[0], &m_flTargetScale[1], &m_flTargetScale[2] };
|
||||
float flScale[3] = { m_flScaleX, m_flScaleY, m_flScaleZ };
|
||||
float flLerpTime[3] = { m_flLerpTimeX, m_flLerpTimeY, m_flLerpTimeZ };
|
||||
float flGoalTime[3] = { m_flGoalTimeX, m_flGoalTimeY, m_flGoalTimeZ };
|
||||
bool *bRunning[3] = { &m_bRunningScale[0], &m_bRunningScale[1], &m_bRunningScale[2] };
|
||||
|
||||
for ( int i = 0; i < 3; i++ )
|
||||
{
|
||||
if ( *flTargetScale[i] != flScale[i] )
|
||||
{
|
||||
float deltaTime = (float)( gpGlobals->curtime - flGoalTime[i]) / flLerpTime[i];
|
||||
float flRemapVal = SimpleSplineRemapValClamped( deltaTime, 0.0f, 1.0f, *flTargetScale[i], flScale[i] );
|
||||
|
||||
*bRunning[i] = true;
|
||||
|
||||
if ( deltaTime >= 1.0f )
|
||||
{
|
||||
*flTargetScale[i] = flScale[i];
|
||||
*bRunning[i] = false;
|
||||
}
|
||||
|
||||
flVal[i] = flRemapVal;
|
||||
m_flCurrentScale[i] = flVal[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flCurrentScale[i] = m_flTargetScale[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Scales the bones based on the current scales
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropScalable::ApplyBoneMatrixTransform( matrix3x4_t& transform )
|
||||
{
|
||||
BaseClass::ApplyBoneMatrixTransform( transform );
|
||||
|
||||
// Find the scale for this frame
|
||||
CalculateScale();
|
||||
|
||||
VectorScale( transform[0], m_flCurrentScale[0], transform[0] );
|
||||
VectorScale( transform[1], m_flCurrentScale[1], transform[1] );
|
||||
VectorScale( transform[2], m_flCurrentScale[2], transform[2] );
|
||||
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Ensures the render bounds match the scales
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropScalable::GetRenderBounds( Vector &theMins, Vector &theMaxs )
|
||||
{
|
||||
BaseClass::GetRenderBounds( theMins, theMaxs );
|
||||
|
||||
// Find the scale for this frame
|
||||
CalculateScale();
|
||||
|
||||
// Extend our render bounds to encompass the scaled object
|
||||
theMins.x *= m_flCurrentScale[0];
|
||||
theMins.y *= m_flCurrentScale[1];
|
||||
theMins.z *= m_flCurrentScale[2];
|
||||
|
||||
theMaxs.x *= m_flCurrentScale[0];
|
||||
theMaxs.y *= m_flCurrentScale[1];
|
||||
theMaxs.z *= m_flCurrentScale[2];
|
||||
|
||||
Assert( theMins.IsValid() && theMaxs.IsValid() );
|
||||
|
||||
}
|
||||
133
sp/src/game/client/episodic/c_vehicle_jeep_episodic.cpp
Normal file
133
sp/src/game/client/episodic/c_vehicle_jeep_episodic.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_prop_vehicle.h"
|
||||
#include "c_vehicle_jeep.h"
|
||||
#include "movevars_shared.h"
|
||||
#include "view.h"
|
||||
#include "flashlighteffect.h"
|
||||
#include "c_baseplayer.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#include "hl2_vehicle_radar.h"
|
||||
#include "usermessages.h"
|
||||
#include "hud_radar.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Client-side Episodic Jeep (Jalopy) Class
|
||||
//
|
||||
class C_PropJeepEpisodic : public C_PropJeep
|
||||
{
|
||||
|
||||
DECLARE_CLASS( C_PropJeepEpisodic, C_PropJeep );
|
||||
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
public:
|
||||
C_PropJeepEpisodic();
|
||||
|
||||
void OnEnteredVehicle( C_BasePlayer *pPlayer );
|
||||
void Simulate( void );
|
||||
|
||||
public:
|
||||
int m_iNumRadarContacts;
|
||||
Vector m_vecRadarContactPos[ RADAR_MAX_CONTACTS ];
|
||||
int m_iRadarContactType[ RADAR_MAX_CONTACTS ];
|
||||
};
|
||||
C_PropJeepEpisodic *g_pJalopy = NULL;
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_PropJeepEpisodic, DT_CPropJeepEpisodic, CPropJeepEpisodic )
|
||||
//CNetworkVar( int, m_iNumRadarContacts );
|
||||
RecvPropInt( RECVINFO(m_iNumRadarContacts) ),
|
||||
|
||||
//CNetworkArray( Vector, m_vecRadarContactPos, RADAR_MAX_CONTACTS );
|
||||
RecvPropArray( RecvPropVector(RECVINFO(m_vecRadarContactPos[0])), m_vecRadarContactPos ),
|
||||
|
||||
//CNetworkArray( int, m_iRadarContactType, RADAR_MAX_CONTACTS );
|
||||
RecvPropArray( RecvPropInt( RECVINFO(m_iRadarContactType[0] ) ), m_iRadarContactType ),
|
||||
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void __MsgFunc_UpdateJalopyRadar(bf_read &msg)
|
||||
{
|
||||
// Radar code here!
|
||||
if( !GetHudRadar() )
|
||||
return;
|
||||
|
||||
// Sometimes we update more quickly when we need to track something in high resolution.
|
||||
// Usually we do not, so default to false.
|
||||
GetHudRadar()->m_bUseFastUpdate = false;
|
||||
|
||||
for( int i = 0 ; i < g_pJalopy->m_iNumRadarContacts ; i++ )
|
||||
{
|
||||
if( g_pJalopy->m_iRadarContactType[i] == RADAR_CONTACT_DOG )
|
||||
{
|
||||
GetHudRadar()->m_bUseFastUpdate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float flContactTimeToLive;
|
||||
|
||||
if( GetHudRadar()->m_bUseFastUpdate )
|
||||
{
|
||||
flContactTimeToLive = RADAR_UPDATE_FREQUENCY_FAST;
|
||||
}
|
||||
else
|
||||
{
|
||||
flContactTimeToLive = RADAR_UPDATE_FREQUENCY;
|
||||
}
|
||||
|
||||
for( int i = 0 ; i < g_pJalopy->m_iNumRadarContacts ; i++ )
|
||||
{
|
||||
GetHudRadar()->AddRadarContact( g_pJalopy->m_vecRadarContactPos[i], g_pJalopy->m_iRadarContactType[i], flContactTimeToLive );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
C_PropJeepEpisodic::C_PropJeepEpisodic()
|
||||
{
|
||||
if( g_pJalopy == NULL )
|
||||
{
|
||||
usermessages->HookMessage( "UpdateJalopyRadar", __MsgFunc_UpdateJalopyRadar );
|
||||
}
|
||||
|
||||
g_pJalopy = this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropJeepEpisodic::Simulate( void )
|
||||
{
|
||||
// Keep trying to hook to the radar.
|
||||
if( GetHudRadar() != NULL )
|
||||
{
|
||||
// This is not our ideal long-term solution. This will only work if you only have
|
||||
// one jalopy in a given level. The Jalopy and the Radar Screen are currently both
|
||||
// assumed to be singletons. This is appropriate for EP2, however. (sjb)
|
||||
GetHudRadar()->SetVehicle( this );
|
||||
}
|
||||
|
||||
BaseClass::Simulate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropJeepEpisodic::OnEnteredVehicle( C_BasePlayer *pPlayer )
|
||||
{
|
||||
BaseClass::OnEnteredVehicle( pPlayer );
|
||||
}
|
||||
600
sp/src/game/client/episodic/c_vort_charge_token.cpp
Normal file
600
sp/src/game/client/episodic/c_vort_charge_token.cpp
Normal file
@@ -0,0 +1,600 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "particles_simple.h"
|
||||
#include "citadel_effects_shared.h"
|
||||
#include "particles_attractor.h"
|
||||
#include "iefx.h"
|
||||
#include "dlight.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#include "fx_quad.h"
|
||||
|
||||
#include "c_ai_basenpc.h"
|
||||
|
||||
// For material proxy
|
||||
#include "proxyentity.h"
|
||||
#include "materialsystem/imaterial.h"
|
||||
#include "materialsystem/imaterialvar.h"
|
||||
|
||||
#define NUM_INTERIOR_PARTICLES 8
|
||||
|
||||
#define DLIGHT_RADIUS (150.0f)
|
||||
#define DLIGHT_MINLIGHT (40.0f/255.0f)
|
||||
|
||||
class C_NPC_Vortigaunt : public C_AI_BaseNPC
|
||||
{
|
||||
DECLARE_CLASS( C_NPC_Vortigaunt, C_AI_BaseNPC );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
public:
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual void ClientThink( void );
|
||||
virtual void ReceiveMessage( int classID, bf_read &msg );
|
||||
|
||||
public:
|
||||
bool m_bIsBlue; ///< wants to fade to blue
|
||||
float m_flBlueEndFadeTime; ///< when to end fading from one skin to another
|
||||
|
||||
bool m_bIsBlack; ///< wants to fade to black (networked)
|
||||
float m_flBlackFade; ///< [0.00 .. 1.00] where 1.00 is all black. Locally interpolated.
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_NPC_Vortigaunt, DT_NPC_Vortigaunt, CNPC_Vortigaunt )
|
||||
RecvPropTime( RECVINFO(m_flBlueEndFadeTime ) ),
|
||||
RecvPropBool( RECVINFO(m_bIsBlue) ),
|
||||
RecvPropBool( RECVINFO(m_bIsBlack) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
#define VORTIGAUNT_BLUE_FADE_TIME 2.25f // takes this long to fade from green to blue or back
|
||||
#define VORT_BLACK_FADE_TIME 2.2f // time to interpolate up or down in fading to black
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Vortigaunt::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
// start thinking if we need to fade.
|
||||
if ( m_flBlackFade != (m_bIsBlack ? 1.0f : 0.0f) )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Vortigaunt::ClientThink( void )
|
||||
{
|
||||
// Don't update if our frame hasn't moved forward (paused)
|
||||
if ( gpGlobals->frametime <= 0.0f )
|
||||
return;
|
||||
|
||||
if ( m_bIsBlack )
|
||||
{
|
||||
// are we done?
|
||||
if ( m_flBlackFade >= 1.0f )
|
||||
{
|
||||
m_flBlackFade = 1.0f;
|
||||
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||
}
|
||||
else // interpolate there
|
||||
{
|
||||
float lerpQuant = gpGlobals->frametime / VORT_BLACK_FADE_TIME;
|
||||
m_flBlackFade += lerpQuant;
|
||||
if ( m_flBlackFade > 1.0f )
|
||||
{
|
||||
m_flBlackFade = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// are we done?
|
||||
if ( m_flBlackFade <= 0.0f )
|
||||
{
|
||||
m_flBlackFade = 0.0f;
|
||||
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||
}
|
||||
else // interpolate there
|
||||
{
|
||||
float lerpQuant = gpGlobals->frametime / VORT_BLACK_FADE_TIME;
|
||||
m_flBlackFade -= lerpQuant;
|
||||
if ( m_flBlackFade < 0.0f )
|
||||
{
|
||||
m_flBlackFade = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Move to shared code!
|
||||
#define VORTFX_ZAPBEAM 0
|
||||
#define VORTFX_ARMBEAM 1
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Receive messages from the server
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Vortigaunt::ReceiveMessage( int classID, bf_read &msg )
|
||||
{
|
||||
// Is the message for a sub-class?
|
||||
if ( classID != GetClientClass()->m_ClassID )
|
||||
{
|
||||
BaseClass::ReceiveMessage( classID, msg );
|
||||
return;
|
||||
}
|
||||
|
||||
int messageType = msg.ReadByte();
|
||||
switch( messageType )
|
||||
{
|
||||
case VORTFX_ZAPBEAM:
|
||||
{
|
||||
// Find our attachment point
|
||||
unsigned char nAttachment = msg.ReadByte();
|
||||
|
||||
// Get our attachment position
|
||||
Vector vecStart;
|
||||
QAngle vecAngles;
|
||||
GetAttachment( nAttachment, vecStart, vecAngles );
|
||||
|
||||
// Get the final position we'll strike
|
||||
Vector vecEndPos;
|
||||
msg.ReadBitVec3Coord( vecEndPos );
|
||||
|
||||
// Place a beam between the two points
|
||||
CNewParticleEffect *pEffect = ParticleProp()->Create( "vortigaunt_beam", PATTACH_POINT_FOLLOW, nAttachment );
|
||||
if ( pEffect )
|
||||
{
|
||||
pEffect->SetControlPoint( 0, vecStart );
|
||||
pEffect->SetControlPoint( 1, vecEndPos );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VORTFX_ARMBEAM:
|
||||
{
|
||||
int nIndex = msg.ReadLong();
|
||||
C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( ClientEntityList().EntIndexToHandle( nIndex ) );
|
||||
|
||||
if ( pEnt )
|
||||
{
|
||||
unsigned char nAttachment = msg.ReadByte();
|
||||
Vector vecEndPos;
|
||||
msg.ReadBitVec3Coord( vecEndPos );
|
||||
|
||||
Vector vecNormal;
|
||||
msg.ReadBitVec3Normal( vecNormal );
|
||||
|
||||
CNewParticleEffect *pEffect = pEnt->ParticleProp()->Create( "vortigaunt_beam_charge", PATTACH_POINT_FOLLOW, nAttachment );
|
||||
if ( pEffect )
|
||||
{
|
||||
// Set the control point's angles to be the surface normal we struct
|
||||
Vector vecRight, vecUp;
|
||||
VectorVectors( vecNormal, vecRight, vecUp );
|
||||
pEffect->SetControlPointOrientation( 1, vecNormal, vecRight, vecUp );
|
||||
pEffect->SetControlPoint( 1, vecEndPos );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertMsg1( false, "Received unknown message %d", messageType);
|
||||
}
|
||||
}
|
||||
|
||||
class C_VortigauntChargeToken : public C_BaseEntity
|
||||
{
|
||||
DECLARE_CLASS( C_VortigauntChargeToken, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
public:
|
||||
virtual void UpdateOnRemove( void );
|
||||
virtual void ClientThink( void );
|
||||
virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
|
||||
virtual void OnDataChanged( DataUpdateType_t type );
|
||||
|
||||
// For RecvProxy handlers
|
||||
float m_flFadeOutTime;
|
||||
float m_flFadeOutStart;
|
||||
|
||||
private:
|
||||
bool SetupEmitters( void );
|
||||
|
||||
bool m_bFadeOut;
|
||||
CNewParticleEffect *m_hEffect;
|
||||
dlight_t *m_pDLight;
|
||||
};
|
||||
|
||||
void RecvProxy_FadeOutDuration( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
C_VortigauntChargeToken *pVortToken = (C_VortigauntChargeToken *) pStruct;
|
||||
Assert( pOut == &pVortToken->m_flFadeOutTime );
|
||||
|
||||
pVortToken->m_flFadeOutStart = gpGlobals->curtime;
|
||||
pVortToken->m_flFadeOutTime = ( pData->m_Value.m_Float - gpGlobals->curtime );
|
||||
}
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_VortigauntChargeToken, DT_VortigauntChargeToken, CVortigauntChargeToken )
|
||||
RecvPropBool( RECVINFO( m_bFadeOut ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
void C_VortigauntChargeToken::UpdateOnRemove( void )
|
||||
{
|
||||
if ( m_hEffect )
|
||||
{
|
||||
m_hEffect->StopEmission();
|
||||
m_hEffect = NULL;
|
||||
}
|
||||
|
||||
if ( m_pDLight != NULL )
|
||||
{
|
||||
m_pDLight->die = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Change our transmission state
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_VortigauntChargeToken::NotifyShouldTransmit( ShouldTransmitState_t state )
|
||||
{
|
||||
BaseClass::NotifyShouldTransmit( state );
|
||||
|
||||
// Turn off
|
||||
if ( state == SHOULDTRANSMIT_END )
|
||||
{
|
||||
if ( m_hEffect )
|
||||
{
|
||||
m_hEffect->StopEmission();
|
||||
m_hEffect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Turn on
|
||||
if ( state == SHOULDTRANSMIT_START )
|
||||
{
|
||||
m_hEffect = ParticleProp()->Create( "vortigaunt_charge_token", PATTACH_ABSORIGIN_FOLLOW );
|
||||
m_hEffect->SetControlPointEntity( 0, this );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_VortigauntChargeToken::OnDataChanged( DataUpdateType_t type )
|
||||
{
|
||||
if ( m_bFadeOut )
|
||||
{
|
||||
if ( m_hEffect )
|
||||
{
|
||||
m_hEffect->StopEmission();
|
||||
m_hEffect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::OnDataChanged( type );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_VortigauntChargeToken::ClientThink( void )
|
||||
{
|
||||
//
|
||||
// -- DLight
|
||||
//
|
||||
|
||||
if ( m_pDLight != NULL )
|
||||
{
|
||||
m_pDLight->origin = GetAbsOrigin();
|
||||
m_pDLight->radius = DLIGHT_RADIUS;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Dispel Effect
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class C_VortigauntEffectDispel : public C_BaseEntity
|
||||
{
|
||||
DECLARE_CLASS( C_VortigauntEffectDispel, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
public:
|
||||
virtual void UpdateOnRemove( void );
|
||||
virtual void ClientThink( void );
|
||||
virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
|
||||
virtual void OnDataChanged( DataUpdateType_t type );
|
||||
|
||||
// For RecvProxy handlers
|
||||
float m_flFadeOutTime;
|
||||
float m_flFadeOutStart;
|
||||
|
||||
private:
|
||||
bool SetupEmitters( void );
|
||||
|
||||
CNewParticleEffect *m_hEffect;
|
||||
bool m_bFadeOut;
|
||||
dlight_t *m_pDLight;
|
||||
};
|
||||
|
||||
void RecvProxy_DispelFadeOutDuration( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
C_VortigauntEffectDispel *pVortToken = (C_VortigauntEffectDispel *) pStruct;
|
||||
Assert( pOut == &pVortToken->m_flFadeOutTime );
|
||||
|
||||
pVortToken->m_flFadeOutStart = gpGlobals->curtime;
|
||||
pVortToken->m_flFadeOutTime = ( pData->m_Value.m_Float - gpGlobals->curtime );
|
||||
}
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_VortigauntEffectDispel, DT_VortigauntEffectDispel, CVortigauntEffectDispel )
|
||||
RecvPropBool( RECVINFO( m_bFadeOut ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
void C_VortigauntEffectDispel::UpdateOnRemove( void )
|
||||
{
|
||||
if ( m_hEffect )
|
||||
{
|
||||
m_hEffect->StopEmission();
|
||||
m_hEffect = NULL;
|
||||
}
|
||||
|
||||
if ( m_pDLight != NULL )
|
||||
{
|
||||
m_pDLight->die = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_VortigauntEffectDispel::OnDataChanged( DataUpdateType_t type )
|
||||
{
|
||||
if ( m_bFadeOut )
|
||||
{
|
||||
if ( m_hEffect )
|
||||
{
|
||||
m_hEffect->StopEmission();
|
||||
m_hEffect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::OnDataChanged( type );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_VortigauntEffectDispel::NotifyShouldTransmit( ShouldTransmitState_t state )
|
||||
{
|
||||
BaseClass::NotifyShouldTransmit( state );
|
||||
|
||||
// Turn off
|
||||
if ( state == SHOULDTRANSMIT_END )
|
||||
{
|
||||
if ( m_hEffect )
|
||||
{
|
||||
m_hEffect->StopEmission();
|
||||
m_hEffect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Turn on
|
||||
if ( state == SHOULDTRANSMIT_START )
|
||||
{
|
||||
m_hEffect = ParticleProp()->Create( "vortigaunt_hand_glow", PATTACH_ABSORIGIN_FOLLOW );
|
||||
m_hEffect->SetControlPointEntity( 0, this );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Create our emitter
|
||||
//-----------------------------------------------------------------------------
|
||||
bool C_VortigauntEffectDispel::SetupEmitters( void )
|
||||
{
|
||||
m_pDLight = NULL;
|
||||
|
||||
#ifndef _X360
|
||||
m_pDLight = effects->CL_AllocDlight ( index );
|
||||
m_pDLight->origin = GetAbsOrigin();
|
||||
m_pDLight->color.r = 64;
|
||||
m_pDLight->color.g = 255;
|
||||
m_pDLight->color.b = 64;
|
||||
m_pDLight->radius = 0;
|
||||
m_pDLight->minlight = DLIGHT_MINLIGHT;
|
||||
m_pDLight->die = FLT_MAX;
|
||||
#endif // _X360
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_VortigauntEffectDispel::ClientThink( void )
|
||||
{
|
||||
if ( m_pDLight != NULL )
|
||||
{
|
||||
m_pDLight->origin = GetAbsOrigin();
|
||||
m_pDLight->radius = DLIGHT_RADIUS;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void DispelCallback( const CEffectData &data )
|
||||
{
|
||||
// Kaboom!
|
||||
Vector startPos = data.m_vOrigin + Vector(0,0,16);
|
||||
Vector endPos = data.m_vOrigin + Vector(0,0,-64);
|
||||
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( startPos, endPos, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction < 1.0f )
|
||||
{
|
||||
//Add a ripple quad to the surface
|
||||
FX_AddQuad( tr.endpos + ( tr.plane.normal * 8.0f ),
|
||||
Vector( 0, 0, 1 ),
|
||||
64.0f,
|
||||
600.0f,
|
||||
0.8f,
|
||||
1.0f, // start alpha
|
||||
0.0f, // end alpha
|
||||
0.3f,
|
||||
random->RandomFloat( 0, 360 ),
|
||||
0.0f,
|
||||
Vector( 0.5f, 1.0f, 0.5f ),
|
||||
0.75f,
|
||||
"effects/ar2_altfire1b",
|
||||
(FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA|FXQUAD_COLOR_FADE) );
|
||||
|
||||
//Add a ripple quad to the surface
|
||||
FX_AddQuad( tr.endpos + ( tr.plane.normal * 8.0f ),
|
||||
Vector( 0, 0, 1 ),
|
||||
16.0f,
|
||||
300.0f,
|
||||
0.9f,
|
||||
1.0f, // start alpha
|
||||
0.0f, // end alpha
|
||||
0.9f,
|
||||
random->RandomFloat( 0, 360 ),
|
||||
0.0f,
|
||||
Vector( 0.5f, 1.0f, 0.5f ),
|
||||
1.25f,
|
||||
"effects/rollerglow",
|
||||
(FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) );
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "VortDispel", DispelCallback );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Used for emissive lightning layer on vort
|
||||
//-----------------------------------------------------------------------------
|
||||
class CVortEmissiveProxy : public CEntityMaterialProxy
|
||||
{
|
||||
public:
|
||||
CVortEmissiveProxy( void );
|
||||
virtual ~CVortEmissiveProxy( void );
|
||||
virtual bool Init( IMaterial *pMaterial, KeyValues* pKeyValues );
|
||||
virtual void OnBind( C_BaseEntity *pC_BaseEntity );
|
||||
virtual IMaterial * GetMaterial();
|
||||
|
||||
private:
|
||||
|
||||
IMaterialVar *m_pMatEmissiveStrength;
|
||||
IMaterialVar *m_pMatDetailBlendStrength;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CVortEmissiveProxy::CVortEmissiveProxy( void )
|
||||
{
|
||||
m_pMatEmissiveStrength = NULL;
|
||||
m_pMatDetailBlendStrength = NULL;
|
||||
}
|
||||
|
||||
CVortEmissiveProxy::~CVortEmissiveProxy( void )
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CVortEmissiveProxy::Init( IMaterial *pMaterial, KeyValues* pKeyValues )
|
||||
{
|
||||
Assert( pMaterial );
|
||||
|
||||
// Need to get the material var
|
||||
bool bFound;
|
||||
m_pMatEmissiveStrength = pMaterial->FindVar( "$emissiveblendstrength", &bFound );
|
||||
|
||||
if ( bFound )
|
||||
{
|
||||
// Optional
|
||||
bool bFound2;
|
||||
m_pMatDetailBlendStrength = pMaterial->FindVar( "$detailblendfactor", &bFound2 );
|
||||
}
|
||||
|
||||
return bFound;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CVortEmissiveProxy::OnBind( C_BaseEntity *pEnt )
|
||||
{
|
||||
C_NPC_Vortigaunt *pVort = dynamic_cast<C_NPC_Vortigaunt *>(pEnt);
|
||||
|
||||
float flBlendValue;
|
||||
|
||||
if (pVort)
|
||||
{
|
||||
// do we need to crossfade?
|
||||
if (gpGlobals->curtime < pVort->m_flBlueEndFadeTime)
|
||||
{
|
||||
// will be 0 when fully faded and 1 when not faded at all:
|
||||
float fadeRatio = (pVort->m_flBlueEndFadeTime - gpGlobals->curtime) / VORTIGAUNT_BLUE_FADE_TIME;
|
||||
if (pVort->m_bIsBlue)
|
||||
{
|
||||
fadeRatio = 1.0f - fadeRatio;
|
||||
}
|
||||
flBlendValue = clamp( fadeRatio, 0.0f, 1.0f );
|
||||
}
|
||||
else // no crossfade
|
||||
{
|
||||
flBlendValue = pVort->m_bIsBlue ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
// ALEX VLACHOS:
|
||||
// The following variable varies on [0 .. 1]. 0.0 means the vort wants to be his normal
|
||||
// color. 1.0 means he wants to be all black. It is interpolated in the
|
||||
// C_NPC_Vortigaunt::ClientThink() function.
|
||||
//
|
||||
// pVort->m_flBlackFade
|
||||
}
|
||||
else
|
||||
{ // if you bind this proxy to anything non-vort (eg a ragdoll) it's always green
|
||||
flBlendValue = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// !!! Change me !!! I'm using a clamped sin wave for debugging
|
||||
float flBlendValue = sinf( gpGlobals->curtime * 4.0f ) * 0.75f + 0.25f;
|
||||
|
||||
// Clamp 0-1
|
||||
flBlendValue = ( flBlendValue < 0.0f ) ? 0.0f : ( flBlendValue > 1.0f ) ? 1.0f : flBlendValue;
|
||||
*/
|
||||
|
||||
if( m_pMatEmissiveStrength != NULL )
|
||||
{
|
||||
m_pMatEmissiveStrength->SetFloatValue( flBlendValue );
|
||||
}
|
||||
|
||||
if( m_pMatDetailBlendStrength != NULL )
|
||||
{
|
||||
m_pMatDetailBlendStrength->SetFloatValue( flBlendValue );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
IMaterial *CVortEmissiveProxy::GetMaterial()
|
||||
{
|
||||
if ( m_pMatEmissiveStrength != NULL )
|
||||
return m_pMatEmissiveStrength->GetOwningMaterial();
|
||||
else if ( m_pMatDetailBlendStrength != NULL )
|
||||
return m_pMatDetailBlendStrength->GetOwningMaterial();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EXPOSE_INTERFACE( CVortEmissiveProxy, IMaterialProxy, "VortEmissive" IMATERIAL_PROXY_INTERFACE_VERSION );
|
||||
421
sp/src/game/client/episodic/c_weapon_hopwire.cpp
Normal file
421
sp/src/game/client/episodic/c_weapon_hopwire.cpp
Normal file
@@ -0,0 +1,421 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "basegrenade_shared.h"
|
||||
#include "fx_interpvalue.h"
|
||||
#include "fx_envelope.h"
|
||||
#include "materialsystem/imaterialvar.h"
|
||||
#include "particles_simple.h"
|
||||
#include "particles_attractor.h"
|
||||
|
||||
// FIXME: Move out
|
||||
extern void DrawSpriteTangentSpace( const Vector &vecOrigin, float flWidth, float flHeight, color32 color );
|
||||
|
||||
#define EXPLOSION_DURATION 3.0f
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Explosion effect for hopwire
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class C_HopwireExplosion : public C_EnvelopeFX
|
||||
{
|
||||
typedef C_EnvelopeFX BaseClass;
|
||||
|
||||
public:
|
||||
C_HopwireExplosion( void ) :
|
||||
m_hOwner( NULL )
|
||||
{
|
||||
m_FXCoreScale.SetAbsolute( 0.0f );
|
||||
m_FXCoreAlpha.SetAbsolute( 0.0f );
|
||||
}
|
||||
|
||||
virtual void Update( void );
|
||||
virtual int DrawModel( int flags );
|
||||
virtual void GetRenderBounds( Vector& mins, Vector& maxs );
|
||||
|
||||
bool SetupEmitters( void );
|
||||
void AddParticles( void );
|
||||
void SetOwner( C_BaseEntity *pOwner );
|
||||
void StartExplosion( void );
|
||||
void StopExplosion( void );
|
||||
void StartPreExplosion( void );
|
||||
|
||||
private:
|
||||
CInterpolatedValue m_FXCoreScale;
|
||||
CInterpolatedValue m_FXCoreAlpha;
|
||||
|
||||
CSmartPtr<CSimpleEmitter> m_pSimpleEmitter;
|
||||
CSmartPtr<CParticleAttractor> m_pAttractorEmitter;
|
||||
|
||||
TimedEvent m_ParticleTimer;
|
||||
|
||||
CHandle<C_BaseEntity> m_hOwner;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Setup the emitters we'll be using
|
||||
//-----------------------------------------------------------------------------
|
||||
bool C_HopwireExplosion::SetupEmitters( void )
|
||||
{
|
||||
// Setup the basic core emitter
|
||||
if ( m_pSimpleEmitter.IsValid() == false )
|
||||
{
|
||||
m_pSimpleEmitter = CSimpleEmitter::Create( "hopwirecore" );
|
||||
|
||||
if ( m_pSimpleEmitter.IsValid() == false )
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup the attractor emitter
|
||||
if ( m_pAttractorEmitter.IsValid() == false )
|
||||
{
|
||||
m_pAttractorEmitter = CParticleAttractor::Create( GetRenderOrigin(), "hopwireattractor" );
|
||||
|
||||
if ( m_pAttractorEmitter.IsValid() == false )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_HopwireExplosion::AddParticles( void )
|
||||
{
|
||||
// Make sure the emitters are setup properly
|
||||
if ( SetupEmitters() == false )
|
||||
return;
|
||||
|
||||
float tempDelta = gpGlobals->frametime;
|
||||
while( m_ParticleTimer.NextEvent( tempDelta ) )
|
||||
{
|
||||
// ========================
|
||||
// Attracted dust particles
|
||||
// ========================
|
||||
|
||||
// Update our attractor point
|
||||
m_pAttractorEmitter->SetAttractorOrigin( GetRenderOrigin() );
|
||||
|
||||
Vector offset;
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
offset = GetRenderOrigin() + RandomVector( -256.0f, 256.0f );
|
||||
|
||||
sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_Fleck_Cement[0], offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = Vector(0,0,8);
|
||||
sParticle->m_flDieTime = 0.5f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 1.0f;
|
||||
|
||||
float alpha = random->RandomFloat( 128.0f, 200.0f );
|
||||
|
||||
sParticle->m_uchColor[0] = alpha;
|
||||
sParticle->m_uchColor[1] = alpha;
|
||||
sParticle->m_uchColor[2] = alpha;
|
||||
sParticle->m_uchStartAlpha = alpha;
|
||||
sParticle->m_uchEndAlpha = alpha;
|
||||
|
||||
sParticle->m_uchStartSize = random->RandomInt( 1, 4 );
|
||||
sParticle->m_uchEndSize = 0;
|
||||
|
||||
// ========================
|
||||
// Core effects
|
||||
// ========================
|
||||
|
||||
// Reset our sort origin
|
||||
m_pSimpleEmitter->SetSortOrigin( GetRenderOrigin() );
|
||||
|
||||
// Base of the core effect
|
||||
sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( "effects/strider_muzzle" ), GetRenderOrigin() );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = vec3_origin;
|
||||
sParticle->m_flDieTime = 0.2f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 4.0f;
|
||||
|
||||
alpha = random->RandomInt( 32, 200 );
|
||||
|
||||
sParticle->m_uchColor[0] = alpha;
|
||||
sParticle->m_uchColor[1] = alpha;
|
||||
sParticle->m_uchColor[2] = alpha;
|
||||
sParticle->m_uchStartAlpha = 0;
|
||||
sParticle->m_uchEndAlpha = alpha;
|
||||
|
||||
sParticle->m_uchStartSize = 255;
|
||||
sParticle->m_uchEndSize = 0;
|
||||
|
||||
// Make sure we encompass the complete particle here!
|
||||
m_pSimpleEmitter->SetParticleCullRadius( sParticle->m_uchEndSize );
|
||||
|
||||
// =========================
|
||||
// Dust ring effect
|
||||
// =========================
|
||||
|
||||
if ( random->RandomInt( 0, 5 ) != 1 )
|
||||
return;
|
||||
|
||||
Vector vecDustColor;
|
||||
vecDustColor.x = 0.35f;
|
||||
vecDustColor.y = 0.3f;
|
||||
vecDustColor.z = 0.25f;
|
||||
|
||||
Vector color;
|
||||
|
||||
int numRingSprites = 8;
|
||||
float yaw;
|
||||
Vector forward, vRight, vForward;
|
||||
|
||||
vForward = Vector( 0, 1, 0 );
|
||||
vRight = Vector( 1, 0, 0 );
|
||||
|
||||
float yawOfs = random->RandomFloat( 0, 359 );
|
||||
|
||||
for ( int i = 0; i < numRingSprites; i++ )
|
||||
{
|
||||
yaw = ( (float) i / (float) numRingSprites ) * 360.0f;
|
||||
yaw += yawOfs;
|
||||
|
||||
forward = ( vRight * sin( DEG2RAD( yaw) ) ) + ( vForward * cos( DEG2RAD( yaw ) ) );
|
||||
VectorNormalize( forward );
|
||||
|
||||
trace_t tr;
|
||||
|
||||
UTIL_TraceLine( GetRenderOrigin(), GetRenderOrigin()+(Vector(0, 0, -1024)), MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
offset = ( RandomVector( -4.0f, 4.0f ) + tr.endpos ) + ( forward * 512.0f );
|
||||
|
||||
sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[random->RandomInt(0,1)], offset );
|
||||
|
||||
if ( sParticle != NULL )
|
||||
{
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
|
||||
|
||||
sParticle->m_vecVelocity = forward * -random->RandomFloat( 1000, 1500 );
|
||||
sParticle->m_vecVelocity[2] += 128.0f;
|
||||
|
||||
#if __EXPLOSION_DEBUG
|
||||
debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + sParticle->m_vecVelocity, 255, 0, 0, false, 3 );
|
||||
#endif
|
||||
|
||||
sParticle->m_uchColor[0] = vecDustColor.x * 255.0f;
|
||||
sParticle->m_uchColor[1] = vecDustColor.y * 255.0f;
|
||||
sParticle->m_uchColor[2] = vecDustColor.z * 255.0f;
|
||||
|
||||
sParticle->m_uchStartSize = random->RandomInt( 32, 128 );
|
||||
sParticle->m_uchEndSize = 200;
|
||||
|
||||
sParticle->m_uchStartAlpha = random->RandomFloat( 16, 64 );
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
|
||||
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pOwner -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_HopwireExplosion::SetOwner( C_BaseEntity *pOwner )
|
||||
{
|
||||
m_hOwner = pOwner;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Updates the internal values for the effect
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_HopwireExplosion::Update( void )
|
||||
{
|
||||
if ( m_hOwner )
|
||||
{
|
||||
SetRenderOrigin( m_hOwner->GetRenderOrigin() );
|
||||
}
|
||||
|
||||
BaseClass::Update();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Updates and renders all effects
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_HopwireExplosion::DrawModel( int flags )
|
||||
{
|
||||
AddParticles();
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->Flush();
|
||||
UpdateRefractTexture();
|
||||
|
||||
IMaterial *pMat = materials->FindMaterial( "effects/strider_pinch_dudv", TEXTURE_GROUP_CLIENT_EFFECTS );
|
||||
|
||||
float refract = m_FXCoreAlpha.Interp( gpGlobals->curtime );
|
||||
float scale = m_FXCoreScale.Interp( gpGlobals->curtime );
|
||||
|
||||
IMaterialVar *pVar = pMat->FindVar( "$refractamount", NULL );
|
||||
pVar->SetFloatValue( refract );
|
||||
|
||||
pRenderContext->Bind( pMat, (IClientRenderable*)this );
|
||||
|
||||
float sin1 = sinf( gpGlobals->curtime * 10 );
|
||||
float sin2 = sinf( gpGlobals->curtime );
|
||||
|
||||
float scaleY = ( sin1 * sin2 ) * 32.0f;
|
||||
float scaleX = (sin2 * sin2) * 32.0f;
|
||||
|
||||
// FIXME: The ball needs to sort properly at all times
|
||||
static color32 white = {255,255,255,255};
|
||||
DrawSpriteTangentSpace( GetRenderOrigin() + ( CurrentViewForward() * 128.0f ), scale+scaleX, scale+scaleY, white );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns the bounds relative to the origin (render bounds)
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_HopwireExplosion::GetRenderBounds( Vector& mins, Vector& maxs )
|
||||
{
|
||||
float scale = m_FXCoreScale.Interp( gpGlobals->curtime );
|
||||
|
||||
mins.Init( -scale, -scale, -scale );
|
||||
maxs.Init( scale, scale, scale );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_HopwireExplosion::StartExplosion( void )
|
||||
{
|
||||
m_FXCoreScale.Init( 300.0f, 500.0f, 2.0f, INTERP_SPLINE );
|
||||
m_FXCoreAlpha.Init( 0.0f, 0.1f, 1.5f, INTERP_SPLINE );
|
||||
|
||||
// Particle timer
|
||||
m_ParticleTimer.Init( 60 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_HopwireExplosion::StopExplosion( void )
|
||||
{
|
||||
m_FXCoreAlpha.InitFromCurrent( 0.0f, 1.0f, INTERP_SPLINE );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_HopwireExplosion::StartPreExplosion( void )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Hopwire client class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class C_GrenadeHopwire : public C_BaseGrenade
|
||||
{
|
||||
DECLARE_CLASS( C_GrenadeHopwire, C_BaseGrenade );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
public:
|
||||
C_GrenadeHopwire( void );
|
||||
|
||||
virtual int DrawModel( int flags );
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual void ReceiveMessage( int classID, bf_read &msg );
|
||||
|
||||
private:
|
||||
|
||||
C_HopwireExplosion m_ExplosionEffect; // Explosion effect information and drawing
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_GrenadeHopwire, DT_GrenadeHopwire, CGrenadeHopwire )
|
||||
END_RECV_TABLE()
|
||||
|
||||
#define HOPWIRE_START_EXPLOSION 0
|
||||
#define HOPWIRE_STOP_EXPLOSION 1
|
||||
#define HOPWIRE_START_PRE_EXPLOSION 2
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_GrenadeHopwire::C_GrenadeHopwire( void )
|
||||
{
|
||||
m_ExplosionEffect.SetActive( false );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Receive messages from the server
|
||||
// Input : classID - class to receive the message
|
||||
// &msg - message in question
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_GrenadeHopwire::ReceiveMessage( int classID, bf_read &msg )
|
||||
{
|
||||
if ( classID != GetClientClass()->m_ClassID )
|
||||
{
|
||||
// Message is for subclass
|
||||
BaseClass::ReceiveMessage( classID, msg );
|
||||
return;
|
||||
}
|
||||
|
||||
int messageType = msg.ReadByte();
|
||||
switch( messageType )
|
||||
{
|
||||
case HOPWIRE_START_EXPLOSION:
|
||||
{
|
||||
m_ExplosionEffect.SetActive();
|
||||
m_ExplosionEffect.SetOwner( this );
|
||||
m_ExplosionEffect.StartExplosion();
|
||||
}
|
||||
break;
|
||||
case HOPWIRE_STOP_EXPLOSION:
|
||||
{
|
||||
m_ExplosionEffect.StopExplosion();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_GrenadeHopwire::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
m_ExplosionEffect.Update();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flags -
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_GrenadeHopwire::DrawModel( int flags )
|
||||
{
|
||||
if ( m_ExplosionEffect.IsActive() )
|
||||
return 1;
|
||||
|
||||
return BaseClass::DrawModel( flags );
|
||||
}
|
||||
|
||||
464
sp/src/game/client/episodic/episodic_screenspaceeffects.cpp
Normal file
464
sp/src/game/client/episodic/episodic_screenspaceeffects.cpp
Normal file
@@ -0,0 +1,464 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Episodic screen-space effects
|
||||
//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "ScreenSpaceEffects.h"
|
||||
#include "rendertexture.h"
|
||||
#include "materialsystem/imaterialsystemhardwareconfig.h"
|
||||
#include "materialsystem/imaterialsystem.h"
|
||||
#include "materialsystem/imaterialvar.h"
|
||||
#include "cdll_client_int.h"
|
||||
#include "materialsystem/itexture.h"
|
||||
#include "KeyValues.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
|
||||
#include "episodic_screenspaceeffects.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef _X360
|
||||
#define STUN_TEXTURE "_rt_FullFrameFB2"
|
||||
#else
|
||||
#define STUN_TEXTURE "_rt_WaterRefraction"
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CStunEffect::Init( void )
|
||||
{
|
||||
m_flDuration = 0.0f;
|
||||
m_flFinishTime = 0.0f;
|
||||
m_bUpdateView = true;
|
||||
|
||||
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
|
||||
pVMTKeyValues->SetString( "$basetexture", STUN_TEXTURE );
|
||||
m_EffectMaterial.Init( "__stuneffect", TEXTURE_GROUP_CLIENT_EFFECTS, pVMTKeyValues );
|
||||
m_StunTexture.Init( STUN_TEXTURE, TEXTURE_GROUP_CLIENT_EFFECTS );
|
||||
}
|
||||
|
||||
void CStunEffect::Shutdown( void )
|
||||
{
|
||||
m_EffectMaterial.Shutdown();
|
||||
m_StunTexture.Shutdown();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: Pick up changes in our parameters
|
||||
//------------------------------------------------------------------------------
|
||||
void CStunEffect::SetParameters( KeyValues *params )
|
||||
{
|
||||
if( params->FindKey( "duration" ) )
|
||||
{
|
||||
m_flDuration = params->GetFloat( "duration" );
|
||||
m_flFinishTime = gpGlobals->curtime + m_flDuration;
|
||||
m_bUpdateView = true;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Render the effect
|
||||
//-----------------------------------------------------------------------------
|
||||
void CStunEffect::Render( int x, int y, int w, int h )
|
||||
{
|
||||
// Make sure we're ready to play this effect
|
||||
if ( m_flFinishTime < gpGlobals->curtime )
|
||||
return;
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
|
||||
// Set ourselves to the proper rendermode
|
||||
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
||||
pRenderContext->PushMatrix();
|
||||
pRenderContext->LoadIdentity();
|
||||
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||||
pRenderContext->PushMatrix();
|
||||
pRenderContext->LoadIdentity();
|
||||
|
||||
// Draw the texture if we're using it
|
||||
if ( m_bUpdateView )
|
||||
{
|
||||
// Save off this pass
|
||||
Rect_t srcRect;
|
||||
srcRect.x = x;
|
||||
srcRect.y = y;
|
||||
srcRect.width = w;
|
||||
srcRect.height = h;
|
||||
pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
|
||||
m_bUpdateView = false;
|
||||
}
|
||||
|
||||
float flEffectPerc = ( m_flFinishTime - gpGlobals->curtime ) / m_flDuration;
|
||||
|
||||
float viewOffs = ( flEffectPerc * 32.0f ) * ( cos( gpGlobals->curtime * 40.0f ) * sin( gpGlobals->curtime * 17.0f ) );
|
||||
float vX = x + viewOffs;
|
||||
|
||||
if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 80 )
|
||||
{
|
||||
if ( g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_NONE )
|
||||
{
|
||||
m_EffectMaterial->ColorModulate( 1.0f, 1.0f, 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a stupid fix, but I don't have time to do a cleaner implementation. Since
|
||||
// the introblur.vmt material uses unlit generic, it will tone map, so I need to undo the tone mapping
|
||||
// using color modulate. The proper fix would be to use a different material type that
|
||||
// supports alpha blending but not tone mapping, which I don't think exists. Whatever. This works when
|
||||
// the tone mapping scalar is less than 1.0, which it is in the cases it's used in game.
|
||||
float flUnTonemap = pow( 1.0f / pRenderContext->GetToneMappingScaleLinear().x, 1.0f / 2.2f );
|
||||
m_EffectMaterial->ColorModulate( flUnTonemap, flUnTonemap, flUnTonemap );
|
||||
}
|
||||
|
||||
// Set alpha blend value
|
||||
float flOverlayAlpha = clamp( ( 150.0f / 255.0f ) * flEffectPerc, 0.0f, 1.0f );
|
||||
m_EffectMaterial->AlphaModulate( flOverlayAlpha );
|
||||
|
||||
// Draw full screen alpha-blended quad
|
||||
pRenderContext->DrawScreenSpaceRectangle( m_EffectMaterial, 0, 0, w, h,
|
||||
vX, 0, (m_StunTexture->GetActualWidth()-1)+vX, (m_StunTexture->GetActualHeight()-1),
|
||||
m_StunTexture->GetActualWidth(), m_StunTexture->GetActualHeight() );
|
||||
}
|
||||
|
||||
// Save off this pass
|
||||
Rect_t srcRect;
|
||||
srcRect.x = x;
|
||||
srcRect.y = y;
|
||||
srcRect.width = w;
|
||||
srcRect.height = h;
|
||||
pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
|
||||
|
||||
// Restore our state
|
||||
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
||||
pRenderContext->PopMatrix();
|
||||
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||||
pRenderContext->PopMatrix();
|
||||
}
|
||||
|
||||
// ================================================================================================================
|
||||
//
|
||||
// Ep 1. Intro blur
|
||||
//
|
||||
// ================================================================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEP1IntroEffect::Init( void )
|
||||
{
|
||||
m_flDuration = 0.0f;
|
||||
m_flFinishTime = 0.0f;
|
||||
m_bUpdateView = true;
|
||||
m_bFadeOut = false;
|
||||
|
||||
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
|
||||
pVMTKeyValues->SetString( "$basetexture", STUN_TEXTURE );
|
||||
m_EffectMaterial.Init( "__ep1introeffect", TEXTURE_GROUP_CLIENT_EFFECTS, pVMTKeyValues );
|
||||
m_StunTexture.Init( STUN_TEXTURE, TEXTURE_GROUP_CLIENT_EFFECTS );
|
||||
}
|
||||
|
||||
void CEP1IntroEffect::Shutdown( void )
|
||||
{
|
||||
m_EffectMaterial.Shutdown();
|
||||
m_StunTexture.Shutdown();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: Pick up changes in our parameters
|
||||
//------------------------------------------------------------------------------
|
||||
void CEP1IntroEffect::SetParameters( KeyValues *params )
|
||||
{
|
||||
if( params->FindKey( "duration" ) )
|
||||
{
|
||||
m_flDuration = params->GetFloat( "duration" );
|
||||
m_flFinishTime = gpGlobals->curtime + m_flDuration;
|
||||
}
|
||||
|
||||
if( params->FindKey( "fadeout" ) )
|
||||
{
|
||||
m_bFadeOut = ( params->GetInt( "fadeout" ) == 1 );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Get the alpha value depending on various factors and time
|
||||
//-----------------------------------------------------------------------------
|
||||
inline unsigned char CEP1IntroEffect::GetFadeAlpha( void )
|
||||
{
|
||||
// Find our percentage between fully "on" and "off" in the pulse range
|
||||
float flEffectPerc = ( m_flDuration == 0.0f ) ? 0.0f : ( m_flFinishTime - gpGlobals->curtime ) / m_flDuration;
|
||||
flEffectPerc = clamp( flEffectPerc, 0.0f, 1.0f );
|
||||
|
||||
if ( m_bFadeOut )
|
||||
{
|
||||
// HDR requires us to be more subtle, or we get uber-brightening
|
||||
if ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
|
||||
return (unsigned char) clamp( 50.0f * flEffectPerc, 0.0f, 50.0f );
|
||||
|
||||
// Non-HDR
|
||||
return (unsigned char) clamp( 64.0f * flEffectPerc, 0.0f, 64.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
// HDR requires us to be more subtle, or we get uber-brightening
|
||||
if ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
|
||||
return (unsigned char) clamp( 64.0f * flEffectPerc, 50.0f, 64.0f );
|
||||
|
||||
// Non-HDR
|
||||
return (unsigned char) clamp( 128.0f * flEffectPerc, 64.0f, 128.0f );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Render the effect
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEP1IntroEffect::Render( int x, int y, int w, int h )
|
||||
{
|
||||
if ( ( m_flFinishTime == 0 ) || ( IsEnabled() == false ) )
|
||||
return;
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
|
||||
// Set ourselves to the proper rendermode
|
||||
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
||||
pRenderContext->PushMatrix();
|
||||
pRenderContext->LoadIdentity();
|
||||
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||||
pRenderContext->PushMatrix();
|
||||
pRenderContext->LoadIdentity();
|
||||
|
||||
// Draw the texture if we're using it
|
||||
if ( m_bUpdateView )
|
||||
{
|
||||
// Save off this pass
|
||||
Rect_t srcRect;
|
||||
srcRect.x = x;
|
||||
srcRect.y = y;
|
||||
srcRect.width = w;
|
||||
srcRect.height = h;
|
||||
pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
|
||||
m_bUpdateView = false;
|
||||
}
|
||||
|
||||
byte overlaycolor[4] = { 255, 255, 255, 0 };
|
||||
|
||||
// Get our fade value depending on our fade duration
|
||||
overlaycolor[3] = GetFadeAlpha();
|
||||
if ( g_pMaterialSystemHardwareConfig->UsesSRGBCorrectBlending() )
|
||||
{
|
||||
// For DX10 cards, alpha blending happens in linear space, so try to adjust by hacking alpha to 50%
|
||||
overlaycolor[3] *= 0.7f;
|
||||
}
|
||||
|
||||
// Disable overself if we're done fading out
|
||||
if ( m_bFadeOut && overlaycolor[3] == 0 )
|
||||
{
|
||||
// Takes effect next frame (we don't want to hose our matrix stacks here)
|
||||
g_pScreenSpaceEffects->DisableScreenSpaceEffect( "episodic_intro" );
|
||||
m_bUpdateView = true;
|
||||
}
|
||||
|
||||
// Calculate some wavey noise to jitter the view by
|
||||
float vX = 2.0f * -fabs( cosf( gpGlobals->curtime ) * cosf( gpGlobals->curtime * 6.0 ) );
|
||||
float vY = 2.0f * cosf( gpGlobals->curtime ) * cosf( gpGlobals->curtime * 5.0 );
|
||||
|
||||
// Scale percentage
|
||||
float flScalePerc = 0.02f + ( 0.01f * cosf( gpGlobals->curtime * 2.0f ) * cosf( gpGlobals->curtime * 0.5f ) );
|
||||
|
||||
// Scaled offsets for the UVs (as texels)
|
||||
float flUOffset = ( m_StunTexture->GetActualWidth() - 1 ) * flScalePerc * 0.5f;
|
||||
float flVOffset = ( m_StunTexture->GetActualHeight() - 1 ) * flScalePerc * 0.5f;
|
||||
|
||||
// New UVs with scaling offsets
|
||||
float flU1 = flUOffset;
|
||||
float flU2 = ( m_StunTexture->GetActualWidth() - 1 ) - flUOffset;
|
||||
float flV1 = flVOffset;
|
||||
float flV2 = ( m_StunTexture->GetActualHeight() - 1 ) - flVOffset;
|
||||
|
||||
// Draw the "zoomed" overlay
|
||||
pRenderContext->DrawScreenSpaceRectangle( m_EffectMaterial, vX, vY, w, h,
|
||||
flU1, flV1,
|
||||
flU2, flV2,
|
||||
m_StunTexture->GetActualWidth(), m_StunTexture->GetActualHeight() );
|
||||
|
||||
render->ViewDrawFade( overlaycolor, m_EffectMaterial );
|
||||
|
||||
// Save off this pass
|
||||
Rect_t srcRect;
|
||||
srcRect.x = x;
|
||||
srcRect.y = y;
|
||||
srcRect.width = w;
|
||||
srcRect.height = h;
|
||||
pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
|
||||
|
||||
// Restore our state
|
||||
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
||||
pRenderContext->PopMatrix();
|
||||
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||||
pRenderContext->PopMatrix();
|
||||
}
|
||||
|
||||
// ================================================================================================================
|
||||
//
|
||||
// Ep 2. Groggy-player view
|
||||
//
|
||||
// ================================================================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEP2StunEffect::Init( void )
|
||||
{
|
||||
m_flDuration = 0.0f;
|
||||
m_flFinishTime = 0.0f;
|
||||
m_bUpdateView = true;
|
||||
m_bFadeOut = false;
|
||||
|
||||
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
|
||||
pVMTKeyValues->SetString( "$basetexture", STUN_TEXTURE );
|
||||
m_EffectMaterial.Init( "__ep2stuneffect", TEXTURE_GROUP_CLIENT_EFFECTS, pVMTKeyValues );
|
||||
m_StunTexture.Init( STUN_TEXTURE, TEXTURE_GROUP_CLIENT_EFFECTS );
|
||||
}
|
||||
|
||||
void CEP2StunEffect::Shutdown( void )
|
||||
{
|
||||
m_EffectMaterial.Shutdown();
|
||||
m_StunTexture.Shutdown();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: Pick up changes in our parameters
|
||||
//------------------------------------------------------------------------------
|
||||
void CEP2StunEffect::SetParameters( KeyValues *params )
|
||||
{
|
||||
if( params->FindKey( "duration" ) )
|
||||
{
|
||||
m_flDuration = params->GetFloat( "duration" );
|
||||
m_flFinishTime = gpGlobals->curtime + m_flDuration;
|
||||
}
|
||||
|
||||
if( params->FindKey( "fadeout" ) )
|
||||
{
|
||||
m_bFadeOut = ( params->GetInt( "fadeout" ) == 1 );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Get the alpha value depending on various factors and time
|
||||
//-----------------------------------------------------------------------------
|
||||
inline unsigned char CEP2StunEffect::GetFadeAlpha( void )
|
||||
{
|
||||
// Find our percentage between fully "on" and "off" in the pulse range
|
||||
float flEffectPerc = ( m_flDuration == 0.0f ) ? 0.0f : ( m_flFinishTime - gpGlobals->curtime ) / m_flDuration;
|
||||
flEffectPerc = clamp( flEffectPerc, 0.0f, 1.0f );
|
||||
|
||||
if ( m_bFadeOut )
|
||||
{
|
||||
// HDR requires us to be more subtle, or we get uber-brightening
|
||||
if ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
|
||||
return (unsigned char) clamp( 50.0f * flEffectPerc, 0.0f, 50.0f );
|
||||
|
||||
// Non-HDR
|
||||
return (unsigned char) clamp( 64.0f * flEffectPerc, 0.0f, 64.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
// HDR requires us to be more subtle, or we get uber-brightening
|
||||
if ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
|
||||
return (unsigned char) clamp( 164.0f * flEffectPerc, 128.0f, 164.0f );
|
||||
|
||||
// Non-HDR
|
||||
return (unsigned char) clamp( 164.0f * flEffectPerc, 128.0f, 164.0f );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Render the effect
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEP2StunEffect::Render( int x, int y, int w, int h )
|
||||
{
|
||||
if ( ( m_flFinishTime == 0 ) || ( IsEnabled() == false ) )
|
||||
return;
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
|
||||
// Set ourselves to the proper rendermode
|
||||
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
||||
pRenderContext->PushMatrix();
|
||||
pRenderContext->LoadIdentity();
|
||||
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||||
pRenderContext->PushMatrix();
|
||||
pRenderContext->LoadIdentity();
|
||||
|
||||
if ( m_bUpdateView )
|
||||
{
|
||||
// Save off this pass
|
||||
Rect_t srcRect;
|
||||
srcRect.x = x;
|
||||
srcRect.y = y;
|
||||
srcRect.width = w;
|
||||
srcRect.height = h;
|
||||
pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
|
||||
m_bUpdateView = false;
|
||||
}
|
||||
|
||||
byte overlaycolor[4] = { 255, 255, 255, 0 };
|
||||
|
||||
// Get our fade value depending on our fade duration
|
||||
overlaycolor[3] = GetFadeAlpha();
|
||||
|
||||
// Disable overself if we're done fading out
|
||||
if ( m_bFadeOut && overlaycolor[3] == 0 )
|
||||
{
|
||||
// Takes effect next frame (we don't want to hose our matrix stacks here)
|
||||
g_pScreenSpaceEffects->DisableScreenSpaceEffect( "ep2_groggy" );
|
||||
m_bUpdateView = true;
|
||||
}
|
||||
|
||||
// Calculate some wavey noise to jitter the view by
|
||||
float vX = 4.0f * cosf( gpGlobals->curtime ) * cosf( gpGlobals->curtime * 6.0 );
|
||||
float vY = 2.0f * cosf( gpGlobals->curtime ) * cosf( gpGlobals->curtime * 5.0 );
|
||||
|
||||
float flBaseScale = 0.2f + 0.005f * sinf( gpGlobals->curtime * 4.0f );
|
||||
|
||||
// Scale percentage
|
||||
float flScalePerc = flBaseScale + ( 0.01f * cosf( gpGlobals->curtime * 2.0f ) * cosf( gpGlobals->curtime * 0.5f ) );
|
||||
|
||||
// Scaled offsets for the UVs (as texels)
|
||||
float flUOffset = ( m_StunTexture->GetActualWidth() - 1 ) * flScalePerc * 0.5f;
|
||||
float flVOffset = ( m_StunTexture->GetActualHeight() - 1 ) * flScalePerc * 0.5f;
|
||||
|
||||
// New UVs with scaling offsets
|
||||
float flU1 = flUOffset;
|
||||
float flU2 = ( m_StunTexture->GetActualWidth() - 1 ) - flUOffset;
|
||||
float flV1 = flVOffset;
|
||||
float flV2 = ( m_StunTexture->GetActualHeight() - 1 ) - flVOffset;
|
||||
|
||||
// Draw the "zoomed" overlay
|
||||
pRenderContext->DrawScreenSpaceRectangle( m_EffectMaterial, vX, vY, w, h,
|
||||
flU1, flV1,
|
||||
flU2, flV2,
|
||||
m_StunTexture->GetActualWidth(), m_StunTexture->GetActualHeight() );
|
||||
|
||||
render->ViewDrawFade( overlaycolor, m_EffectMaterial );
|
||||
|
||||
// Save off this pass
|
||||
Rect_t srcRect;
|
||||
srcRect.x = x;
|
||||
srcRect.y = y;
|
||||
srcRect.width = w;
|
||||
srcRect.height = h;
|
||||
pRenderContext->CopyRenderTargetToTextureEx( m_StunTexture, 0, &srcRect, NULL );
|
||||
|
||||
// Restore our state
|
||||
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
||||
pRenderContext->PopMatrix();
|
||||
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||||
pRenderContext->PopMatrix();
|
||||
}
|
||||
119
sp/src/game/client/episodic/episodic_screenspaceeffects.h
Normal file
119
sp/src/game/client/episodic/episodic_screenspaceeffects.h
Normal file
@@ -0,0 +1,119 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef EPISODIC_SCREENSPACEEFFECTS_H
|
||||
#define EPISODIC_SCREENSPACEEFFECTS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "ScreenSpaceEffects.h"
|
||||
|
||||
class CStunEffect : public IScreenSpaceEffect
|
||||
{
|
||||
public:
|
||||
CStunEffect( void ) :
|
||||
m_flDuration( 0.0f ),
|
||||
m_flFinishTime( 0.0f ),
|
||||
m_bUpdateView( true ) {}
|
||||
|
||||
virtual void Init( void );
|
||||
virtual void Shutdown( void );
|
||||
virtual void SetParameters( KeyValues *params );
|
||||
virtual void Enable( bool bEnable ) {};
|
||||
virtual bool IsEnabled( ) { return true; }
|
||||
|
||||
virtual void Render( int x, int y, int w, int h );
|
||||
|
||||
private:
|
||||
CTextureReference m_StunTexture;
|
||||
CMaterialReference m_EffectMaterial;
|
||||
float m_flDuration;
|
||||
float m_flFinishTime;
|
||||
bool m_bUpdateView;
|
||||
};
|
||||
|
||||
ADD_SCREENSPACE_EFFECT( CStunEffect, episodic_stun );
|
||||
|
||||
//
|
||||
// EP1 Intro Blur
|
||||
//
|
||||
|
||||
class CEP1IntroEffect : public IScreenSpaceEffect
|
||||
{
|
||||
public:
|
||||
CEP1IntroEffect( void ) :
|
||||
m_flDuration( 0.0f ),
|
||||
m_flFinishTime( 0.0f ),
|
||||
m_bUpdateView( true ),
|
||||
m_bEnabled( false ),
|
||||
m_bFadeOut( false ) {}
|
||||
|
||||
virtual void Init( void );
|
||||
virtual void Shutdown( void );
|
||||
virtual void SetParameters( KeyValues *params );
|
||||
virtual void Enable( bool bEnable ) { m_bEnabled = bEnable; }
|
||||
virtual bool IsEnabled( ) { return m_bEnabled; }
|
||||
|
||||
virtual void Render( int x, int y, int w, int h );
|
||||
|
||||
private:
|
||||
|
||||
inline unsigned char GetFadeAlpha( void );
|
||||
|
||||
CTextureReference m_StunTexture;
|
||||
CMaterialReference m_EffectMaterial;
|
||||
float m_flDuration;
|
||||
float m_flFinishTime;
|
||||
bool m_bUpdateView;
|
||||
bool m_bEnabled;
|
||||
bool m_bFadeOut;
|
||||
};
|
||||
|
||||
ADD_SCREENSPACE_EFFECT( CEP1IntroEffect, episodic_intro );
|
||||
|
||||
//
|
||||
// EP2 Player Stunned Effect
|
||||
//
|
||||
|
||||
//
|
||||
// EP1 Intro Blur
|
||||
//
|
||||
|
||||
class CEP2StunEffect : public IScreenSpaceEffect
|
||||
{
|
||||
public:
|
||||
CEP2StunEffect( void ) :
|
||||
m_flDuration( 0.0f ),
|
||||
m_flFinishTime( 0.0f ),
|
||||
m_bUpdateView( true ),
|
||||
m_bEnabled( false ),
|
||||
m_bFadeOut( false ) {}
|
||||
|
||||
virtual void Init( void );
|
||||
virtual void Shutdown( void );
|
||||
virtual void SetParameters( KeyValues *params );
|
||||
virtual void Enable( bool bEnable ) { m_bEnabled = bEnable; }
|
||||
virtual bool IsEnabled( ) { return m_bEnabled; }
|
||||
|
||||
virtual void Render( int x, int y, int w, int h );
|
||||
|
||||
private:
|
||||
|
||||
inline unsigned char GetFadeAlpha( void );
|
||||
|
||||
CTextureReference m_StunTexture;
|
||||
CMaterialReference m_EffectMaterial;
|
||||
float m_flDuration;
|
||||
float m_flFinishTime;
|
||||
bool m_bUpdateView;
|
||||
bool m_bEnabled;
|
||||
bool m_bFadeOut;
|
||||
};
|
||||
|
||||
ADD_SCREENSPACE_EFFECT( CEP2StunEffect, ep2_groggy );
|
||||
|
||||
#endif // EPISODIC_SCREENSPACEEFFECTS_H
|
||||
225
sp/src/game/client/episodic/flesh_internal_material_proxy.cpp
Normal file
225
sp/src/game/client/episodic/flesh_internal_material_proxy.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=====================================================================================//
|
||||
#include "cbase.h"
|
||||
#include "proxyentity.h"
|
||||
#include "materialsystem/imaterial.h"
|
||||
#include "materialsystem/imaterialvar.h"
|
||||
#include "debugoverlay_shared.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
class C_FleshEffectTarget;
|
||||
void AddFleshProxyTarget( C_FleshEffectTarget *pTarget );
|
||||
void RemoveFleshProxy( C_FleshEffectTarget *pTarget );
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Flesh effect target (used for orchestrating the "Invisible Alyx" moment
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
class C_FleshEffectTarget : public C_BaseEntity
|
||||
{
|
||||
DECLARE_CLASS( C_FleshEffectTarget, C_BaseEntity );
|
||||
|
||||
public:
|
||||
float GetRadius( void )
|
||||
{
|
||||
if ( m_flScaleTime <= 0.0f )
|
||||
return m_flRadius;
|
||||
|
||||
float dt = ( gpGlobals->curtime - m_flScaleStartTime );
|
||||
if ( dt >= m_flScaleTime )
|
||||
return m_flRadius;
|
||||
|
||||
return SimpleSplineRemapVal( ( dt / m_flScaleTime ), 0.0f, 1.0f, m_flStartRadius, m_flRadius );
|
||||
}
|
||||
|
||||
virtual void Release( void )
|
||||
{
|
||||
// Remove us from the list of targets
|
||||
RemoveFleshProxy( this );
|
||||
}
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
// Add us to the list of flesh proxy targets
|
||||
AddFleshProxyTarget( this );
|
||||
}
|
||||
}
|
||||
|
||||
float m_flRadius;
|
||||
float m_flStartRadius;
|
||||
float m_flScaleStartTime;
|
||||
float m_flScaleTime;
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
};
|
||||
|
||||
void RecvProxy_FleshEffect_Radius( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
C_FleshEffectTarget *pTarget = (C_FleshEffectTarget *) pStruct;
|
||||
float flRadius = pData->m_Value.m_Float;
|
||||
|
||||
//If changed, update our internal information
|
||||
if ( pTarget->m_flRadius != flRadius )
|
||||
{
|
||||
pTarget->m_flStartRadius = pTarget->m_flRadius;
|
||||
pTarget->m_flScaleStartTime = gpGlobals->curtime;
|
||||
}
|
||||
|
||||
pTarget->m_flRadius = flRadius;
|
||||
}
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_FleshEffectTarget, DT_FleshEffectTarget, CFleshEffectTarget )
|
||||
RecvPropFloat( RECVINFO(m_flRadius), 0, RecvProxy_FleshEffect_Radius ),
|
||||
RecvPropFloat( RECVINFO(m_flScaleTime) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
CUtlVector< C_FleshEffectTarget * > g_FleshProxyTargets;
|
||||
|
||||
void AddFleshProxyTarget( C_FleshEffectTarget *pTarget )
|
||||
{
|
||||
// Take it!
|
||||
g_FleshProxyTargets.AddToTail( pTarget );
|
||||
}
|
||||
|
||||
void RemoveFleshProxy( C_FleshEffectTarget *pTarget )
|
||||
{
|
||||
int nIndex = g_FleshProxyTargets.Find( pTarget );
|
||||
if ( nIndex != g_FleshProxyTargets.InvalidIndex() )
|
||||
{
|
||||
g_FleshProxyTargets.Remove( nIndex );
|
||||
}
|
||||
}
|
||||
|
||||
// $sineVar : name of variable that controls the FleshInterior level (float)
|
||||
class CFleshInteriorMaterialProxy : public CEntityMaterialProxy
|
||||
{
|
||||
public:
|
||||
CFleshInteriorMaterialProxy();
|
||||
virtual ~CFleshInteriorMaterialProxy();
|
||||
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
|
||||
virtual void OnBind( C_BaseEntity *pEntity );
|
||||
virtual IMaterial *GetMaterial();
|
||||
|
||||
private:
|
||||
IMaterialVar *m_pMaterialParamFleshEffectCenterRadius1;
|
||||
IMaterialVar *m_pMaterialParamFleshEffectCenterRadius2;
|
||||
IMaterialVar *m_pMaterialParamFleshEffectCenterRadius3;
|
||||
IMaterialVar *m_pMaterialParamFleshEffectCenterRadius4;
|
||||
IMaterialVar *m_pMaterialParamFleshGlobalOpacity;
|
||||
IMaterialVar *m_pMaterialParamFleshSubsurfaceTint;
|
||||
};
|
||||
|
||||
CFleshInteriorMaterialProxy::CFleshInteriorMaterialProxy()
|
||||
{
|
||||
m_pMaterialParamFleshEffectCenterRadius1 = NULL;
|
||||
m_pMaterialParamFleshEffectCenterRadius2 = NULL;
|
||||
m_pMaterialParamFleshEffectCenterRadius3 = NULL;
|
||||
m_pMaterialParamFleshEffectCenterRadius4 = NULL;
|
||||
m_pMaterialParamFleshGlobalOpacity = NULL;
|
||||
m_pMaterialParamFleshSubsurfaceTint = NULL;
|
||||
}
|
||||
|
||||
CFleshInteriorMaterialProxy::~CFleshInteriorMaterialProxy()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
bool CFleshInteriorMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
|
||||
{
|
||||
bool bFoundVar = false;
|
||||
|
||||
m_pMaterialParamFleshEffectCenterRadius1 = pMaterial->FindVar( "$FleshEffectCenterRadius1", &bFoundVar, false );
|
||||
if ( bFoundVar == false)
|
||||
return false;
|
||||
|
||||
m_pMaterialParamFleshEffectCenterRadius2 = pMaterial->FindVar( "$FleshEffectCenterRadius2", &bFoundVar, false );
|
||||
if ( bFoundVar == false)
|
||||
return false;
|
||||
|
||||
m_pMaterialParamFleshEffectCenterRadius3 = pMaterial->FindVar( "$FleshEffectCenterRadius3", &bFoundVar, false );
|
||||
if ( bFoundVar == false)
|
||||
return false;
|
||||
|
||||
m_pMaterialParamFleshEffectCenterRadius4 = pMaterial->FindVar( "$FleshEffectCenterRadius4", &bFoundVar, false );
|
||||
if ( bFoundVar == false)
|
||||
return false;
|
||||
|
||||
m_pMaterialParamFleshGlobalOpacity = pMaterial->FindVar( "$FleshGlobalOpacity", &bFoundVar, false );
|
||||
if ( bFoundVar == false)
|
||||
return false;
|
||||
|
||||
m_pMaterialParamFleshSubsurfaceTint = pMaterial->FindVar( "$FleshSubsurfaceTint", &bFoundVar, false );
|
||||
if ( bFoundVar == false)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CFleshInteriorMaterialProxy::OnBind( C_BaseEntity *pEnt )
|
||||
{
|
||||
IMaterialVar *pParams[] =
|
||||
{
|
||||
m_pMaterialParamFleshEffectCenterRadius1,
|
||||
m_pMaterialParamFleshEffectCenterRadius2,
|
||||
m_pMaterialParamFleshEffectCenterRadius3,
|
||||
m_pMaterialParamFleshEffectCenterRadius4
|
||||
};
|
||||
|
||||
float vEffectCenterRadius[4];
|
||||
for ( int i = 0; i < ARRAYSIZE( pParams ); i++ )
|
||||
{
|
||||
if ( i < g_FleshProxyTargets.Count() )
|
||||
{
|
||||
// Setup the target
|
||||
if ( g_FleshProxyTargets[i]->IsAbsQueriesValid() == false )
|
||||
continue;
|
||||
|
||||
Vector vecAbsOrigin = g_FleshProxyTargets[i]->GetAbsOrigin();
|
||||
vEffectCenterRadius[0] = vecAbsOrigin.x;
|
||||
vEffectCenterRadius[1] = vecAbsOrigin.y;
|
||||
vEffectCenterRadius[2] = vecAbsOrigin.z;
|
||||
vEffectCenterRadius[3] = g_FleshProxyTargets[i]->GetRadius();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear the target
|
||||
vEffectCenterRadius[0] = vEffectCenterRadius[1] = vEffectCenterRadius[2] = vEffectCenterRadius[3] = 0.0f;
|
||||
}
|
||||
|
||||
// Set the value either way
|
||||
pParams[i]->SetVecValue( vEffectCenterRadius, 4 );
|
||||
}
|
||||
|
||||
// Subsurface texture. NOTE: This texture bleeds through the color of the flesh texture so expect
|
||||
// to have to set this brighter than white to really see the subsurface texture glow through.
|
||||
if ( m_pMaterialParamFleshSubsurfaceTint != NULL )
|
||||
{
|
||||
float vSubsurfaceTintColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
// !!! Test code. REPLACE ME!
|
||||
// vSubsurfaceTintColor[0] = vSubsurfaceTintColor[1] = vSubsurfaceTintColor[2] = sinf( gpGlobals->curtime * 3.0f ) + 1.0f; // * 0.5f + 0.5f;
|
||||
|
||||
m_pMaterialParamFleshSubsurfaceTint->SetVecValue( vSubsurfaceTintColor, 4 );
|
||||
}
|
||||
}
|
||||
|
||||
IMaterial *CFleshInteriorMaterialProxy::GetMaterial()
|
||||
{
|
||||
if ( m_pMaterialParamFleshEffectCenterRadius1 == NULL)
|
||||
return NULL;
|
||||
|
||||
return m_pMaterialParamFleshEffectCenterRadius1->GetOwningMaterial();
|
||||
}
|
||||
|
||||
EXPOSE_INTERFACE( CFleshInteriorMaterialProxy, IMaterialProxy, "FleshInterior" IMATERIAL_PROXY_INTERFACE_VERSION );
|
||||
580
sp/src/game/client/game_controls/ClientScoreBoardDialog.cpp
Normal file
580
sp/src/game/client/game_controls/ClientScoreBoardDialog.cpp
Normal file
@@ -0,0 +1,580 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cdll_client_int.h>
|
||||
#include <cdll_util.h>
|
||||
#include <globalvars_base.h>
|
||||
#include <igameresources.h>
|
||||
#include "IGameUIFuncs.h" // for key bindings
|
||||
#include "inputsystem/iinputsystem.h"
|
||||
#include "clientscoreboarddialog.h"
|
||||
#include <voice_status.h>
|
||||
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui/IVGui.h>
|
||||
#include <vstdlib/IKeyValuesSystem.h>
|
||||
|
||||
#include <KeyValues.h>
|
||||
#include <vgui_controls/ImageList.h>
|
||||
#include <vgui_controls/Label.h>
|
||||
#include <vgui_controls/SectionedListPanel.h>
|
||||
|
||||
#include <game/client/iviewport.h>
|
||||
#include <igameresources.h>
|
||||
|
||||
#include "vgui_avatarimage.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
bool AvatarIndexLessFunc( const int &lhs, const int &rhs )
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CClientScoreBoardDialog::CClientScoreBoardDialog(IViewPort *pViewPort) : EditablePanel( NULL, PANEL_SCOREBOARD )
|
||||
{
|
||||
m_iPlayerIndexSymbol = KeyValuesSystem()->GetSymbolForString("playerIndex");
|
||||
m_nCloseKey = BUTTON_CODE_INVALID;
|
||||
|
||||
//memset(s_VoiceImage, 0x0, sizeof( s_VoiceImage ));
|
||||
TrackerImage = 0;
|
||||
m_pViewPort = pViewPort;
|
||||
|
||||
// initialize dialog
|
||||
SetProportional(true);
|
||||
SetKeyBoardInputEnabled(false);
|
||||
SetMouseInputEnabled(false);
|
||||
|
||||
// set the scheme before any child control is created
|
||||
SetScheme("ClientScheme");
|
||||
|
||||
m_pPlayerList = new SectionedListPanel(this, "PlayerList");
|
||||
m_pPlayerList->SetVerticalScrollbar(false);
|
||||
|
||||
LoadControlSettings("Resource/UI/ScoreBoard.res");
|
||||
m_iDesiredHeight = GetTall();
|
||||
m_pPlayerList->SetVisible( false ); // hide this until we load the images in applyschemesettings
|
||||
|
||||
m_HLTVSpectators = 0;
|
||||
m_ReplaySpectators = 0;
|
||||
|
||||
// update scoreboard instantly if on of these events occure
|
||||
ListenForGameEvent( "hltv_status" );
|
||||
ListenForGameEvent( "server_spawn" );
|
||||
|
||||
m_pImageList = NULL;
|
||||
|
||||
m_mapAvatarsToImageList.SetLessFunc( DefLessFunc( CSteamID ) );
|
||||
m_mapAvatarsToImageList.RemoveAll();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CClientScoreBoardDialog::~CClientScoreBoardDialog()
|
||||
{
|
||||
if ( NULL != m_pImageList )
|
||||
{
|
||||
delete m_pImageList;
|
||||
m_pImageList = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Call every frame
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::OnThink()
|
||||
{
|
||||
BaseClass::OnThink();
|
||||
|
||||
// NOTE: this is necessary because of the way input works.
|
||||
// If a key down message is sent to vgui, then it will get the key up message
|
||||
// Sometimes the scoreboard is activated by other vgui menus,
|
||||
// sometimes by console commands. In the case where it's activated by
|
||||
// other vgui menus, we lose the key up message because this panel
|
||||
// doesn't accept keyboard input. It *can't* accept keyboard input
|
||||
// because another feature of the dialog is that if it's triggered
|
||||
// from within the game, you should be able to still run around while
|
||||
// the scoreboard is up. That feature is impossible if this panel accepts input.
|
||||
// because if a vgui panel is up that accepts input, it prevents the engine from
|
||||
// receiving that input. So, I'm stuck with a polling solution.
|
||||
//
|
||||
// Close key is set to non-invalid when something other than a keybind
|
||||
// brings the scoreboard up, and it's set to invalid as soon as the
|
||||
// dialog becomes hidden.
|
||||
if ( m_nCloseKey != BUTTON_CODE_INVALID )
|
||||
{
|
||||
if ( !g_pInputSystem->IsButtonDown( m_nCloseKey ) )
|
||||
{
|
||||
m_nCloseKey = BUTTON_CODE_INVALID;
|
||||
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, false );
|
||||
GetClientVoiceMgr()->StopSquelchMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Called by vgui panels that activate the client scoreboard
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::OnPollHideCode( int code )
|
||||
{
|
||||
m_nCloseKey = (ButtonCode_t)code;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: clears everything in the scoreboard and all it's state
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::Reset()
|
||||
{
|
||||
// clear
|
||||
m_pPlayerList->DeleteAllItems();
|
||||
m_pPlayerList->RemoveAllSections();
|
||||
|
||||
m_iSectionId = 0;
|
||||
m_fNextUpdateTime = 0;
|
||||
// add all the sections
|
||||
InitScoreboardSections();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: adds all the team sections to the scoreboard
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::InitScoreboardSections()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets up screen
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::ApplySchemeSettings( IScheme *pScheme )
|
||||
{
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
|
||||
if ( m_pImageList )
|
||||
delete m_pImageList;
|
||||
m_pImageList = new ImageList( false );
|
||||
|
||||
m_mapAvatarsToImageList.RemoveAll();
|
||||
|
||||
PostApplySchemeSettings( pScheme );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Does dialog-specific customization after applying scheme settings.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::PostApplySchemeSettings( vgui::IScheme *pScheme )
|
||||
{
|
||||
// resize the images to our resolution
|
||||
for (int i = 0; i < m_pImageList->GetImageCount(); i++ )
|
||||
{
|
||||
int wide, tall;
|
||||
m_pImageList->GetImage(i)->GetSize(wide, tall);
|
||||
m_pImageList->GetImage(i)->SetSize(scheme()->GetProportionalScaledValueEx( GetScheme(),wide), scheme()->GetProportionalScaledValueEx( GetScheme(),tall));
|
||||
}
|
||||
|
||||
m_pPlayerList->SetImageList( m_pImageList, false );
|
||||
m_pPlayerList->SetVisible( true );
|
||||
|
||||
// light up scoreboard a bit
|
||||
SetBgColor( Color( 0,0,0,0) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::ShowPanel(bool bShow)
|
||||
{
|
||||
// Catch the case where we call ShowPanel before ApplySchemeSettings, eg when
|
||||
// going from windowed <-> fullscreen
|
||||
if ( m_pImageList == NULL )
|
||||
{
|
||||
InvalidateLayout( true, true );
|
||||
}
|
||||
|
||||
if ( !bShow )
|
||||
{
|
||||
m_nCloseKey = BUTTON_CODE_INVALID;
|
||||
}
|
||||
|
||||
if ( BaseClass::IsVisible() == bShow )
|
||||
return;
|
||||
|
||||
if ( bShow )
|
||||
{
|
||||
Reset();
|
||||
Update();
|
||||
SetVisible( true );
|
||||
MoveToFront();
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseClass::SetVisible( false );
|
||||
SetMouseInputEnabled( false );
|
||||
SetKeyBoardInputEnabled( false );
|
||||
}
|
||||
}
|
||||
|
||||
void CClientScoreBoardDialog::FireGameEvent( IGameEvent *event )
|
||||
{
|
||||
const char * type = event->GetName();
|
||||
|
||||
if ( Q_strcmp(type, "hltv_status") == 0 )
|
||||
{
|
||||
// spectators = clients - proxies
|
||||
m_HLTVSpectators = event->GetInt( "clients" );
|
||||
m_HLTVSpectators -= event->GetInt( "proxies" );
|
||||
}
|
||||
else if ( Q_strcmp(type, "server_spawn") == 0 )
|
||||
{
|
||||
// We'll post the message ourselves instead of using SetControlString()
|
||||
// so we don't try to translate the hostname.
|
||||
const char *hostname = event->GetString( "hostname" );
|
||||
Panel *control = FindChildByName( "ServerName" );
|
||||
if ( control )
|
||||
{
|
||||
PostMessage( control, new KeyValues( "SetText", "text", hostname ) );
|
||||
control->MoveToFront();
|
||||
}
|
||||
}
|
||||
|
||||
if( IsVisible() )
|
||||
Update();
|
||||
|
||||
}
|
||||
|
||||
bool CClientScoreBoardDialog::NeedsUpdate( void )
|
||||
{
|
||||
return (m_fNextUpdateTime < gpGlobals->curtime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Recalculate the internal scoreboard data
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::Update( void )
|
||||
{
|
||||
// Set the title
|
||||
|
||||
// Reset();
|
||||
m_pPlayerList->DeleteAllItems();
|
||||
|
||||
FillScoreBoard();
|
||||
|
||||
// grow the scoreboard to fit all the players
|
||||
int wide, tall;
|
||||
m_pPlayerList->GetContentSize(wide, tall);
|
||||
tall += GetAdditionalHeight();
|
||||
wide = GetWide();
|
||||
if (m_iDesiredHeight < tall)
|
||||
{
|
||||
SetSize(wide, tall);
|
||||
m_pPlayerList->SetSize(wide, tall);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSize(wide, m_iDesiredHeight);
|
||||
m_pPlayerList->SetSize(wide, m_iDesiredHeight);
|
||||
}
|
||||
|
||||
MoveToCenterOfScreen();
|
||||
|
||||
// update every second
|
||||
m_fNextUpdateTime = gpGlobals->curtime + 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sort all the teams
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::UpdateTeamInfo()
|
||||
{
|
||||
// TODO: work out a sorting algorithm for team display for TF2
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::UpdatePlayerInfo()
|
||||
{
|
||||
m_iSectionId = 0; // 0'th row is a header
|
||||
int selectedRow = -1;
|
||||
|
||||
// walk all the players and make sure they're in the scoreboard
|
||||
for ( int i = 1; i <= gpGlobals->maxClients; ++i )
|
||||
{
|
||||
IGameResources *gr = GameResources();
|
||||
|
||||
if ( gr && gr->IsConnected( i ) )
|
||||
{
|
||||
// add the player to the list
|
||||
KeyValues *playerData = new KeyValues("data");
|
||||
GetPlayerScoreInfo( i, playerData );
|
||||
UpdatePlayerAvatar( i, playerData );
|
||||
|
||||
const char *oldName = playerData->GetString("name","");
|
||||
char newName[MAX_PLAYER_NAME_LENGTH];
|
||||
|
||||
UTIL_MakeSafeName( oldName, newName, MAX_PLAYER_NAME_LENGTH );
|
||||
|
||||
playerData->SetString("name", newName);
|
||||
|
||||
int itemID = FindItemIDForPlayerIndex( i );
|
||||
int sectionID = gr->GetTeam( i );
|
||||
|
||||
if ( gr->IsLocalPlayer( i ) )
|
||||
{
|
||||
selectedRow = itemID;
|
||||
}
|
||||
if (itemID == -1)
|
||||
{
|
||||
// add a new row
|
||||
itemID = m_pPlayerList->AddItem( sectionID, playerData );
|
||||
}
|
||||
else
|
||||
{
|
||||
// modify the current row
|
||||
m_pPlayerList->ModifyItem( itemID, sectionID, playerData );
|
||||
}
|
||||
|
||||
// set the row color based on the players team
|
||||
m_pPlayerList->SetItemFgColor( itemID, gr->GetTeamColor( sectionID ) );
|
||||
|
||||
playerData->deleteThis();
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove the player
|
||||
int itemID = FindItemIDForPlayerIndex( i );
|
||||
if (itemID != -1)
|
||||
{
|
||||
m_pPlayerList->RemoveItem(itemID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( selectedRow != -1 )
|
||||
{
|
||||
m_pPlayerList->SetSelectedItem(selectedRow);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: adds the top header of the scoreboars
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::AddHeader()
|
||||
{
|
||||
// add the top header
|
||||
m_pPlayerList->AddSection(m_iSectionId, "");
|
||||
m_pPlayerList->SetSectionAlwaysVisible(m_iSectionId);
|
||||
m_pPlayerList->AddColumnToSection(m_iSectionId, "name", "#PlayerName", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),NAME_WIDTH) );
|
||||
m_pPlayerList->AddColumnToSection(m_iSectionId, "frags", "#PlayerScore", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),SCORE_WIDTH) );
|
||||
m_pPlayerList->AddColumnToSection(m_iSectionId, "deaths", "#PlayerDeath", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),DEATH_WIDTH) );
|
||||
m_pPlayerList->AddColumnToSection(m_iSectionId, "ping", "#PlayerPing", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),PING_WIDTH) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Adds a new section to the scoreboard (i.e the team header)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::AddSection(int teamType, int teamNumber)
|
||||
{
|
||||
if ( teamType == TYPE_TEAM )
|
||||
{
|
||||
IGameResources *gr = GameResources();
|
||||
|
||||
if ( !gr )
|
||||
return;
|
||||
|
||||
// setup the team name
|
||||
wchar_t *teamName = g_pVGuiLocalize->Find( gr->GetTeamName(teamNumber) );
|
||||
wchar_t name[64];
|
||||
wchar_t string1[1024];
|
||||
|
||||
if (!teamName)
|
||||
{
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode(gr->GetTeamName(teamNumber), name, sizeof(name));
|
||||
teamName = name;
|
||||
}
|
||||
|
||||
g_pVGuiLocalize->ConstructString( string1, sizeof( string1 ), g_pVGuiLocalize->Find("#Player"), 2, teamName );
|
||||
|
||||
m_pPlayerList->AddSection(m_iSectionId, "", StaticPlayerSortFunc);
|
||||
|
||||
// Avatars are always displayed at 32x32 regardless of resolution
|
||||
if ( ShowAvatars() )
|
||||
{
|
||||
m_pPlayerList->AddColumnToSection( m_iSectionId, "avatar", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, m_iAvatarWidth );
|
||||
}
|
||||
|
||||
m_pPlayerList->AddColumnToSection(m_iSectionId, "name", string1, 0, scheme()->GetProportionalScaledValueEx( GetScheme(),NAME_WIDTH) - m_iAvatarWidth );
|
||||
m_pPlayerList->AddColumnToSection(m_iSectionId, "frags", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),SCORE_WIDTH) );
|
||||
m_pPlayerList->AddColumnToSection(m_iSectionId, "deaths", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),DEATH_WIDTH) );
|
||||
m_pPlayerList->AddColumnToSection(m_iSectionId, "ping", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),PING_WIDTH) );
|
||||
}
|
||||
else if ( teamType == TYPE_SPECTATORS )
|
||||
{
|
||||
m_pPlayerList->AddSection(m_iSectionId, "");
|
||||
|
||||
// Avatars are always displayed at 32x32 regardless of resolution
|
||||
if ( ShowAvatars() )
|
||||
{
|
||||
m_pPlayerList->AddColumnToSection( m_iSectionId, "avatar", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, m_iAvatarWidth );
|
||||
}
|
||||
m_pPlayerList->AddColumnToSection(m_iSectionId, "name", "#Spectators", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),NAME_WIDTH) - m_iAvatarWidth );
|
||||
m_pPlayerList->AddColumnToSection(m_iSectionId, "frags", "", 0, scheme()->GetProportionalScaledValueEx( GetScheme(),SCORE_WIDTH) );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Used for sorting players
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CClientScoreBoardDialog::StaticPlayerSortFunc(vgui::SectionedListPanel *list, int itemID1, int itemID2)
|
||||
{
|
||||
KeyValues *it1 = list->GetItemData(itemID1);
|
||||
KeyValues *it2 = list->GetItemData(itemID2);
|
||||
Assert(it1 && it2);
|
||||
|
||||
// first compare frags
|
||||
int v1 = it1->GetInt("frags");
|
||||
int v2 = it2->GetInt("frags");
|
||||
if (v1 > v2)
|
||||
return true;
|
||||
else if (v1 < v2)
|
||||
return false;
|
||||
|
||||
// next compare deaths
|
||||
v1 = it1->GetInt("deaths");
|
||||
v2 = it2->GetInt("deaths");
|
||||
if (v1 > v2)
|
||||
return false;
|
||||
else if (v1 < v2)
|
||||
return true;
|
||||
|
||||
// the same, so compare itemID's (as a sentinel value to get deterministic sorts)
|
||||
return itemID1 < itemID2;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Adds a new row to the scoreboard, from the playerinfo structure
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CClientScoreBoardDialog::GetPlayerScoreInfo(int playerIndex, KeyValues *kv)
|
||||
{
|
||||
IGameResources *gr = GameResources();
|
||||
|
||||
if (!gr )
|
||||
return false;
|
||||
|
||||
kv->SetInt("deaths", gr->GetDeaths( playerIndex ) );
|
||||
kv->SetInt("frags", gr->GetFrags( playerIndex ) );
|
||||
kv->SetInt("ping", gr->GetPing( playerIndex ) ) ;
|
||||
kv->SetString("name", gr->GetPlayerName( playerIndex ) );
|
||||
kv->SetInt("playerIndex", playerIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::UpdatePlayerAvatar( int playerIndex, KeyValues *kv )
|
||||
{
|
||||
// Update their avatar
|
||||
if ( kv && ShowAvatars() && steamapicontext->SteamFriends() && steamapicontext->SteamUtils() )
|
||||
{
|
||||
player_info_t pi;
|
||||
if ( engine->GetPlayerInfo( playerIndex, &pi ) )
|
||||
{
|
||||
if ( pi.friendsID )
|
||||
{
|
||||
CSteamID steamIDForPlayer( pi.friendsID, 1, steamapicontext->SteamUtils()->GetConnectedUniverse(), k_EAccountTypeIndividual );
|
||||
|
||||
// See if we already have that avatar in our list
|
||||
int iMapIndex = m_mapAvatarsToImageList.Find( steamIDForPlayer );
|
||||
int iImageIndex;
|
||||
if ( iMapIndex == m_mapAvatarsToImageList.InvalidIndex() )
|
||||
{
|
||||
CAvatarImage *pImage = new CAvatarImage();
|
||||
pImage->SetAvatarSteamID( steamIDForPlayer );
|
||||
pImage->SetAvatarSize( 32, 32 ); // Deliberately non scaling
|
||||
iImageIndex = m_pImageList->AddImage( pImage );
|
||||
|
||||
m_mapAvatarsToImageList.Insert( steamIDForPlayer, iImageIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
iImageIndex = m_mapAvatarsToImageList[ iMapIndex ];
|
||||
}
|
||||
|
||||
kv->SetInt( "avatar", iImageIndex );
|
||||
|
||||
CAvatarImage *pAvIm = (CAvatarImage *)m_pImageList->GetImage( iImageIndex );
|
||||
pAvIm->UpdateFriendStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: reload the player list on the scoreboard
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::FillScoreBoard()
|
||||
{
|
||||
// update totals information
|
||||
UpdateTeamInfo();
|
||||
|
||||
// update player info
|
||||
UpdatePlayerInfo();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: searches for the player in the scoreboard
|
||||
//-----------------------------------------------------------------------------
|
||||
int CClientScoreBoardDialog::FindItemIDForPlayerIndex(int playerIndex)
|
||||
{
|
||||
for (int i = 0; i <= m_pPlayerList->GetHighestItemID(); i++)
|
||||
{
|
||||
if (m_pPlayerList->IsItemIDValid(i))
|
||||
{
|
||||
KeyValues *kv = m_pPlayerList->GetItemData(i);
|
||||
kv = kv->FindKey(m_iPlayerIndexSymbol);
|
||||
if (kv && kv->GetInt() == playerIndex)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the text of a control by name
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::MoveLabelToFront(const char *textEntryName)
|
||||
{
|
||||
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
|
||||
if (entry)
|
||||
{
|
||||
entry->MoveToFront();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Center the dialog on the screen. (vgui has this method on
|
||||
// Frame, but we're an EditablePanel, need to roll our own.)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClientScoreBoardDialog::MoveToCenterOfScreen()
|
||||
{
|
||||
int wx, wy, ww, wt;
|
||||
surface()->GetWorkspaceBounds(wx, wy, ww, wt);
|
||||
SetPos((ww - GetWide()) / 2, (wt - GetTall()) / 2);
|
||||
}
|
||||
68
sp/src/game/client/game_controls/IconPanel.cpp
Normal file
68
sp/src/game/client/game_controls/IconPanel.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "IconPanel.h"
|
||||
#include "KeyValues.h"
|
||||
|
||||
DECLARE_BUILD_FACTORY( CIconPanel );
|
||||
|
||||
CIconPanel::CIconPanel( vgui::Panel *parent, const char *name ) : vgui::Panel( parent, name )
|
||||
{
|
||||
m_szIcon[0] = '\0';
|
||||
m_icon = NULL;
|
||||
m_bScaleImage = false;
|
||||
}
|
||||
|
||||
void CIconPanel::ApplySettings( KeyValues *inResourceData )
|
||||
{
|
||||
Q_strncpy( m_szIcon, inResourceData->GetString( "icon", "" ), sizeof( m_szIcon ) );
|
||||
|
||||
m_icon = gHUD.GetIcon( m_szIcon );
|
||||
|
||||
m_bScaleImage = inResourceData->GetInt("scaleImage", 0);
|
||||
|
||||
BaseClass::ApplySettings( inResourceData );
|
||||
}
|
||||
|
||||
void CIconPanel::SetIcon( const char *szIcon )
|
||||
{
|
||||
Q_strncpy( m_szIcon, szIcon, sizeof(m_szIcon) );
|
||||
|
||||
m_icon = gHUD.GetIcon( m_szIcon );
|
||||
}
|
||||
|
||||
void CIconPanel::Paint()
|
||||
{
|
||||
BaseClass::Paint();
|
||||
|
||||
if ( m_icon )
|
||||
{
|
||||
int x, y, w, h;
|
||||
GetBounds( x, y, w, h );
|
||||
|
||||
if ( m_bScaleImage )
|
||||
{
|
||||
m_icon->DrawSelf( 0, 0, w, h, m_IconColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_icon->DrawSelf( 0, 0, m_IconColor );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CIconPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||||
{
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
|
||||
if ( m_szIcon[0] != '\0' )
|
||||
{
|
||||
m_icon = gHUD.GetIcon( m_szIcon );
|
||||
}
|
||||
|
||||
SetFgColor( pScheme->GetColor( "FgColor", Color( 255, 255, 255, 255 ) ) );
|
||||
}
|
||||
42
sp/src/game/client/game_controls/IconPanel.h
Normal file
42
sp/src/game/client/game_controls/IconPanel.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ICONPANEL_H
|
||||
#define ICONPANEL_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui_controls/Panel.h>
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
class CIconPanel : public vgui::Panel
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CIconPanel, vgui::Panel );
|
||||
|
||||
public:
|
||||
CIconPanel( vgui::Panel *parent, const char *name );
|
||||
|
||||
void Init( void );
|
||||
virtual void Paint();
|
||||
virtual void ApplySettings( KeyValues *inResourceData );
|
||||
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
|
||||
|
||||
void SetIcon( const char *szIcon );
|
||||
void SetIconColor( Color cColor ) { m_IconColor = cColor; }
|
||||
|
||||
private:
|
||||
CHudTexture *m_icon;
|
||||
char m_szIcon[128];
|
||||
|
||||
bool m_bScaleImage;
|
||||
|
||||
CPanelAnimationVar( Color, m_IconColor, "iconColor", "255 255 255 255" );
|
||||
};
|
||||
|
||||
#endif //ICONPANEL_H
|
||||
1340
sp/src/game/client/game_controls/MapOverview.cpp
Normal file
1340
sp/src/game/client/game_controls/MapOverview.cpp
Normal file
File diff suppressed because it is too large
Load Diff
137
sp/src/game/client/game_controls/NavProgress.cpp
Normal file
137
sp/src/game/client/game_controls/NavProgress.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "NavProgress.h"
|
||||
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <filesystem.h>
|
||||
#include <KeyValues.h>
|
||||
#include <convar.h>
|
||||
|
||||
#include <vgui_controls/Label.h>
|
||||
|
||||
#include <game/client/iviewport.h>
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
CNavProgress::CNavProgress( IViewPort *pViewPort ) : Frame( NULL, PANEL_NAV_PROGRESS )
|
||||
{
|
||||
// initialize dialog
|
||||
m_pViewPort = pViewPort;
|
||||
|
||||
// load the new scheme early!!
|
||||
SetScheme("ClientScheme");
|
||||
SetMoveable(false);
|
||||
SetSizeable(false);
|
||||
SetProportional(true);
|
||||
|
||||
// hide the system buttons
|
||||
SetTitleBarVisible( false );
|
||||
|
||||
m_pTitle = new Label( this, "TitleLabel", "" );
|
||||
m_pText = new Label( this, "TextLabel", "" );
|
||||
|
||||
m_pProgressBarBorder = new Panel( this, "ProgressBarBorder" );
|
||||
m_pProgressBar = new Panel( this, "ProgressBar" );
|
||||
m_pProgressBarSizer = new Panel( this, "ProgressBarSizer" );
|
||||
|
||||
LoadControlSettings("Resource/UI/NavProgress.res");
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
CNavProgress::~CNavProgress()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
void CNavProgress::ApplySchemeSettings(IScheme *pScheme)
|
||||
{
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
|
||||
SetPaintBackgroundType( 2 );
|
||||
|
||||
m_pProgressBarSizer->SetVisible( false );
|
||||
|
||||
m_pProgressBarBorder->SetBorder( pScheme->GetBorder( "ButtonDepressedBorder" ) );
|
||||
m_pProgressBarBorder->SetBgColor( Color( 0, 0, 0, 0 ) );
|
||||
|
||||
m_pProgressBar->SetBorder( pScheme->GetBorder( "ButtonBorder" ) );
|
||||
m_pProgressBar->SetBgColor( pScheme->GetColor( "ProgressBar.FgColor", Color( 0, 0, 0, 0 ) ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
void CNavProgress::PerformLayout()
|
||||
{
|
||||
BaseClass::PerformLayout();
|
||||
|
||||
if ( m_numTicks )
|
||||
{
|
||||
int w = m_pProgressBarSizer->GetWide();
|
||||
w = w * m_currentTick / m_numTicks;
|
||||
m_pProgressBar->SetWide( w );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
void CNavProgress::Init( const char *title, int numTicks, int startTick )
|
||||
{
|
||||
m_pText->SetText( title );
|
||||
|
||||
m_numTicks = MAX( 1, numTicks ); // non-zero, since we'll divide by this
|
||||
m_currentTick = MAX( 0, MIN( m_numTicks, startTick ) );
|
||||
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
void CNavProgress::SetData(KeyValues *data)
|
||||
{
|
||||
Init( data->GetString( "msg" ),
|
||||
data->GetInt( "total" ),
|
||||
data->GetInt( "current" ) );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
void CNavProgress::ShowPanel( bool bShow )
|
||||
{
|
||||
if ( BaseClass::IsVisible() == bShow )
|
||||
return;
|
||||
|
||||
m_pViewPort->ShowBackGround( bShow );
|
||||
|
||||
if ( bShow )
|
||||
{
|
||||
Activate();
|
||||
SetMouseInputEnabled( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetVisible( false );
|
||||
SetMouseInputEnabled( false );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
void CNavProgress::Reset( void )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
void CNavProgress::Update( void )
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
59
sp/src/game/client/game_controls/NavProgress.h
Normal file
59
sp/src/game/client/game_controls/NavProgress.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef NAVPROGRESS_H
|
||||
#define NAVPROGRESS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui_controls/Frame.h>
|
||||
#include <vgui_controls/ProgressBar.h>
|
||||
|
||||
#include <game/client/iviewport.h>
|
||||
|
||||
class CNavProgress : public vgui::Frame, public IViewPortPanel
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CNavProgress, vgui::Frame );
|
||||
|
||||
public:
|
||||
CNavProgress(IViewPort *pViewPort);
|
||||
virtual ~CNavProgress();
|
||||
|
||||
virtual const char *GetName( void ) { return PANEL_NAV_PROGRESS; }
|
||||
virtual void SetData(KeyValues *data);
|
||||
virtual void Reset();
|
||||
virtual void Update();
|
||||
virtual bool NeedsUpdate( void ) { return false; }
|
||||
virtual bool HasInputElements( void ) { return true; }
|
||||
virtual void ShowPanel( bool bShow );
|
||||
|
||||
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
|
||||
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
|
||||
virtual bool IsVisible() { return BaseClass::IsVisible(); }
|
||||
virtual void SetParent( vgui::VPANEL parent ) { BaseClass::SetParent( parent ); }
|
||||
|
||||
public:
|
||||
|
||||
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
|
||||
virtual void PerformLayout();
|
||||
void Init( const char *title, int numTicks, int currentTick );
|
||||
|
||||
protected:
|
||||
IViewPort *m_pViewPort;
|
||||
|
||||
int m_numTicks;
|
||||
int m_currentTick;
|
||||
|
||||
vgui::Label * m_pTitle;
|
||||
vgui::Label * m_pText;
|
||||
vgui::Panel * m_pProgressBarBorder;
|
||||
vgui::Panel * m_pProgressBar;
|
||||
vgui::Panel * m_pProgressBarSizer;
|
||||
};
|
||||
|
||||
#endif // NAVPROGRESS_H
|
||||
850
sp/src/game/client/game_controls/SpectatorGUI.cpp
Normal file
850
sp/src/game/client/game_controls/SpectatorGUI.cpp
Normal file
@@ -0,0 +1,850 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include <cdll_client_int.h>
|
||||
#include <globalvars_base.h>
|
||||
#include <cdll_util.h>
|
||||
#include <KeyValues.h>
|
||||
|
||||
#include "spectatorgui.h"
|
||||
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui/IPanel.h>
|
||||
#include <vgui_controls/ImageList.h>
|
||||
#include <vgui_controls/MenuItem.h>
|
||||
#include <vgui_controls/TextImage.h>
|
||||
|
||||
#include <stdio.h> // _snprintf define
|
||||
|
||||
#include <game/client/iviewport.h>
|
||||
#include "commandmenu.h"
|
||||
#include "hltvcamera.h"
|
||||
#if defined( REPLAY_ENABLED )
|
||||
#include "replay/replaycamera.h"
|
||||
#endif
|
||||
|
||||
#include <vgui_controls/TextEntry.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include <vgui_controls/ImagePanel.h>
|
||||
#include <vgui_controls/Menu.h>
|
||||
#include "IGameUIFuncs.h" // for key bindings
|
||||
#include <imapoverview.h>
|
||||
#include <shareddefs.h>
|
||||
#include <igameresources.h>
|
||||
|
||||
#ifdef TF_CLIENT_DLL
|
||||
#include "tf_gamerules.h"
|
||||
void AddSubKeyNamed( KeyValues *pKeys, const char *pszName );
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#ifndef _XBOX
|
||||
extern IGameUIFuncs *gameuifuncs; // for key binding details
|
||||
#endif
|
||||
|
||||
// void DuckMessage(const char *str); // from vgui_teamfortressviewport.cpp
|
||||
|
||||
ConVar spec_scoreboard( "spec_scoreboard", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE );
|
||||
|
||||
CSpectatorGUI *g_pSpectatorGUI = NULL;
|
||||
|
||||
|
||||
// NB disconnect between localization text and observer mode enums
|
||||
static const char *s_SpectatorModes[] =
|
||||
{
|
||||
"#Spec_Mode0", // OBS_MODE_NONE = 0,
|
||||
"#Spec_Mode1", // OBS_MODE_DEATHCAM,
|
||||
"", // OBS_MODE_FREEZECAM,
|
||||
"#Spec_Mode2", // OBS_MODE_FIXED,
|
||||
"#Spec_Mode3", // OBS_MODE_IN_EYE,
|
||||
"#Spec_Mode4", // OBS_MODE_CHASE,
|
||||
"#Spec_Mode5", // OBS_MODE_ROAMING,
|
||||
};
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
ConVar cl_spec_mode(
|
||||
"cl_spec_mode",
|
||||
"1",
|
||||
FCVAR_ARCHIVE | FCVAR_USERINFO | FCVAR_SERVER_CAN_EXECUTE,
|
||||
"spectator mode" );
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: left and right buttons pointing buttons
|
||||
//-----------------------------------------------------------------------------
|
||||
class CSpecButton : public Button
|
||||
{
|
||||
public:
|
||||
CSpecButton(Panel *parent, const char *panelName): Button(parent, panelName, "") {}
|
||||
|
||||
private:
|
||||
void ApplySchemeSettings(vgui::IScheme *pScheme)
|
||||
{
|
||||
Button::ApplySchemeSettings(pScheme);
|
||||
SetFont(pScheme->GetFont("Marlett", IsProportional()) );
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CSpectatorMenu::CSpectatorMenu( IViewPort *pViewPort ) : Frame( NULL, PANEL_SPECMENU )
|
||||
{
|
||||
m_iDuckKey = BUTTON_CODE_INVALID;
|
||||
|
||||
m_pViewPort = pViewPort;
|
||||
|
||||
SetMouseInputEnabled( true );
|
||||
SetKeyBoardInputEnabled( true );
|
||||
SetTitleBarVisible( false ); // don't draw a title bar
|
||||
SetMoveable( false );
|
||||
SetSizeable( false );
|
||||
SetProportional(true);
|
||||
|
||||
SetScheme("ClientScheme");
|
||||
|
||||
m_pPlayerList = new ComboBox(this, "playercombo", 10 , false);
|
||||
HFont hFallbackFont = scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultVerySmallFallBack", false );
|
||||
if ( INVALID_FONT != hFallbackFont )
|
||||
{
|
||||
m_pPlayerList->SetUseFallbackFont( true, hFallbackFont );
|
||||
}
|
||||
|
||||
m_pViewOptions = new ComboBox(this, "viewcombo", 10 , false );
|
||||
m_pConfigSettings = new ComboBox(this, "settingscombo", 10 , false );
|
||||
|
||||
m_pLeftButton = new CSpecButton( this, "specprev");
|
||||
m_pLeftButton->SetText("3");
|
||||
m_pRightButton = new CSpecButton( this, "specnext");
|
||||
m_pRightButton->SetText("4");
|
||||
|
||||
m_pPlayerList->SetText("");
|
||||
m_pViewOptions->SetText("#Spec_Modes");
|
||||
m_pConfigSettings->SetText("#Spec_Options");
|
||||
|
||||
m_pPlayerList->SetOpenDirection( Menu::UP );
|
||||
m_pViewOptions->SetOpenDirection( Menu::UP );
|
||||
m_pConfigSettings->SetOpenDirection( Menu::UP );
|
||||
|
||||
// create view config menu
|
||||
CommandMenu * menu = new CommandMenu(m_pConfigSettings, "spectatormenu", gViewPortInterface);
|
||||
menu->LoadFromFile( "Resource/spectatormenu.res" );
|
||||
m_pConfigSettings->SetMenu( menu ); // attach menu to combo box
|
||||
|
||||
// create view mode menu
|
||||
menu = new CommandMenu(m_pViewOptions, "spectatormodes", gViewPortInterface);
|
||||
menu->LoadFromFile("Resource/spectatormodes.res");
|
||||
m_pViewOptions->SetMenu( menu ); // attach menu to combo box
|
||||
|
||||
LoadControlSettings("Resource/UI/BottomSpectator.res");
|
||||
ListenForGameEvent( "spec_target_updated" );
|
||||
}
|
||||
|
||||
void CSpectatorMenu::ApplySchemeSettings(IScheme *pScheme)
|
||||
{
|
||||
BaseClass::ApplySchemeSettings(pScheme);
|
||||
// need to MakeReadyForUse() on the menus so we can set their bg color before they are displayed
|
||||
m_pConfigSettings->GetMenu()->MakeReadyForUse();
|
||||
m_pViewOptions->GetMenu()->MakeReadyForUse();
|
||||
m_pPlayerList->GetMenu()->MakeReadyForUse();
|
||||
|
||||
if ( g_pSpectatorGUI )
|
||||
{
|
||||
m_pConfigSettings->GetMenu()->SetBgColor( g_pSpectatorGUI->GetBlackBarColor() );
|
||||
m_pViewOptions->GetMenu()->SetBgColor( g_pSpectatorGUI->GetBlackBarColor() );
|
||||
m_pPlayerList->GetMenu()->SetBgColor( g_pSpectatorGUI->GetBlackBarColor() );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: makes the GUI fill the screen
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorMenu::PerformLayout()
|
||||
{
|
||||
int w,h;
|
||||
GetHudSize(w, h);
|
||||
|
||||
// fill the screen
|
||||
SetSize(w,GetTall());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handles changes to combo boxes
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorMenu::OnTextChanged(KeyValues *data)
|
||||
{
|
||||
Panel *panel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") );
|
||||
|
||||
vgui::ComboBox *box = dynamic_cast<vgui::ComboBox *>( panel );
|
||||
|
||||
if( box == m_pConfigSettings) // don't change the text in the config setting combo
|
||||
{
|
||||
m_pConfigSettings->SetText("#Spec_Options");
|
||||
}
|
||||
else if ( box == m_pPlayerList )
|
||||
{
|
||||
KeyValues *kv = box->GetActiveItemUserData();
|
||||
if ( kv && GameResources() )
|
||||
{
|
||||
const char *player = kv->GetString("player");
|
||||
|
||||
int currentPlayerNum = GetSpectatorTarget();
|
||||
const char *currentPlayerName = GameResources()->GetPlayerName( currentPlayerNum );
|
||||
|
||||
if ( !FStrEq( currentPlayerName, player ) )
|
||||
{
|
||||
char command[128];
|
||||
Q_snprintf( command, sizeof(command), "spec_player \"%s\"", player );
|
||||
engine->ClientCmd( command );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSpectatorMenu::OnCommand( const char *command )
|
||||
{
|
||||
if (!stricmp(command, "specnext") )
|
||||
{
|
||||
engine->ClientCmd("spec_next");
|
||||
}
|
||||
else if (!stricmp(command, "specprev") )
|
||||
{
|
||||
engine->ClientCmd("spec_prev");
|
||||
}
|
||||
}
|
||||
|
||||
void CSpectatorMenu::FireGameEvent( IGameEvent * event )
|
||||
{
|
||||
const char *pEventName = event->GetName();
|
||||
|
||||
if ( Q_strcmp( "spec_target_updated", pEventName ) == 0 )
|
||||
{
|
||||
IGameResources *gr = GameResources();
|
||||
if ( !gr )
|
||||
return;
|
||||
|
||||
// make sure the player combo box is up to date
|
||||
int playernum = GetSpectatorTarget();
|
||||
if ( playernum < 1 || playernum > MAX_PLAYERS )
|
||||
return;
|
||||
|
||||
const char *selectedPlayerName = gr->GetPlayerName( playernum );
|
||||
const char *currentPlayerName = "";
|
||||
KeyValues *kv = m_pPlayerList->GetActiveItemUserData();
|
||||
if ( kv )
|
||||
{
|
||||
currentPlayerName = kv->GetString( "player" );
|
||||
}
|
||||
if ( !FStrEq( currentPlayerName, selectedPlayerName ) )
|
||||
{
|
||||
for ( int i=0; i<m_pPlayerList->GetItemCount(); ++i )
|
||||
{
|
||||
KeyValues *kv = m_pPlayerList->GetItemUserData( i );
|
||||
if ( kv && FStrEq( kv->GetString( "player" ), selectedPlayerName ) )
|
||||
{
|
||||
m_pPlayerList->ActivateItemByRow( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: when duck is pressed it hides the active part of the GUI
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorMenu::OnKeyCodePressed(KeyCode code)
|
||||
{
|
||||
if ( code == m_iDuckKey )
|
||||
{
|
||||
// hide if DUCK is pressed again
|
||||
m_pViewPort->ShowPanel( this, false );
|
||||
}
|
||||
}
|
||||
|
||||
void CSpectatorMenu::ShowPanel(bool bShow)
|
||||
{
|
||||
if ( BaseClass::IsVisible() == bShow )
|
||||
return;
|
||||
|
||||
if ( bShow )
|
||||
{
|
||||
Activate();
|
||||
SetMouseInputEnabled( true );
|
||||
SetKeyBoardInputEnabled( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetVisible( false );
|
||||
SetMouseInputEnabled( false );
|
||||
SetKeyBoardInputEnabled( false );
|
||||
}
|
||||
|
||||
bool bIsEnabled = true;
|
||||
|
||||
if ( engine->IsHLTV() && HLTVCamera()->IsPVSLocked() )
|
||||
{
|
||||
// when watching HLTV or Replay with a locked PVS, some elements are disabled
|
||||
bIsEnabled = false;
|
||||
}
|
||||
|
||||
m_pLeftButton->SetVisible( bIsEnabled );
|
||||
m_pRightButton->SetVisible( bIsEnabled );
|
||||
m_pPlayerList->SetVisible( bIsEnabled );
|
||||
m_pViewOptions->SetVisible( bIsEnabled );
|
||||
}
|
||||
|
||||
void CSpectatorMenu::Update( void )
|
||||
{
|
||||
IGameResources *gr = GameResources();
|
||||
|
||||
Reset();
|
||||
|
||||
if ( m_iDuckKey == BUTTON_CODE_INVALID )
|
||||
{
|
||||
m_iDuckKey = gameuifuncs->GetButtonCodeForBind( "duck" );
|
||||
}
|
||||
|
||||
if ( !gr )
|
||||
return;
|
||||
|
||||
int iPlayerIndex;
|
||||
for ( iPlayerIndex = 1 ; iPlayerIndex <= gpGlobals->maxClients; iPlayerIndex++ )
|
||||
{
|
||||
|
||||
// does this slot in the array have a name?
|
||||
if ( !gr->IsConnected( iPlayerIndex ) )
|
||||
continue;
|
||||
|
||||
if ( gr->IsLocalPlayer( iPlayerIndex ) )
|
||||
continue;
|
||||
|
||||
if ( !gr->IsAlive( iPlayerIndex ) )
|
||||
continue;
|
||||
|
||||
wchar_t playerText[ 80 ], playerName[ 64 ], *team, teamText[ 64 ];
|
||||
char localizeTeamName[64];
|
||||
char szPlayerIndex[16];
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( UTIL_SafeName( gr->GetPlayerName(iPlayerIndex) ), playerName, sizeof( playerName ) );
|
||||
const char * teamname = gr->GetTeamName( gr->GetTeam(iPlayerIndex) );
|
||||
if ( teamname )
|
||||
{
|
||||
Q_snprintf( localizeTeamName, sizeof( localizeTeamName ), "#%s", teamname );
|
||||
team=g_pVGuiLocalize->Find( localizeTeamName );
|
||||
|
||||
if ( !team )
|
||||
{
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( teamname , teamText, sizeof( teamText ) );
|
||||
team = teamText;
|
||||
}
|
||||
|
||||
g_pVGuiLocalize->ConstructString( playerText, sizeof( playerText ), g_pVGuiLocalize->Find( "#Spec_PlayerItem_Team" ), 2, playerName, team );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pVGuiLocalize->ConstructString( playerText, sizeof( playerText ), g_pVGuiLocalize->Find( "#Spec_PlayerItem" ), 1, playerName );
|
||||
}
|
||||
|
||||
Q_snprintf( szPlayerIndex, sizeof( szPlayerIndex ), "%d", iPlayerIndex );
|
||||
|
||||
KeyValues *kv = new KeyValues( "UserData", "player", gr->GetPlayerName( iPlayerIndex ), "index", szPlayerIndex );
|
||||
m_pPlayerList->AddItem( playerText, kv );
|
||||
kv->deleteThis();
|
||||
}
|
||||
|
||||
// make sure the player combo box is up to date
|
||||
int playernum = GetSpectatorTarget();
|
||||
const char *selectedPlayerName = gr->GetPlayerName( playernum );
|
||||
for ( iPlayerIndex=0; iPlayerIndex<m_pPlayerList->GetItemCount(); ++iPlayerIndex )
|
||||
{
|
||||
KeyValues *kv = m_pPlayerList->GetItemUserData( iPlayerIndex );
|
||||
if ( kv && FStrEq( kv->GetString( "player" ), selectedPlayerName ) )
|
||||
{
|
||||
m_pPlayerList->ActivateItemByRow( iPlayerIndex );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// HPE_BEGIN:
|
||||
// [pfreese] make sure the view mode combo box is up to date - the spectator
|
||||
// mode can be changed multiple ways
|
||||
//=============================================================================
|
||||
|
||||
int specmode = GetSpectatorMode();
|
||||
m_pViewOptions->SetText(s_SpectatorModes[specmode]);
|
||||
|
||||
//=============================================================================
|
||||
// HPE_END
|
||||
//=============================================================================
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// main spectator panel
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CSpectatorGUI::CSpectatorGUI(IViewPort *pViewPort) : EditablePanel( NULL, PANEL_SPECGUI )
|
||||
{
|
||||
// m_bHelpShown = false;
|
||||
// m_bInsetVisible = false;
|
||||
// m_iDuckKey = KEY_NONE;
|
||||
SetSize( 10, 10 ); // Quiet "parent not sized yet" spew
|
||||
m_bSpecScoreboard = false;
|
||||
|
||||
m_pViewPort = pViewPort;
|
||||
g_pSpectatorGUI = this;
|
||||
|
||||
// initialize dialog
|
||||
SetVisible(false);
|
||||
SetProportional(true);
|
||||
|
||||
// load the new scheme early!!
|
||||
SetScheme("ClientScheme");
|
||||
SetMouseInputEnabled( false );
|
||||
SetKeyBoardInputEnabled( false );
|
||||
|
||||
m_pTopBar = new Panel( this, "topbar" );
|
||||
m_pBottomBarBlank = new Panel( this, "bottombarblank" );
|
||||
|
||||
// m_pBannerImage = new ImagePanel( m_pTopBar, NULL );
|
||||
m_pPlayerLabel = new Label( this, "playerlabel", "" );
|
||||
m_pPlayerLabel->SetVisible( false );
|
||||
TextImage *image = m_pPlayerLabel->GetTextImage();
|
||||
if ( image )
|
||||
{
|
||||
HFont hFallbackFont = scheme()->GetIScheme( GetScheme() )->GetFont( "DefaultVerySmallFallBack", false );
|
||||
if ( INVALID_FONT != hFallbackFont )
|
||||
{
|
||||
image->SetUseFallbackFont( true, hFallbackFont );
|
||||
}
|
||||
}
|
||||
|
||||
SetPaintBorderEnabled(false);
|
||||
SetPaintBackgroundEnabled(false);
|
||||
|
||||
// m_pBannerImage->SetVisible(false);
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CSpectatorGUI::~CSpectatorGUI()
|
||||
{
|
||||
g_pSpectatorGUI = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the colour of the top and bottom bars
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorGUI::ApplySchemeSettings(IScheme *pScheme)
|
||||
{
|
||||
KeyValues *pConditions = NULL;
|
||||
|
||||
#ifdef TF_CLIENT_DLL
|
||||
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
|
||||
{
|
||||
pConditions = new KeyValues( "conditions" );
|
||||
AddSubKeyNamed( pConditions, "if_mvm" );
|
||||
}
|
||||
#endif
|
||||
|
||||
LoadControlSettings( GetResFile(), NULL, NULL, pConditions );
|
||||
|
||||
if ( pConditions )
|
||||
{
|
||||
pConditions->deleteThis();
|
||||
}
|
||||
|
||||
m_pBottomBarBlank->SetVisible( true );
|
||||
m_pTopBar->SetVisible( true );
|
||||
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
SetBgColor(Color( 0,0,0,0 ) ); // make the background transparent
|
||||
m_pTopBar->SetBgColor(GetBlackBarColor());
|
||||
m_pBottomBarBlank->SetBgColor(GetBlackBarColor());
|
||||
// m_pBottomBar->SetBgColor(Color( 0,0,0,0 ));
|
||||
SetPaintBorderEnabled(false);
|
||||
|
||||
SetBorder( NULL );
|
||||
|
||||
#ifdef CSTRIKE_DLL
|
||||
SetZPos(80); // guarantee it shows above the scope
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: makes the GUI fill the screen
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorGUI::PerformLayout()
|
||||
{
|
||||
int w,h,x,y;
|
||||
GetHudSize(w, h);
|
||||
|
||||
// fill the screen
|
||||
SetBounds(0,0,w,h);
|
||||
|
||||
// stretch the bottom bar across the screen
|
||||
m_pBottomBarBlank->GetPos(x,y);
|
||||
m_pBottomBarBlank->SetSize( w, h - y );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks spec_scoreboard cvar to see if the scoreboard should be displayed
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorGUI::OnThink()
|
||||
{
|
||||
BaseClass::OnThink();
|
||||
|
||||
if ( IsVisible() )
|
||||
{
|
||||
if ( m_bSpecScoreboard != spec_scoreboard.GetBool() )
|
||||
{
|
||||
if ( !spec_scoreboard.GetBool() || !gViewPortInterface->GetActivePanel() )
|
||||
{
|
||||
m_bSpecScoreboard = spec_scoreboard.GetBool();
|
||||
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, m_bSpecScoreboard );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the image to display for the banner in the top right corner
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorGUI::SetLogoImage(const char *image)
|
||||
{
|
||||
if ( m_pBannerImage )
|
||||
{
|
||||
m_pBannerImage->SetImage( scheme()->GetImage(image, false) );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the text of a control by name
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorGUI::SetLabelText(const char *textEntryName, const char *text)
|
||||
{
|
||||
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
|
||||
if (entry)
|
||||
{
|
||||
entry->SetText(text);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the text of a control by name
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorGUI::SetLabelText(const char *textEntryName, wchar_t *text)
|
||||
{
|
||||
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
|
||||
if (entry)
|
||||
{
|
||||
entry->SetText(text);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the text of a control by name
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorGUI::MoveLabelToFront(const char *textEntryName)
|
||||
{
|
||||
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
|
||||
if (entry)
|
||||
{
|
||||
entry->MoveToFront();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: shows/hides the buy menu
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorGUI::ShowPanel(bool bShow)
|
||||
{
|
||||
if ( bShow && !IsVisible() )
|
||||
{
|
||||
m_bSpecScoreboard = false;
|
||||
}
|
||||
SetVisible( bShow );
|
||||
if ( !bShow && m_bSpecScoreboard )
|
||||
{
|
||||
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, false );
|
||||
}
|
||||
}
|
||||
|
||||
bool CSpectatorGUI::ShouldShowPlayerLabel( int specmode )
|
||||
{
|
||||
return ( (specmode == OBS_MODE_IN_EYE) || (specmode == OBS_MODE_CHASE) );
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Updates the gui, rearranges elements
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorGUI::Update()
|
||||
{
|
||||
int wide, tall;
|
||||
int bx, by, bwide, btall;
|
||||
|
||||
GetHudSize(wide, tall);
|
||||
m_pTopBar->GetBounds( bx, by, bwide, btall );
|
||||
|
||||
IGameResources *gr = GameResources();
|
||||
int specmode = GetSpectatorMode();
|
||||
int playernum = GetSpectatorTarget();
|
||||
|
||||
IViewPortPanel *overview = gViewPortInterface->FindPanelByName( PANEL_OVERVIEW );
|
||||
|
||||
if ( overview && overview->IsVisible() )
|
||||
{
|
||||
int mx, my, mwide, mtall;
|
||||
|
||||
VPANEL p = overview->GetVPanel();
|
||||
vgui::ipanel()->GetPos( p, mx, my );
|
||||
vgui::ipanel()->GetSize( p, mwide, mtall );
|
||||
|
||||
if ( my < btall )
|
||||
{
|
||||
// reduce to bar
|
||||
m_pTopBar->SetSize( wide - (mx + mwide), btall );
|
||||
m_pTopBar->SetPos( (mx + mwide), 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// full top bar
|
||||
m_pTopBar->SetSize( wide , btall );
|
||||
m_pTopBar->SetPos( 0, 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// full top bar
|
||||
m_pTopBar->SetSize( wide , btall ); // change width, keep height
|
||||
m_pTopBar->SetPos( 0, 0 );
|
||||
}
|
||||
|
||||
m_pPlayerLabel->SetVisible( ShouldShowPlayerLabel(specmode) );
|
||||
|
||||
// update player name filed, text & color
|
||||
|
||||
if ( playernum > 0 && playernum <= gpGlobals->maxClients && gr )
|
||||
{
|
||||
Color c = gr->GetTeamColor( gr->GetTeam(playernum) ); // Player's team color
|
||||
|
||||
m_pPlayerLabel->SetFgColor( c );
|
||||
|
||||
wchar_t playerText[ 80 ], playerName[ 64 ], health[ 10 ];
|
||||
V_wcsncpy( playerText, L"Unable to find #Spec_PlayerItem*", sizeof( playerText ) );
|
||||
memset( playerName, 0x0, sizeof( playerName ) );
|
||||
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( UTIL_SafeName(gr->GetPlayerName( playernum )), playerName, sizeof( playerName ) );
|
||||
int iHealth = gr->GetHealth( playernum );
|
||||
if ( iHealth > 0 && gr->IsAlive(playernum) )
|
||||
{
|
||||
_snwprintf( health, ARRAYSIZE( health ), L"%i", iHealth );
|
||||
g_pVGuiLocalize->ConstructString( playerText, sizeof( playerText ), g_pVGuiLocalize->Find( "#Spec_PlayerItem_Team" ), 2, playerName, health );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pVGuiLocalize->ConstructString( playerText, sizeof( playerText ), g_pVGuiLocalize->Find( "#Spec_PlayerItem" ), 1, playerName );
|
||||
}
|
||||
|
||||
m_pPlayerLabel->SetText( playerText );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pPlayerLabel->SetText( L"" );
|
||||
}
|
||||
|
||||
// update extra info field
|
||||
wchar_t szEtxraInfo[1024];
|
||||
wchar_t szTitleLabel[1024];
|
||||
char tempstr[128];
|
||||
|
||||
if ( engine->IsHLTV() )
|
||||
{
|
||||
// set spectator number and HLTV title
|
||||
Q_snprintf(tempstr,sizeof(tempstr),"Spectators : %d", HLTVCamera()->GetNumSpectators() );
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode(tempstr,szEtxraInfo,sizeof(szEtxraInfo));
|
||||
|
||||
Q_strncpy( tempstr, HLTVCamera()->GetTitleText(), sizeof(tempstr) );
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode(tempstr,szTitleLabel,sizeof(szTitleLabel));
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise show map name
|
||||
Q_FileBase( engine->GetLevelName(), tempstr, sizeof(tempstr) );
|
||||
|
||||
wchar_t wMapName[64];
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode(tempstr,wMapName,sizeof(wMapName));
|
||||
g_pVGuiLocalize->ConstructString( szEtxraInfo,sizeof( szEtxraInfo ), g_pVGuiLocalize->Find("#Spec_Map" ),1, wMapName );
|
||||
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( "" ,szTitleLabel,sizeof(szTitleLabel));
|
||||
}
|
||||
|
||||
SetLabelText("extrainfo", szEtxraInfo );
|
||||
SetLabelText("titlelabel", szTitleLabel );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Updates the timer label if one exists
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSpectatorGUI::UpdateTimer()
|
||||
{
|
||||
wchar_t szText[ 63 ];
|
||||
|
||||
int timer = 0;
|
||||
|
||||
V_swprintf_safe ( szText, L"%d:%02d\n", (timer / 60), (timer % 60) );
|
||||
|
||||
SetLabelText("timerlabel", szText );
|
||||
}
|
||||
|
||||
static void ForwardSpecCmdToServer( const CCommand &args )
|
||||
{
|
||||
if ( engine->IsPlayingDemo() )
|
||||
return;
|
||||
|
||||
if ( args.ArgC() == 1 )
|
||||
{
|
||||
// just forward the command without parameters
|
||||
engine->ServerCmd( args[ 0 ] );
|
||||
}
|
||||
else if ( args.ArgC() == 2 )
|
||||
{
|
||||
// forward the command with parameter
|
||||
char command[128];
|
||||
Q_snprintf( command, sizeof(command), "%s \"%s\"", args[ 0 ], args[ 1 ] );
|
||||
engine->ServerCmd( command );
|
||||
}
|
||||
}
|
||||
|
||||
CON_COMMAND_F( spec_next, "Spectate next player", FCVAR_CLIENTCMD_CAN_EXECUTE )
|
||||
{
|
||||
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
|
||||
|
||||
if ( !pPlayer || !pPlayer->IsObserver() )
|
||||
return;
|
||||
|
||||
if ( engine->IsHLTV() )
|
||||
{
|
||||
// handle the command clientside
|
||||
if ( !HLTVCamera()->IsPVSLocked() )
|
||||
{
|
||||
HLTVCamera()->SpecNextPlayer( false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ForwardSpecCmdToServer( args );
|
||||
}
|
||||
}
|
||||
|
||||
CON_COMMAND_F( spec_prev, "Spectate previous player", FCVAR_CLIENTCMD_CAN_EXECUTE )
|
||||
{
|
||||
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
|
||||
|
||||
if ( !pPlayer || !pPlayer->IsObserver() )
|
||||
return;
|
||||
|
||||
if ( engine->IsHLTV() )
|
||||
{
|
||||
// handle the command clientside
|
||||
if ( !HLTVCamera()->IsPVSLocked() )
|
||||
{
|
||||
HLTVCamera()->SpecNextPlayer( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ForwardSpecCmdToServer( args );
|
||||
}
|
||||
}
|
||||
|
||||
CON_COMMAND_F( spec_mode, "Set spectator mode", FCVAR_CLIENTCMD_CAN_EXECUTE )
|
||||
{
|
||||
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
|
||||
|
||||
if ( !pPlayer || !pPlayer->IsObserver() )
|
||||
return;
|
||||
|
||||
if ( engine->IsHLTV() )
|
||||
{
|
||||
if ( HLTVCamera()->IsPVSLocked() )
|
||||
{
|
||||
// in locked mode we can only switch between first and 3rd person
|
||||
HLTVCamera()->ToggleChaseAsFirstPerson();
|
||||
}
|
||||
else
|
||||
{
|
||||
// we can choose any mode, not loked to PVS
|
||||
int mode;
|
||||
|
||||
if ( args.ArgC() == 2 )
|
||||
{
|
||||
// set specifc mode
|
||||
mode = Q_atoi( args[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
// set next mode
|
||||
mode = HLTVCamera()->GetMode()+1;
|
||||
|
||||
if ( mode > LAST_PLAYER_OBSERVERMODE )
|
||||
mode = OBS_MODE_IN_EYE;
|
||||
}
|
||||
|
||||
// handle the command clientside
|
||||
HLTVCamera()->SetMode( mode );
|
||||
}
|
||||
|
||||
// turn off auto director once user tried to change view settings
|
||||
HLTVCamera()->SetAutoDirector( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
// we spectate on a game server, forward command
|
||||
ForwardSpecCmdToServer( args );
|
||||
}
|
||||
}
|
||||
|
||||
CON_COMMAND_F( spec_player, "Spectate player by name", FCVAR_CLIENTCMD_CAN_EXECUTE )
|
||||
{
|
||||
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
|
||||
|
||||
if ( !pPlayer || !pPlayer->IsObserver() )
|
||||
return;
|
||||
|
||||
if ( args.ArgC() != 2 )
|
||||
return;
|
||||
|
||||
if ( engine->IsHLTV() )
|
||||
{
|
||||
// we can only switch primary spectator targets is PVS isnt locked by auto-director
|
||||
if ( !HLTVCamera()->IsPVSLocked() )
|
||||
{
|
||||
HLTVCamera()->SpecNamedPlayer( args[1] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ForwardSpecCmdToServer( args );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
653
sp/src/game/client/game_controls/basemodel_panel.cpp
Normal file
653
sp/src/game/client/game_controls/basemodel_panel.cpp
Normal file
@@ -0,0 +1,653 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "basemodel_panel.h"
|
||||
#include "activitylist.h"
|
||||
#include "animation.h"
|
||||
#include "vgui/IInput.h"
|
||||
#include "matsys_controls/manipulator.h"
|
||||
|
||||
using namespace vgui;
|
||||
DECLARE_BUILD_FACTORY( CBaseModelPanel );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseModelPanel::CBaseModelPanel( vgui::Panel *pParent, const char *pName ): BaseClass( pParent, pName )
|
||||
{
|
||||
m_bForcePos = false;
|
||||
m_bMousePressed = false;
|
||||
m_bAllowRotation = false;
|
||||
m_bAllowFullManipulation = false;
|
||||
m_bApplyManipulators = false;
|
||||
m_bForcedCameraPosition = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseModelPanel::~CBaseModelPanel()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Load in the model portion of the panel's resource file.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::ApplySettings( KeyValues *inResourceData )
|
||||
{
|
||||
BaseClass::ApplySettings( inResourceData );
|
||||
|
||||
// Set whether we render to texture
|
||||
m_bRenderToTexture = inResourceData->GetBool( "render_texture", true );
|
||||
|
||||
// Grab and set the camera FOV.
|
||||
float flFOV = GetCameraFOV();
|
||||
m_BMPResData.m_flFOV = inResourceData->GetInt( "fov", flFOV );
|
||||
SetCameraFOV( m_BMPResData.m_flFOV );
|
||||
|
||||
// Do we allow rotation on these panels.
|
||||
m_bAllowRotation = inResourceData->GetBool( "allow_rot", false );
|
||||
|
||||
// Do we allow full manipulation on these panels.
|
||||
m_bAllowFullManipulation = inResourceData->GetBool( "allow_manip", false );
|
||||
|
||||
// Parse our resource file and apply all necessary updates to the MDL.
|
||||
for ( KeyValues *pData = inResourceData->GetFirstSubKey() ; pData != NULL ; pData = pData->GetNextKey() )
|
||||
{
|
||||
if ( !Q_stricmp( pData->GetName(), "model" ) )
|
||||
{
|
||||
ParseModelResInfo( pData );
|
||||
}
|
||||
}
|
||||
|
||||
SetMouseInputEnabled( m_bAllowFullManipulation || m_bAllowRotation );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::ParseModelResInfo( KeyValues *inResourceData )
|
||||
{
|
||||
m_bForcePos = ( inResourceData->GetInt( "force_pos", 0 ) == 1 );
|
||||
m_BMPResData.m_pszModelName = ReadAndAllocStringValue( inResourceData, "modelname" );
|
||||
m_BMPResData.m_pszModelName_HWM = ReadAndAllocStringValue( inResourceData, "modelname_hwm" );
|
||||
m_BMPResData.m_pszVCD = ReadAndAllocStringValue( inResourceData, "vcd" );
|
||||
m_BMPResData.m_angModelPoseRot.Init( inResourceData->GetFloat( "angles_x", 0.0f ), inResourceData->GetFloat( "angles_y", 0.0f ), inResourceData->GetFloat( "angles_z", 0.0f ) );
|
||||
m_BMPResData.m_vecOriginOffset.Init( inResourceData->GetFloat( "origin_x", 110.0 ), inResourceData->GetFloat( "origin_y", 5.0 ), inResourceData->GetFloat( "origin_z", 5.0 ) );
|
||||
m_BMPResData.m_vecFramedOriginOffset.Init( inResourceData->GetFloat( "frame_origin_x", 110.0 ), inResourceData->GetFloat( "frame_origin_y", 5.0 ), inResourceData->GetFloat( "frame_origin_z", 5.0 ) );
|
||||
m_BMPResData.m_vecViewportOffset.Init();
|
||||
m_BMPResData.m_nSkin = inResourceData->GetInt( "skin", -1 );
|
||||
m_BMPResData.m_bUseSpotlight = ( inResourceData->GetInt( "spotlight", 0 ) == 1 );
|
||||
|
||||
m_angPlayer = m_BMPResData.m_angModelPoseRot;
|
||||
m_vecPlayerPos = m_BMPResData.m_vecOriginOffset;
|
||||
|
||||
for ( KeyValues *pData = inResourceData->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
|
||||
{
|
||||
if ( !Q_stricmp( pData->GetName(), "animation" ) )
|
||||
{
|
||||
ParseModelAnimInfo( pData );
|
||||
}
|
||||
else if ( !Q_stricmp( pData->GetName(), "attached_model" ) )
|
||||
{
|
||||
ParseModelAttachInfo( pData );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::ParseModelAnimInfo( KeyValues *inResourceData )
|
||||
{
|
||||
if ( !inResourceData )
|
||||
return;
|
||||
|
||||
int iAnim = m_BMPResData.m_aAnimations.AddToTail();
|
||||
if ( iAnim == m_BMPResData.m_aAnimations.InvalidIndex() )
|
||||
return;
|
||||
|
||||
m_BMPResData.m_aAnimations[iAnim].m_pszName = ReadAndAllocStringValue( inResourceData, "name" );
|
||||
m_BMPResData.m_aAnimations[iAnim].m_pszSequence = ReadAndAllocStringValue( inResourceData, "sequence" );
|
||||
m_BMPResData.m_aAnimations[iAnim].m_pszActivity = ReadAndAllocStringValue( inResourceData, "activity" );
|
||||
m_BMPResData.m_aAnimations[iAnim].m_bDefault = ( inResourceData->GetInt( "default", 0 ) == 1 );
|
||||
|
||||
for ( KeyValues *pAnimData = inResourceData->GetFirstSubKey(); pAnimData != NULL; pAnimData = pAnimData->GetNextKey() )
|
||||
{
|
||||
if ( !Q_stricmp( pAnimData->GetName(), "pose_parameters" ) )
|
||||
{
|
||||
m_BMPResData.m_aAnimations[iAnim].m_pPoseParameters = pAnimData->MakeCopy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::ParseModelAttachInfo( KeyValues *inResourceData )
|
||||
{
|
||||
if ( !inResourceData )
|
||||
return;
|
||||
|
||||
int iAttach = m_BMPResData.m_aAttachModels.AddToTail();
|
||||
if ( iAttach == m_BMPResData.m_aAttachModels.InvalidIndex() )
|
||||
return;
|
||||
|
||||
m_BMPResData.m_aAttachModels[iAttach].m_pszModelName = ReadAndAllocStringValue( inResourceData, "modelname" );
|
||||
m_BMPResData.m_aAttachModels[iAttach].m_nSkin = inResourceData->GetInt( "skin", -1 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::SetupModelDefaults( void )
|
||||
{
|
||||
SetupModelAnimDefaults();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::SetupModelAnimDefaults( void )
|
||||
{
|
||||
// Set the move_x parameter so the run activity works
|
||||
SetPoseParameterByName( "move_x", 1.0f );
|
||||
|
||||
// Verify that we have animations for this model.
|
||||
int nAnimCount = m_BMPResData.m_aAnimations.Count();
|
||||
if ( nAnimCount == 0 )
|
||||
return;
|
||||
|
||||
// Find the default animation if one exists.
|
||||
int iIndex = FindDefaultAnim();
|
||||
if ( iIndex == -1 )
|
||||
return;
|
||||
|
||||
SetModelAnim( iIndex );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseModelPanel::FindDefaultAnim( void )
|
||||
{
|
||||
int iIndex = -1;
|
||||
|
||||
int nAnimCount = m_BMPResData.m_aAnimations.Count();
|
||||
for ( int iAnim = 0; iAnim < nAnimCount; ++iAnim )
|
||||
{
|
||||
if ( m_BMPResData.m_aAnimations[iAnim].m_bDefault )
|
||||
return iAnim;
|
||||
}
|
||||
|
||||
return iIndex;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseModelPanel::FindAnimByName( const char *pszName )
|
||||
{
|
||||
int iIndex = -1;
|
||||
if ( !pszName )
|
||||
return iIndex;
|
||||
|
||||
int nAnimCount = m_BMPResData.m_aAnimations.Count();
|
||||
for ( int iAnim = 0; iAnim < nAnimCount; ++iAnim )
|
||||
{
|
||||
if ( !Q_stricmp( m_BMPResData.m_aAnimations[iAnim].m_pszName, pszName ) )
|
||||
return iAnim;
|
||||
}
|
||||
|
||||
return iIndex;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseModelPanel::FindSequenceFromActivity( CStudioHdr *pStudioHdr, const char *pszActivity )
|
||||
{
|
||||
if ( !pStudioHdr )
|
||||
return -1;
|
||||
|
||||
for ( int iSeq = 0; iSeq < pStudioHdr->GetNumSeq(); ++iSeq )
|
||||
{
|
||||
mstudioseqdesc_t &seqDesc = pStudioHdr->pSeqdesc( iSeq );
|
||||
if ( !V_stricmp( seqDesc.pszActivityName(), pszActivity ) )
|
||||
{
|
||||
return iSeq;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::SetModelAnim( int iAnim )
|
||||
{
|
||||
int nAnimCount = m_BMPResData.m_aAnimations.Count();
|
||||
if ( nAnimCount == 0 || !m_BMPResData.m_aAnimations.IsValidIndex( iAnim ) )
|
||||
return;
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
// Get the studio header of the root model.
|
||||
studiohdr_t *pStudioHdr = m_RootMDL.m_MDL.GetStudioHdr();
|
||||
if ( !pStudioHdr )
|
||||
return;
|
||||
|
||||
CStudioHdr studioHdr( pStudioHdr, g_pMDLCache );
|
||||
|
||||
// Do we have an activity or a sequence?
|
||||
int iSequence = ACT_INVALID;
|
||||
if ( m_BMPResData.m_aAnimations[iAnim].m_pszActivity && m_BMPResData.m_aAnimations[iAnim].m_pszActivity[0] )
|
||||
{
|
||||
iSequence = FindSequenceFromActivity( &studioHdr, m_BMPResData.m_aAnimations[iAnim].m_pszActivity );
|
||||
}
|
||||
else if ( m_BMPResData.m_aAnimations[iAnim].m_pszSequence && m_BMPResData.m_aAnimations[iAnim].m_pszSequence[0] )
|
||||
{
|
||||
iSequence = LookupSequence( &studioHdr, m_BMPResData.m_aAnimations[iAnim].m_pszSequence );
|
||||
}
|
||||
|
||||
if ( iSequence != ACT_INVALID )
|
||||
{
|
||||
SetSequence( iSequence );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::SetMDL( MDLHandle_t handle, void *pProxyData )
|
||||
{
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
studiohdr_t *pHdr = g_pMDLCache->GetStudioHdr( handle );
|
||||
|
||||
if ( pHdr )
|
||||
{
|
||||
// SetMDL will cause the base CMdl code to set our localtoglobal indices if they aren't set.
|
||||
// We set them up here so that they're left alone by that code.
|
||||
CStudioHdr studioHdr( pHdr, g_pMDLCache );
|
||||
if (studioHdr.numflexcontrollers() > 0 && studioHdr.pFlexcontroller( LocalFlexController_t(0) )->localToGlobal == -1)
|
||||
{
|
||||
for (LocalFlexController_t i = LocalFlexController_t(0); i < studioHdr.numflexcontrollers(); i++)
|
||||
{
|
||||
int j = C_BaseFlex::AddGlobalFlexController( studioHdr.pFlexcontroller( i )->pszName() );
|
||||
studioHdr.pFlexcontroller( i )->localToGlobal = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handle = MDLHANDLE_INVALID;
|
||||
}
|
||||
|
||||
// Clear our current sequence
|
||||
SetSequence( ACT_IDLE );
|
||||
|
||||
BaseClass::SetMDL( handle, pProxyData );
|
||||
|
||||
SetupModelDefaults();
|
||||
|
||||
// Need to invalidate the layout so the panel will adjust is LookAt for the new model.
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::SetModelAnglesAndPosition( const QAngle &angRot, const Vector &vecPos )
|
||||
{
|
||||
BaseClass::SetModelAnglesAndPosition( angRot, vecPos );
|
||||
|
||||
// Cache
|
||||
m_vecPlayerPos = vecPos;
|
||||
m_angPlayer = angRot;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::SetMDL( const char *pMDLName, void *pProxyData )
|
||||
{
|
||||
BaseClass::SetMDL( pMDLName, pProxyData );
|
||||
|
||||
// Need to invalidate the layout so the panel will adjust is LookAt for the new model.
|
||||
// InvalidateLayout();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::PerformLayout()
|
||||
{
|
||||
BaseClass::PerformLayout();
|
||||
|
||||
if ( m_bForcedCameraPosition )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_bAllowFullManipulation )
|
||||
{
|
||||
// Set this to true if you want to keep the current rotation when changing models or poses
|
||||
const bool bPreserveManipulation = false;
|
||||
|
||||
// Need to look at the target so we can rotate around it
|
||||
const Vector kVecFocalPoint( 0.0f, 0.0f, 60.0f );
|
||||
ResetCameraPivot();
|
||||
SetCameraOffset( -(m_vecPlayerPos + kVecFocalPoint) );
|
||||
SetCameraPositionAndAngles( kVecFocalPoint, vec3_angle, !bPreserveManipulation );
|
||||
|
||||
// We want to move the player to the origin and facing the correct way,
|
||||
// but don't clobber m_angPlayer and m_vecPlayerPos, so use BaseClass.
|
||||
BaseClass::SetModelAnglesAndPosition( m_angPlayer, vec3_origin );
|
||||
|
||||
// Once a manual transform has been done we want to apply it
|
||||
if ( m_bApplyManipulators )
|
||||
{
|
||||
ApplyManipulation();
|
||||
}
|
||||
else
|
||||
{
|
||||
SyncManipulation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_bForcePos )
|
||||
{
|
||||
ResetCameraPivot();
|
||||
SetCameraOffset( Vector( 0.0f, 0.0f, 0.0f ) );
|
||||
SetCameraPositionAndAngles( vec3_origin, vec3_angle );
|
||||
SetModelAnglesAndPosition( m_angPlayer, m_vecPlayerPos );
|
||||
}
|
||||
|
||||
// Center and fill the frame with the model?
|
||||
if ( m_bStartFramed )
|
||||
{
|
||||
Vector vecBoundsMin, vecBoundsMax;
|
||||
if ( GetBoundingBox( vecBoundsMin, vecBoundsMax ) )
|
||||
{
|
||||
LookAtBounds( vecBoundsMin, vecBoundsMax );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::OnKeyCodePressed ( vgui::KeyCode code )
|
||||
{
|
||||
if ( m_bAllowFullManipulation )
|
||||
{
|
||||
BaseClass::OnKeyCodePressed( code );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::OnKeyCodeReleased( vgui::KeyCode code )
|
||||
{
|
||||
if ( m_bAllowFullManipulation )
|
||||
{
|
||||
BaseClass::OnKeyCodeReleased( code );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::OnMousePressed ( vgui::MouseCode code )
|
||||
{
|
||||
if ( m_bAllowFullManipulation )
|
||||
{
|
||||
BaseClass::OnMousePressed( code );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !m_bAllowRotation )
|
||||
return;
|
||||
|
||||
RequestFocus();
|
||||
|
||||
EnableMouseCapture( true, code );
|
||||
|
||||
// Warp the mouse to the center of the screen
|
||||
int width, height;
|
||||
GetSize( width, height );
|
||||
int x = width / 2;
|
||||
int y = height / 2;
|
||||
|
||||
int xpos = x;
|
||||
int ypos = y;
|
||||
LocalToScreen( xpos, ypos );
|
||||
input()->SetCursorPos( xpos, ypos );
|
||||
|
||||
m_nManipStartX = xpos;
|
||||
m_nManipStartY = ypos;
|
||||
|
||||
m_bMousePressed = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::OnMouseReleased( vgui::MouseCode code )
|
||||
{
|
||||
if ( m_bAllowFullManipulation )
|
||||
{
|
||||
BaseClass::OnMouseReleased( code );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !m_bAllowRotation )
|
||||
return;
|
||||
|
||||
EnableMouseCapture( false );
|
||||
m_bMousePressed = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::OnCursorMoved( int x, int y )
|
||||
{
|
||||
if ( m_bAllowFullManipulation )
|
||||
{
|
||||
if ( m_pCurrentManip )
|
||||
{
|
||||
m_bApplyManipulators = true;
|
||||
}
|
||||
BaseClass::OnCursorMoved( x, y );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !m_bAllowRotation )
|
||||
return;
|
||||
|
||||
if ( m_bMousePressed )
|
||||
{
|
||||
WarpMouse( x, y );
|
||||
int xpos, ypos;
|
||||
input()->GetCursorPos( xpos, ypos );
|
||||
|
||||
// Only want the x delta.
|
||||
float flDelta = xpos - m_nManipStartX;
|
||||
|
||||
// Apply the delta and rotate the player.
|
||||
RotateYaw( flDelta );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::RotateYaw( float flDelta )
|
||||
{
|
||||
m_angPlayer.y += flDelta;
|
||||
if ( m_angPlayer.y > 360.0f )
|
||||
{
|
||||
m_angPlayer.y = m_angPlayer.y - 360.0f;
|
||||
}
|
||||
else if ( m_angPlayer.y < -360.0f )
|
||||
{
|
||||
m_angPlayer.y = m_angPlayer.y + 360.0f;
|
||||
}
|
||||
|
||||
SetModelAnglesAndPosition( m_angPlayer, m_vecPlayerPos );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
Vector CBaseModelPanel::GetPlayerPos() const
|
||||
{
|
||||
return m_vecPlayerPos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
QAngle CBaseModelPanel::GetPlayerAngles() const
|
||||
{
|
||||
return m_angPlayer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::OnMouseWheeled( int delta )
|
||||
{
|
||||
if ( m_bAllowFullManipulation )
|
||||
{
|
||||
BaseClass::OnMouseWheeled( delta );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Set the camera to a distance that allows the object to fill the model panel.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseModelPanel::LookAtBounds( const Vector &vecBoundsMin, const Vector &vecBoundsMax )
|
||||
{
|
||||
// Get the model space render bounds.
|
||||
Vector vecMin = vecBoundsMin;
|
||||
Vector vecMax = vecBoundsMax;
|
||||
Vector vecCenter = ( vecMax + vecMin ) * 0.5f;
|
||||
vecMin -= vecCenter;
|
||||
vecMax -= vecCenter;
|
||||
|
||||
// Get the bounds points and transform them by the desired model panel rotation.
|
||||
Vector aBoundsPoints[8];
|
||||
aBoundsPoints[0].Init( vecMax.x, vecMax.y, vecMax.z );
|
||||
aBoundsPoints[1].Init( vecMin.x, vecMax.y, vecMax.z );
|
||||
aBoundsPoints[2].Init( vecMax.x, vecMin.y, vecMax.z );
|
||||
aBoundsPoints[3].Init( vecMin.x, vecMin.y, vecMax.z );
|
||||
aBoundsPoints[4].Init( vecMax.x, vecMax.y, vecMin.z );
|
||||
aBoundsPoints[5].Init( vecMin.x, vecMax.y, vecMin.z );
|
||||
aBoundsPoints[6].Init( vecMax.x, vecMin.y, vecMin.z );
|
||||
aBoundsPoints[7].Init( vecMin.x, vecMin.y, vecMin.z );
|
||||
|
||||
// Translated center point (offset from camera center).
|
||||
Vector vecTranslateCenter = -vecCenter;
|
||||
|
||||
// Build the rotation matrix.
|
||||
matrix3x4_t matRotation;
|
||||
AngleMatrix( m_BMPResData.m_angModelPoseRot, matRotation );
|
||||
|
||||
Vector aXFormPoints[8];
|
||||
for ( int iPoint = 0; iPoint < 8; ++iPoint )
|
||||
{
|
||||
VectorTransform( aBoundsPoints[iPoint], matRotation, aXFormPoints[iPoint] );
|
||||
}
|
||||
|
||||
Vector vecXFormCenter;
|
||||
VectorTransform( -vecTranslateCenter, matRotation, vecXFormCenter );
|
||||
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
float flW = (float)w;
|
||||
float flH = (float)h;
|
||||
|
||||
float flFOVx = DEG2RAD( m_BMPResData.m_flFOV * 0.5f );
|
||||
float flFOVy = CalcFovY( ( m_BMPResData.m_flFOV * 0.5f ), flW/flH );
|
||||
flFOVy = DEG2RAD( flFOVy );
|
||||
|
||||
float flTanFOVx = tan( flFOVx );
|
||||
float flTanFOVy = tan( flFOVy );
|
||||
|
||||
// Find the max value of x, y, or z
|
||||
Vector2D dist[8];
|
||||
float flDist = 0.0f;
|
||||
for ( int iPoint = 0; iPoint < 8; ++iPoint )
|
||||
{
|
||||
float flDistY = fabs( aXFormPoints[iPoint].y / flTanFOVx ) - aXFormPoints[iPoint].x;
|
||||
float flDistZ = fabs( aXFormPoints[iPoint].z / flTanFOVy ) - aXFormPoints[iPoint].x;
|
||||
dist[iPoint].x = flDistY;
|
||||
dist[iPoint].y = flDistZ;
|
||||
float flTestDist = MAX( flDistZ, flDistY );
|
||||
flDist = MAX( flDist, flTestDist );
|
||||
}
|
||||
|
||||
// Screen space points.
|
||||
Vector2D aScreenPoints[8];
|
||||
Vector aCameraPoints[8];
|
||||
for ( int iPoint = 0; iPoint < 8; ++iPoint )
|
||||
{
|
||||
aCameraPoints[iPoint] = aXFormPoints[iPoint];
|
||||
aCameraPoints[iPoint].x += flDist;
|
||||
|
||||
aScreenPoints[iPoint].x = aCameraPoints[iPoint].y / ( flTanFOVx * aCameraPoints[iPoint].x );
|
||||
aScreenPoints[iPoint].y = aCameraPoints[iPoint].z / ( flTanFOVy * aCameraPoints[iPoint].x );
|
||||
|
||||
aScreenPoints[iPoint].x = ( aScreenPoints[iPoint].x * 0.5f + 0.5f ) * flW;
|
||||
aScreenPoints[iPoint].y = ( aScreenPoints[iPoint].y * 0.5f + 0.5f ) * flH;
|
||||
}
|
||||
|
||||
// Find the min/max and center of the 2D bounding box of the object.
|
||||
Vector2D vecScreenMin( 99999.0f, 99999.0f ), vecScreenMax( -99999.0f, -99999.0f );
|
||||
for ( int iPoint = 0; iPoint < 8; ++iPoint )
|
||||
{
|
||||
vecScreenMin.x = MIN( vecScreenMin.x, aScreenPoints[iPoint].x );
|
||||
vecScreenMin.y = MIN( vecScreenMin.y, aScreenPoints[iPoint].y );
|
||||
vecScreenMax.x = MAX( vecScreenMax.x, aScreenPoints[iPoint].x );
|
||||
vecScreenMax.y = MAX( vecScreenMax.y, aScreenPoints[iPoint].y );
|
||||
}
|
||||
|
||||
// Offset the model to the be the correct distance away from the camera.
|
||||
Vector vecModelPos;
|
||||
vecModelPos.x = flDist - vecXFormCenter.x;
|
||||
vecModelPos.y = -vecXFormCenter.y;
|
||||
vecModelPos.z = -vecXFormCenter.z;
|
||||
SetModelAnglesAndPosition( m_BMPResData.m_angModelPoseRot, vecModelPos );
|
||||
m_vecPlayerPos = vecModelPos;
|
||||
|
||||
// Back project to figure out the camera offset to center the model.
|
||||
Vector2D vecPanelCenter( ( flW * 0.5f ), ( flH * 0.5f ) );
|
||||
Vector2D vecScreenCenter = ( vecScreenMax + vecScreenMin ) * 0.5f;
|
||||
|
||||
Vector2D vecPanelCenterCamera, vecScreenCenterCamera;
|
||||
vecPanelCenterCamera.x = ( ( vecPanelCenter.x / flW ) * 2.0f ) - 0.5f;
|
||||
vecPanelCenterCamera.y = ( ( vecPanelCenter.y / flH ) * 2.0f ) - 0.5f;
|
||||
vecPanelCenterCamera.x *= ( flTanFOVx * flDist );
|
||||
vecPanelCenterCamera.y *= ( flTanFOVy * flDist );
|
||||
vecScreenCenterCamera.x = ( ( vecScreenCenter.x / flW ) * 2.0f ) - 0.5f;
|
||||
vecScreenCenterCamera.y = ( ( vecScreenCenter.y / flH ) * 2.0f ) - 0.5f;
|
||||
vecScreenCenterCamera.x *= ( flTanFOVx * flDist );
|
||||
vecScreenCenterCamera.y *= ( flTanFOVy * flDist );
|
||||
|
||||
Vector2D vecCameraOffset( 0.0f, 0.0f );
|
||||
vecCameraOffset.x = vecPanelCenterCamera.x - vecScreenCenterCamera.x;
|
||||
vecCameraOffset.y = vecPanelCenterCamera.y - vecScreenCenterCamera.y;
|
||||
|
||||
// Clear the camera pivot and set position matrix.
|
||||
ResetCameraPivot();
|
||||
if (m_bAllowRotation )
|
||||
{
|
||||
vecCameraOffset.x = 0.0f;
|
||||
}
|
||||
SetCameraOffset( Vector( 0.0f, -vecCameraOffset.x, -vecCameraOffset.y ) );
|
||||
UpdateCameraTransform();
|
||||
}
|
||||
|
||||
225
sp/src/game/client/game_controls/basemodel_panel.h
Normal file
225
sp/src/game/client/game_controls/basemodel_panel.h
Normal file
@@ -0,0 +1,225 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef BASEMODEL_PANEL_H
|
||||
#define BASEMODEL_PANEL_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "matsys_controls/mdlpanel.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Resource file data used in posing the model inside of the model panel.
|
||||
//-----------------------------------------------------------------------------
|
||||
struct BMPResAnimData_t
|
||||
{
|
||||
const char *m_pszName;
|
||||
const char *m_pszSequence;
|
||||
const char *m_pszActivity;
|
||||
KeyValues *m_pPoseParameters;
|
||||
bool m_bDefault;
|
||||
|
||||
BMPResAnimData_t()
|
||||
{
|
||||
m_pszName = NULL;
|
||||
m_pszSequence = NULL;
|
||||
m_pszActivity = NULL;
|
||||
m_pPoseParameters = NULL;
|
||||
m_bDefault = false;
|
||||
}
|
||||
|
||||
~BMPResAnimData_t()
|
||||
{
|
||||
if ( m_pszName && m_pszName[0] )
|
||||
{
|
||||
delete [] m_pszName;
|
||||
m_pszName = NULL;
|
||||
}
|
||||
|
||||
if ( m_pszSequence && m_pszSequence[0] )
|
||||
{
|
||||
delete [] m_pszSequence;
|
||||
m_pszSequence = NULL;
|
||||
}
|
||||
|
||||
if ( m_pszActivity && m_pszActivity[0] )
|
||||
{
|
||||
delete [] m_pszActivity;
|
||||
m_pszActivity = NULL;
|
||||
}
|
||||
|
||||
if ( m_pPoseParameters )
|
||||
{
|
||||
m_pPoseParameters->deleteThis();
|
||||
m_pPoseParameters = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BMPResAttachData_t
|
||||
{
|
||||
const char *m_pszModelName;
|
||||
int m_nSkin;
|
||||
|
||||
BMPResAttachData_t()
|
||||
{
|
||||
m_pszModelName = NULL;
|
||||
m_nSkin = 0;
|
||||
}
|
||||
|
||||
~BMPResAttachData_t()
|
||||
{
|
||||
if ( m_pszModelName && m_pszModelName[0] )
|
||||
{
|
||||
delete [] m_pszModelName;
|
||||
m_pszModelName = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BMPResData_t
|
||||
{
|
||||
float m_flFOV;
|
||||
|
||||
const char *m_pszModelName;
|
||||
const char *m_pszModelName_HWM;
|
||||
const char *m_pszVCD;
|
||||
QAngle m_angModelPoseRot;
|
||||
Vector m_vecOriginOffset;
|
||||
Vector m_vecFramedOriginOffset;
|
||||
Vector2D m_vecViewportOffset;
|
||||
int m_nSkin;
|
||||
bool m_bUseSpotlight;
|
||||
|
||||
CUtlVector<BMPResAnimData_t> m_aAnimations;
|
||||
CUtlVector<BMPResAttachData_t> m_aAttachModels;
|
||||
|
||||
BMPResData_t()
|
||||
{
|
||||
m_flFOV = 0.0f;
|
||||
|
||||
m_pszModelName = NULL;
|
||||
m_pszModelName_HWM = NULL;
|
||||
m_pszVCD = NULL;
|
||||
m_angModelPoseRot.Init();
|
||||
m_vecOriginOffset.Init();
|
||||
m_vecFramedOriginOffset.Init();
|
||||
m_vecViewportOffset.Init();
|
||||
m_nSkin = 0;
|
||||
m_bUseSpotlight = false;
|
||||
}
|
||||
|
||||
~BMPResData_t()
|
||||
{
|
||||
if ( m_pszModelName && m_pszModelName[0] )
|
||||
{
|
||||
delete [] m_pszModelName;
|
||||
m_pszModelName = NULL;
|
||||
}
|
||||
|
||||
if ( m_pszModelName_HWM && m_pszModelName_HWM[0] )
|
||||
{
|
||||
delete [] m_pszModelName_HWM;
|
||||
m_pszModelName_HWM = NULL;
|
||||
}
|
||||
|
||||
if ( m_pszVCD && m_pszVCD[0] )
|
||||
{
|
||||
delete [] m_pszVCD;
|
||||
m_pszVCD = NULL;
|
||||
}
|
||||
|
||||
m_aAnimations.Purge();
|
||||
m_aAttachModels.Purge();
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Base Model Panel
|
||||
//
|
||||
// ...vgui::Panel |--> vgui
|
||||
// +->vgui::EditablePanel |
|
||||
// +->PotterWheelPanel |--> matsys_controls
|
||||
// +->MDLPanel |
|
||||
// +->BaseModelPanel |--> game_controls, client.dll
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBaseModelPanel : public CMDLPanel
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CBaseModelPanel, CMDLPanel );
|
||||
|
||||
public:
|
||||
|
||||
// Constructor, Destructor.
|
||||
CBaseModelPanel( vgui::Panel *pParent, const char *pName );
|
||||
virtual ~CBaseModelPanel();
|
||||
|
||||
// Overridden mdlpanel.h
|
||||
virtual void SetMDL( MDLHandle_t handle, void *pProxyData = NULL );
|
||||
virtual void SetMDL( const char *pMDLName, void *pProxyData = NULL );
|
||||
virtual void SetModelAnglesAndPosition( const QAngle &angRot, const Vector &vecPos );
|
||||
|
||||
// Overridden methods of vgui::Panel
|
||||
virtual void ApplySettings( KeyValues *inResourceData );
|
||||
virtual void PerformLayout();
|
||||
|
||||
// Animation.
|
||||
int FindDefaultAnim( void );
|
||||
int FindAnimByName( const char *pszName );
|
||||
void SetModelAnim( int iAnim );
|
||||
|
||||
// Manipulation.
|
||||
virtual void OnKeyCodePressed ( vgui::KeyCode code );
|
||||
virtual void OnKeyCodeReleased( vgui::KeyCode code );
|
||||
virtual void OnMousePressed ( vgui::MouseCode code );
|
||||
virtual void OnMouseReleased( vgui::MouseCode code );
|
||||
virtual void OnCursorMoved( int x, int y );
|
||||
virtual void OnMouseWheeled( int delta );
|
||||
|
||||
studiohdr_t* GetStudioHdr( void ) { return m_RootMDL.m_MDL.GetStudioHdr(); }
|
||||
void SetBody( unsigned int nBody ) { m_RootMDL.m_MDL.m_nBody = nBody; }
|
||||
|
||||
void RotateYaw( float flDelta );
|
||||
|
||||
Vector GetPlayerPos() const;
|
||||
QAngle GetPlayerAngles() const;
|
||||
|
||||
void LookAtBounds( const Vector &vecBoundsMin, const Vector &vecBoundsMax );
|
||||
|
||||
// Set to true if external code has set a specific camera position that shouldn't be clobbered by layout
|
||||
void SetForcedCameraPosition( bool bForcedCameraPosition ) { m_bForcedCameraPosition = bForcedCameraPosition; }
|
||||
|
||||
int FindSequenceFromActivity( CStudioHdr *pStudioHdr, const char *pszActivity );
|
||||
|
||||
protected:
|
||||
|
||||
// Resource file data.
|
||||
void ParseModelResInfo( KeyValues *inResourceData );
|
||||
void ParseModelAnimInfo( KeyValues *inResourceData );
|
||||
void ParseModelAttachInfo( KeyValues *inResourceData );
|
||||
|
||||
void SetupModelDefaults( void );
|
||||
void SetupModelAnimDefaults( void );
|
||||
|
||||
public:
|
||||
BMPResData_t m_BMPResData; // Base model panel data set in the .res file.
|
||||
QAngle m_angPlayer;
|
||||
Vector m_vecPlayerPos;
|
||||
|
||||
protected:
|
||||
bool m_bForcePos;
|
||||
bool m_bMousePressed;
|
||||
bool m_bAllowRotation;
|
||||
bool m_bAllowFullManipulation;
|
||||
bool m_bApplyManipulators;
|
||||
bool m_bForcedCameraPosition;
|
||||
|
||||
// VGUI script accessible variables.
|
||||
CPanelAnimationVar( bool, m_bStartFramed, "start_framed", "0" );
|
||||
CPanelAnimationVar( bool, m_bDisableManipulation, "disable_manipulation", "0" );
|
||||
};
|
||||
|
||||
#endif // BASEMODEL_PANEL_H
|
||||
898
sp/src/game/client/game_controls/basemodelpanel.cpp
Normal file
898
sp/src/game/client/game_controls/basemodelpanel.cpp
Normal file
@@ -0,0 +1,898 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
|
||||
#include "cbase.h"
|
||||
#include <KeyValues.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui/ISystem.h>
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui_controls/AnimationController.h>
|
||||
#include <vgui_controls/EditablePanel.h>
|
||||
#include <vgui_controls/ImagePanel.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui/IImage.h>
|
||||
#include <vgui_controls/Label.h>
|
||||
|
||||
#include "materialsystem/imaterialsystem.h"
|
||||
#include "engine/ivmodelinfo.h"
|
||||
|
||||
#include "c_sceneentity.h"
|
||||
#include "gamestringpool.h"
|
||||
#include "model_types.h"
|
||||
#include "view_shared.h"
|
||||
#include "view.h"
|
||||
#include "ivrenderview.h"
|
||||
#include "iefx.h"
|
||||
#include "dlight.h"
|
||||
#include "activitylist.h"
|
||||
|
||||
#include "basemodelpanel.h"
|
||||
|
||||
bool UseHWMorphModels();
|
||||
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
DECLARE_BUILD_FACTORY( CModelPanel );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CModelPanel::CModelPanel( vgui::Panel *pParent, const char *pName ) : vgui::EditablePanel( pParent, pName )
|
||||
{
|
||||
m_nFOV = 54;
|
||||
m_hModel = NULL;
|
||||
m_pModelInfo = NULL;
|
||||
m_hScene = NULL;
|
||||
m_iDefaultAnimation = 0;
|
||||
m_bPanelDirty = true;
|
||||
m_bStartFramed = false;
|
||||
m_bAllowOffscreen = false;
|
||||
|
||||
ListenForGameEvent( "game_newmap" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CModelPanel::~CModelPanel()
|
||||
{
|
||||
if ( m_pModelInfo )
|
||||
{
|
||||
delete m_pModelInfo;
|
||||
m_pModelInfo = NULL;
|
||||
}
|
||||
|
||||
DeleteVCDData();
|
||||
DeleteModelData();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::ApplySettings( KeyValues *inResourceData )
|
||||
{
|
||||
BaseClass::ApplySettings( inResourceData );
|
||||
|
||||
m_nFOV = inResourceData->GetInt( "fov", 54 );
|
||||
m_bStartFramed = inResourceData->GetInt( "start_framed", false );
|
||||
m_bAllowOffscreen = inResourceData->GetInt( "allow_offscreen", false );
|
||||
|
||||
// do we have a valid "model" section in the .res file?
|
||||
for ( KeyValues *pData = inResourceData->GetFirstSubKey() ; pData != NULL ; pData = pData->GetNextKey() )
|
||||
{
|
||||
if ( !Q_stricmp( pData->GetName(), "model" ) )
|
||||
{
|
||||
ParseModelInfo( pData );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::ParseModelInfo( KeyValues *inResourceData )
|
||||
{
|
||||
// delete any current info
|
||||
if ( m_pModelInfo )
|
||||
{
|
||||
delete m_pModelInfo;
|
||||
m_pModelInfo = NULL;
|
||||
}
|
||||
|
||||
m_pModelInfo = new CModelPanelModelInfo;
|
||||
|
||||
if ( !m_pModelInfo )
|
||||
return;
|
||||
|
||||
m_pModelInfo->m_pszModelName = ReadAndAllocStringValue( inResourceData, "modelname" );
|
||||
m_pModelInfo->m_pszModelName_HWM = ReadAndAllocStringValue( inResourceData, "modelname_hwm" );
|
||||
m_pModelInfo->m_nSkin = inResourceData->GetInt( "skin", -1 );
|
||||
m_pModelInfo->m_vecAbsAngles.Init( inResourceData->GetFloat( "angles_x", 0.0 ), inResourceData->GetFloat( "angles_y", 0.0 ), inResourceData->GetFloat( "angles_z", 0.0 ) );
|
||||
m_pModelInfo->m_vecOriginOffset.Init( inResourceData->GetFloat( "origin_x", 110.0 ), inResourceData->GetFloat( "origin_y", 5.0 ), inResourceData->GetFloat( "origin_z", 5.0 ) );
|
||||
m_pModelInfo->m_vecFramedOriginOffset.Init( inResourceData->GetFloat( "frame_origin_x", 110.0 ), inResourceData->GetFloat( "frame_origin_y", 5.0 ), inResourceData->GetFloat( "frame_origin_z", 5.0 ) );
|
||||
m_pModelInfo->m_pszVCD = ReadAndAllocStringValue( inResourceData, "vcd" );
|
||||
m_pModelInfo->m_bUseSpotlight = ( inResourceData->GetInt( "spotlight", 0 ) == 1 );
|
||||
m_pModelInfo->m_vecViewportOffset.Init();
|
||||
|
||||
for ( KeyValues *pData = inResourceData->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
|
||||
{
|
||||
if ( !Q_stricmp( pData->GetName(), "animation" ) )
|
||||
{
|
||||
OnAddAnimation( pData );
|
||||
}
|
||||
else if ( !Q_stricmp( pData->GetName(), "attached_model" ) )
|
||||
{
|
||||
CModelPanelAttachedModelInfo *pAttachedModelInfo = new CModelPanelAttachedModelInfo;
|
||||
|
||||
if ( pAttachedModelInfo )
|
||||
{
|
||||
pAttachedModelInfo->m_pszModelName = ReadAndAllocStringValue( pData, "modelname" );
|
||||
pAttachedModelInfo->m_nSkin = pData->GetInt( "skin", -1 );
|
||||
|
||||
m_pModelInfo->m_AttachedModelsInfo.AddToTail( pAttachedModelInfo );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bPanelDirty = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::OnAddAnimation( KeyValues *pData )
|
||||
{
|
||||
if ( !pData )
|
||||
return;
|
||||
|
||||
CModelPanelModelAnimation *pAnimation = new CModelPanelModelAnimation;
|
||||
|
||||
if ( pAnimation )
|
||||
{
|
||||
pAnimation->m_pszName = ReadAndAllocStringValue( pData, "name" );
|
||||
pAnimation->m_pszSequence = ReadAndAllocStringValue( pData, "sequence" );
|
||||
pAnimation->m_pszActivity = ReadAndAllocStringValue( pData, "activity" );
|
||||
pAnimation->m_bDefault = ( pData->GetInt( "default", 0 ) == 1 );
|
||||
|
||||
for ( KeyValues *pAnimData = pData->GetFirstSubKey(); pAnimData != NULL; pAnimData = pAnimData->GetNextKey() )
|
||||
{
|
||||
if ( !Q_stricmp( pAnimData->GetName(), "pose_parameters" ) )
|
||||
{
|
||||
pAnimation->m_pPoseParameters = pAnimData->MakeCopy();
|
||||
}
|
||||
}
|
||||
|
||||
m_pModelInfo->m_Animations.AddToTail( pAnimation );
|
||||
if ( pAnimation->m_bDefault )
|
||||
{
|
||||
m_iDefaultAnimation = m_pModelInfo->m_Animations.Find( pAnimation );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::FireGameEvent( IGameEvent * event )
|
||||
{
|
||||
const char *type = event->GetName();
|
||||
|
||||
if ( Q_strcmp( type, "game_newmap" ) == 0 )
|
||||
{
|
||||
// force the models to re-setup themselves
|
||||
m_bPanelDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::SetDefaultAnimation( const char *pszName )
|
||||
{
|
||||
if ( m_pModelInfo )
|
||||
{
|
||||
for ( int i = 0; i < m_pModelInfo->m_Animations.Count(); i++ )
|
||||
{
|
||||
if ( m_pModelInfo->m_Animations[i] && m_pModelInfo->m_Animations[i]->m_pszName )
|
||||
{
|
||||
if ( !Q_stricmp( m_pModelInfo->m_Animations[i]->m_pszName, pszName ) )
|
||||
{
|
||||
m_iDefaultAnimation = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert( 0 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Replaces the current model with a new one, without changing the camera settings
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::SwapModel( const char *pszName, const char *pszAttached )
|
||||
{
|
||||
if ( !m_pModelInfo || !pszName || !pszName[0] )
|
||||
return;
|
||||
|
||||
int len = Q_strlen( pszName ) + 1;
|
||||
char *pAlloced = new char[ len ];
|
||||
Assert( pAlloced );
|
||||
Q_strncpy( pAlloced, pszName, len );
|
||||
m_pModelInfo->m_pszModelName = pAlloced;
|
||||
|
||||
ClearAttachedModelInfos();
|
||||
|
||||
if ( pszAttached )
|
||||
{
|
||||
CModelPanelAttachedModelInfo *pAttachedModelInfo = new CModelPanelAttachedModelInfo;
|
||||
if ( pAttachedModelInfo )
|
||||
{
|
||||
len = Q_strlen( pszAttached ) + 1;
|
||||
pAlloced = new char[ len ];
|
||||
Assert( pAlloced );
|
||||
Q_strncpy( pAlloced, pszAttached, len );
|
||||
pAttachedModelInfo->m_pszModelName = pAlloced;
|
||||
pAttachedModelInfo->m_nSkin = 0;
|
||||
|
||||
m_pModelInfo->m_AttachedModelsInfo.AddToTail( pAttachedModelInfo );
|
||||
}
|
||||
}
|
||||
|
||||
m_bPanelDirty = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::DeleteVCDData( void )
|
||||
{
|
||||
if ( m_hScene.Get() )
|
||||
{
|
||||
m_hScene->StopClientOnlyScene();
|
||||
|
||||
m_hScene->Remove();
|
||||
m_hScene = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::SetupVCD( void )
|
||||
{
|
||||
if ( !m_pModelInfo )
|
||||
return;
|
||||
|
||||
DeleteVCDData();
|
||||
|
||||
C_SceneEntity *pEnt = new class C_SceneEntity;
|
||||
|
||||
if ( !pEnt )
|
||||
return;
|
||||
|
||||
if ( pEnt->InitializeAsClientEntity( "", RENDER_GROUP_OTHER ) == false )
|
||||
{
|
||||
// we failed to initialize this entity so just return gracefully
|
||||
pEnt->Remove();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup the handle
|
||||
m_hScene = pEnt;
|
||||
|
||||
// setup the scene
|
||||
pEnt->SetupClientOnlyScene( m_pModelInfo->m_pszVCD, m_hModel, true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::ClearAttachedModelInfos( void )
|
||||
{
|
||||
if ( m_pModelInfo )
|
||||
{
|
||||
m_pModelInfo->m_AttachedModelsInfo.PurgeAndDeleteElements();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::DeleteModelData( void )
|
||||
{
|
||||
if ( m_hModel.Get() )
|
||||
{
|
||||
m_hModel->Remove();
|
||||
m_hModel = NULL;
|
||||
m_flFrameDistance = 0;
|
||||
}
|
||||
|
||||
for ( int i = 0 ; i < m_AttachedModels.Count() ; i++ )
|
||||
{
|
||||
if ( m_AttachedModels[i].Get() )
|
||||
{
|
||||
m_AttachedModels[i]->Remove();
|
||||
}
|
||||
m_AttachedModels.Remove( i );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CModelPanel::GetModelName( void )
|
||||
{
|
||||
if ( !m_pModelInfo )
|
||||
return NULL;
|
||||
|
||||
// check to see if we want to use a HWM model
|
||||
if ( UseHWMorphModels() )
|
||||
{
|
||||
// do we have a valid HWM model filename
|
||||
if ( m_pModelInfo->m_pszModelName_HWM && ( Q_strlen( m_pModelInfo->m_pszModelName_HWM ) > 0 ) )
|
||||
{
|
||||
// does the file exist
|
||||
model_t *pModel = (model_t *)engine->LoadModel( m_pModelInfo->m_pszModelName_HWM );
|
||||
if ( pModel )
|
||||
{
|
||||
return m_pModelInfo->m_pszModelName_HWM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_pModelInfo->m_pszModelName;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::SetupModel( void )
|
||||
{
|
||||
if ( !m_pModelInfo )
|
||||
return;
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
// remove any current models we're using
|
||||
DeleteModelData();
|
||||
|
||||
const char *pszModelName = GetModelName();
|
||||
if ( !pszModelName || !pszModelName[0] )
|
||||
return;
|
||||
|
||||
// create the new model
|
||||
CModelPanelModel *pEnt = new CModelPanelModel;
|
||||
|
||||
if ( !pEnt )
|
||||
return;
|
||||
|
||||
if ( pEnt->InitializeAsClientEntity( pszModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false )
|
||||
{
|
||||
// we failed to initialize this entity so just return gracefully
|
||||
pEnt->Remove();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup the handle
|
||||
m_hModel = pEnt;
|
||||
|
||||
pEnt->DontRecordInTools();
|
||||
pEnt->AddEffects( EF_NODRAW ); // don't let the renderer draw the model normally
|
||||
|
||||
if ( m_pModelInfo->m_nSkin >= 0 )
|
||||
{
|
||||
pEnt->m_nSkin = m_pModelInfo->m_nSkin;
|
||||
}
|
||||
|
||||
// do we have any animation information?
|
||||
if ( m_pModelInfo->m_Animations.Count() > 0 && m_pModelInfo->m_Animations.IsValidIndex( m_iDefaultAnimation ) )
|
||||
{
|
||||
CModelPanelModelAnimation *pAnim = m_pModelInfo->m_Animations[ m_iDefaultAnimation ];
|
||||
int sequence = ACT_INVALID;
|
||||
if ( pAnim->m_pszActivity && pAnim->m_pszActivity[0] )
|
||||
{
|
||||
Activity activity = (Activity)ActivityList_IndexForName( pAnim->m_pszActivity );
|
||||
sequence = pEnt->SelectWeightedSequence( activity );
|
||||
}
|
||||
else if ( pAnim->m_pszSequence && pAnim->m_pszSequence[0] )
|
||||
{
|
||||
sequence = pEnt->LookupSequence( pAnim->m_pszSequence );
|
||||
}
|
||||
if ( sequence != ACT_INVALID )
|
||||
{
|
||||
pEnt->ResetSequence( sequence );
|
||||
pEnt->SetCycle( 0 );
|
||||
|
||||
if ( pAnim->m_pPoseParameters )
|
||||
{
|
||||
for ( KeyValues *pData = pAnim->m_pPoseParameters->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
|
||||
{
|
||||
const char *pName = pData->GetName();
|
||||
float flValue = pData->GetFloat();
|
||||
|
||||
pEnt->SetPoseParameter( pName, flValue );
|
||||
}
|
||||
}
|
||||
|
||||
pEnt->m_flAnimTime = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
// setup any attached models
|
||||
for ( int i = 0 ; i < m_pModelInfo->m_AttachedModelsInfo.Count() ; i++ )
|
||||
{
|
||||
CModelPanelAttachedModelInfo *pInfo = m_pModelInfo->m_AttachedModelsInfo[i];
|
||||
C_BaseAnimating *pTemp = new C_BaseAnimating;
|
||||
|
||||
if ( pTemp )
|
||||
{
|
||||
if ( pTemp->InitializeAsClientEntity( pInfo->m_pszModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false )
|
||||
{
|
||||
// we failed to initialize this model so just skip it
|
||||
pTemp->Remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
pTemp->DontRecordInTools();
|
||||
pTemp->AddEffects( EF_NODRAW ); // don't let the renderer draw the model normally
|
||||
pTemp->FollowEntity( m_hModel.Get() ); // attach to parent model
|
||||
|
||||
if ( pInfo->m_nSkin >= 0 )
|
||||
{
|
||||
pTemp->m_nSkin = pInfo->m_nSkin;
|
||||
}
|
||||
|
||||
pTemp->m_flAnimTime = gpGlobals->curtime;
|
||||
m_AttachedModels.AddToTail( pTemp );
|
||||
}
|
||||
}
|
||||
|
||||
CalculateFrameDistance();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::InitCubeMaps()
|
||||
{
|
||||
ITexture *pCubemapTexture;
|
||||
|
||||
// Deal with the default cubemap
|
||||
if ( g_pMaterialSystemHardwareConfig->GetHDREnabled() )
|
||||
{
|
||||
pCubemapTexture = materials->FindTexture( "editor/cubemap.hdr", NULL, true );
|
||||
m_DefaultHDREnvCubemap.Init( pCubemapTexture );
|
||||
}
|
||||
else
|
||||
{
|
||||
pCubemapTexture = materials->FindTexture( "editor/cubemap", NULL, true );
|
||||
m_DefaultEnvCubemap.Init( pCubemapTexture );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: If the panel is marked as dirty, update it and mark it as clean
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::UpdateModel()
|
||||
{
|
||||
if ( m_bPanelDirty )
|
||||
{
|
||||
InitCubeMaps();
|
||||
|
||||
SetupModel();
|
||||
|
||||
// are we trying to play a VCD?
|
||||
if ( Q_strlen( m_pModelInfo->m_pszVCD ) > 0 )
|
||||
{
|
||||
SetupVCD();
|
||||
}
|
||||
|
||||
m_bPanelDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::Paint()
|
||||
{
|
||||
BaseClass::Paint();
|
||||
|
||||
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
|
||||
|
||||
if ( !pLocalPlayer || !m_pModelInfo )
|
||||
return;
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
UpdateModel();
|
||||
|
||||
if ( !m_hModel.Get() )
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
int x, y, w, h;
|
||||
|
||||
GetBounds( x, y, w, h );
|
||||
ParentLocalToScreen( x, y );
|
||||
|
||||
if ( !m_bAllowOffscreen && x < 0 )
|
||||
{
|
||||
// prevent x from being pushed off the left side of the screen
|
||||
// for modes like 1280 x 1024 (prevents model from being drawn in the panel)
|
||||
x = 0;
|
||||
}
|
||||
|
||||
Vector vecExtraModelOffset( 0, 0, 0 );
|
||||
float flWidthRatio = ((float)w / (float)h ) / ( 4.0f / 3.0f );
|
||||
|
||||
// is this a player model?
|
||||
if ( Q_strstr( GetModelName(), "models/player/" ) )
|
||||
{
|
||||
// need to know if the ratio is not 4/3
|
||||
// HACK! HACK! to get our player models to appear the way they do in 4/3 if we're using other aspect ratios
|
||||
if ( flWidthRatio > 1.05f )
|
||||
{
|
||||
vecExtraModelOffset.Init( -60, 0, 0 );
|
||||
}
|
||||
else if ( flWidthRatio < 0.95f )
|
||||
{
|
||||
vecExtraModelOffset.Init( 15, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
m_hModel->SetAbsOrigin( m_pModelInfo->m_vecOriginOffset + vecExtraModelOffset );
|
||||
m_hModel->SetAbsAngles( QAngle( m_pModelInfo->m_vecAbsAngles.x, m_pModelInfo->m_vecAbsAngles.y, m_pModelInfo->m_vecAbsAngles.z ) );
|
||||
|
||||
// do we have a valid sequence?
|
||||
if ( m_hModel->GetSequence() != -1 )
|
||||
{
|
||||
m_hModel->FrameAdvance( gpGlobals->frametime );
|
||||
}
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
|
||||
// figure out what our viewport is right now
|
||||
int viewportX, viewportY, viewportWidth, viewportHeight;
|
||||
pRenderContext->GetViewport( viewportX, viewportY, viewportWidth, viewportHeight );
|
||||
|
||||
// Now draw it.
|
||||
CViewSetup view;
|
||||
view.x = x + m_pModelInfo->m_vecViewportOffset.x + viewportX; // we actually want to offset by the
|
||||
view.y = y + m_pModelInfo->m_vecViewportOffset.y + viewportY; // viewport origin here because Push3DView expects global coords below
|
||||
view.width = w;
|
||||
view.height = h;
|
||||
|
||||
view.m_bOrtho = false;
|
||||
|
||||
// scale the FOV for aspect ratios other than 4/3
|
||||
view.fov = ScaleFOVByWidthRatio( m_nFOV, flWidthRatio );
|
||||
|
||||
view.origin = vec3_origin;
|
||||
view.angles.Init();
|
||||
view.zNear = VIEW_NEARZ;
|
||||
view.zFar = 1000;
|
||||
|
||||
|
||||
|
||||
// Not supported by queued material system - doesn't appear to be necessary
|
||||
// ITexture *pLocalCube = pRenderContext->GetLocalCubemap();
|
||||
|
||||
if ( g_pMaterialSystemHardwareConfig->GetHDREnabled() )
|
||||
{
|
||||
pRenderContext->BindLocalCubemap( m_DefaultHDREnvCubemap );
|
||||
}
|
||||
else
|
||||
{
|
||||
pRenderContext->BindLocalCubemap( m_DefaultEnvCubemap );
|
||||
}
|
||||
|
||||
pRenderContext->SetLightingOrigin( vec3_origin );
|
||||
pRenderContext->SetAmbientLight( 0.4, 0.4, 0.4 );
|
||||
|
||||
static Vector white[6] =
|
||||
{
|
||||
Vector( 0.4, 0.4, 0.4 ),
|
||||
Vector( 0.4, 0.4, 0.4 ),
|
||||
Vector( 0.4, 0.4, 0.4 ),
|
||||
Vector( 0.4, 0.4, 0.4 ),
|
||||
Vector( 0.4, 0.4, 0.4 ),
|
||||
Vector( 0.4, 0.4, 0.4 ),
|
||||
};
|
||||
|
||||
g_pStudioRender->SetAmbientLightColors( white );
|
||||
g_pStudioRender->SetLocalLights( 0, NULL );
|
||||
|
||||
if ( m_pModelInfo->m_bUseSpotlight )
|
||||
{
|
||||
Vector vecMins, vecMaxs;
|
||||
m_hModel->GetRenderBounds( vecMins, vecMaxs );
|
||||
LightDesc_t spotLight( vec3_origin + Vector( 0, 0, 200 ), Vector( 1, 1, 1 ), m_hModel->GetAbsOrigin() + Vector( 0, 0, ( vecMaxs.z - vecMins.z ) * 0.75 ), 0.035, 0.873 );
|
||||
g_pStudioRender->SetLocalLights( 1, &spotLight );
|
||||
}
|
||||
|
||||
Frustum dummyFrustum;
|
||||
render->Push3DView( view, 0, NULL, dummyFrustum );
|
||||
|
||||
modelrender->SuppressEngineLighting( true );
|
||||
float color[3] = { 1.0f, 1.0f, 1.0f };
|
||||
render->SetColorModulation( color );
|
||||
render->SetBlend( 1.0f );
|
||||
m_hModel->DrawModel( STUDIO_RENDER );
|
||||
|
||||
for ( i = 0 ; i < m_AttachedModels.Count() ; i++ )
|
||||
{
|
||||
if ( m_AttachedModels[i].Get() )
|
||||
{
|
||||
m_AttachedModels[i]->DrawModel( STUDIO_RENDER );
|
||||
}
|
||||
}
|
||||
|
||||
modelrender->SuppressEngineLighting( false );
|
||||
|
||||
render->PopView( dummyFrustum );
|
||||
|
||||
pRenderContext->BindLocalCubemap( NULL );
|
||||
|
||||
/*
|
||||
vgui::surface()->DrawSetColor( Color(0,0,0,255) );
|
||||
vgui::surface()->DrawOutlinedRect( 0,0, GetWide(), GetTall() );
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CModelPanel::FindAnimByName( const char *pszName )
|
||||
{
|
||||
// first try to find the sequence using pszName as the friendly name
|
||||
for ( int iIndex = 0 ; iIndex < m_pModelInfo->m_Animations.Count() ; iIndex++ )
|
||||
{
|
||||
CModelPanelModelAnimation *pAnimation = m_pModelInfo->m_Animations[ iIndex ];
|
||||
if ( FStrEq( pAnimation->m_pszName, pszName ) )
|
||||
return iIndex;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CModelPanel::SetSequence( const char *pszName )
|
||||
{
|
||||
bool bRetVal = false;
|
||||
const char *pszAnim = NULL;
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
if ( m_pModelInfo )
|
||||
{
|
||||
int iIndex = FindAnimByName(pszName);
|
||||
if ( iIndex != -1 )
|
||||
{
|
||||
pszAnim = m_pModelInfo->m_Animations[iIndex]->m_pszSequence;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not, just use the passed name as the sequence
|
||||
pszAnim = pszName;
|
||||
}
|
||||
|
||||
if ( m_hModel.Get() )
|
||||
{
|
||||
int sequence = m_hModel->LookupSequence( pszAnim );
|
||||
if ( sequence != ACT_INVALID )
|
||||
{
|
||||
m_hModel->ResetSequence( sequence );
|
||||
m_hModel->SetCycle( 0 );
|
||||
|
||||
bRetVal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::OnSetAnimation( KeyValues *data )
|
||||
{
|
||||
UpdateModel();
|
||||
|
||||
// If there's no model, these commands will be ignored.
|
||||
Assert(m_hModel);
|
||||
|
||||
if ( data )
|
||||
{
|
||||
const char *pszAnimation = data->GetString( "animation", "" );
|
||||
const char *pszActivity = data->GetString( "activity", "" );
|
||||
if ( pszActivity && pszActivity[0] )
|
||||
{
|
||||
if ( m_hModel )
|
||||
{
|
||||
int iIndex = FindAnimByName(pszActivity);
|
||||
if ( iIndex != -1 )
|
||||
{
|
||||
pszActivity = m_pModelInfo->m_Animations[iIndex]->m_pszActivity;
|
||||
}
|
||||
|
||||
Activity activity = (Activity)ActivityList_IndexForName( pszActivity );
|
||||
int sequence = m_hModel->SelectWeightedSequence( activity );
|
||||
if ( sequence != ACT_INVALID )
|
||||
{
|
||||
m_hModel->ResetSequence( sequence );
|
||||
m_hModel->SetCycle( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSequence( pszAnimation );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CModelPanel::CalculateFrameDistanceInternal( const model_t *pModel )
|
||||
{
|
||||
// Get the model space render bounds.
|
||||
Vector vecMin, vecMax;
|
||||
modelinfo->GetModelRenderBounds( pModel, vecMin, vecMax );
|
||||
Vector vecCenter = ( vecMax + vecMin ) * 0.5f;
|
||||
vecMin -= vecCenter;
|
||||
vecMax -= vecCenter;
|
||||
|
||||
// Get the bounds points and transform them by the desired model panel rotation.
|
||||
Vector aBoundsPoints[8];
|
||||
aBoundsPoints[0].Init( vecMax.x, vecMax.y, vecMax.z );
|
||||
aBoundsPoints[1].Init( vecMin.x, vecMax.y, vecMax.z );
|
||||
aBoundsPoints[2].Init( vecMax.x, vecMin.y, vecMax.z );
|
||||
aBoundsPoints[3].Init( vecMin.x, vecMin.y, vecMax.z );
|
||||
aBoundsPoints[4].Init( vecMax.x, vecMax.y, vecMin.z );
|
||||
aBoundsPoints[5].Init( vecMin.x, vecMax.y, vecMin.z );
|
||||
aBoundsPoints[6].Init( vecMax.x, vecMin.y, vecMin.z );
|
||||
aBoundsPoints[7].Init( vecMin.x, vecMin.y, vecMin.z );
|
||||
|
||||
// Translated center point (offset from camera center).
|
||||
Vector vecTranslateCenter = -vecCenter;
|
||||
|
||||
// Build the rotation matrix.
|
||||
QAngle angPanelAngles( m_pModelInfo->m_vecAbsAngles.x, m_pModelInfo->m_vecAbsAngles.y, m_pModelInfo->m_vecAbsAngles.z );
|
||||
matrix3x4_t matRotation;
|
||||
AngleMatrix( angPanelAngles, matRotation );
|
||||
|
||||
Vector aXFormPoints[8];
|
||||
for ( int iPoint = 0; iPoint < 8; ++iPoint )
|
||||
{
|
||||
VectorTransform( aBoundsPoints[iPoint], matRotation, aXFormPoints[iPoint] );
|
||||
}
|
||||
|
||||
Vector vecXFormCenter;
|
||||
VectorTransform( -vecTranslateCenter, matRotation, vecXFormCenter );
|
||||
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
float flW = (float)w;
|
||||
float flH = (float)h;
|
||||
|
||||
float flFOVx = DEG2RAD( m_nFOV * 0.5f );
|
||||
float flFOVy = CalcFovY( ( m_nFOV * 0.5f ), flW/flH );
|
||||
flFOVy = DEG2RAD( flFOVy );
|
||||
|
||||
float flTanFOVx = tan( flFOVx );
|
||||
float flTanFOVy = tan( flFOVy );
|
||||
|
||||
// Find the max value of x, y, or z
|
||||
float flDist = 0.0f;
|
||||
for ( int iPoint = 0; iPoint < 8; ++iPoint )
|
||||
{
|
||||
float flDistZ = fabs( aXFormPoints[iPoint].z / flTanFOVy - aXFormPoints[iPoint].x );
|
||||
float flDistY = fabs( aXFormPoints[iPoint].y / flTanFOVx - aXFormPoints[iPoint].x );
|
||||
float flTestDist = MAX( flDistZ, flDistY );
|
||||
flDist = MAX( flDist, flTestDist );
|
||||
}
|
||||
|
||||
// Scale the object down by 10%.
|
||||
flDist *= 1.10f;
|
||||
|
||||
// Add the framing offset.
|
||||
vecXFormCenter += m_pModelInfo->m_vecFramedOriginOffset;
|
||||
|
||||
// Zoom to the frame distance
|
||||
m_pModelInfo->m_vecOriginOffset.x = flDist - vecXFormCenter.x;
|
||||
m_pModelInfo->m_vecOriginOffset.y = -vecXFormCenter.y;
|
||||
m_pModelInfo->m_vecOriginOffset.z = -vecXFormCenter.z;
|
||||
|
||||
// Screen space points.
|
||||
Vector2D aScreenPoints[8];
|
||||
Vector aCameraPoints[8];
|
||||
for ( int iPoint = 0; iPoint < 8; ++iPoint )
|
||||
{
|
||||
aCameraPoints[iPoint] = aXFormPoints[iPoint];
|
||||
aCameraPoints[iPoint].x += flDist;
|
||||
|
||||
aScreenPoints[iPoint].x = aCameraPoints[iPoint].y / ( flTanFOVx * aCameraPoints[iPoint].x );
|
||||
aScreenPoints[iPoint].y = aCameraPoints[iPoint].z / ( flTanFOVy * aCameraPoints[iPoint].x );
|
||||
|
||||
aScreenPoints[iPoint].x = ( aScreenPoints[iPoint].x * 0.5f + 0.5f ) * flW;
|
||||
aScreenPoints[iPoint].y = ( aScreenPoints[iPoint].y * 0.5f + 0.5f ) * flH;
|
||||
}
|
||||
|
||||
// Find the min/max and center of the 2D bounding box of the object.
|
||||
Vector2D vecScreenMin( 99999.0f, 99999.0f ), vecScreenMax( -99999.0f, -99999.0f );
|
||||
for ( int iPoint = 0; iPoint < 8; ++iPoint )
|
||||
{
|
||||
vecScreenMin.x = MIN( vecScreenMin.x, aScreenPoints[iPoint].x );
|
||||
vecScreenMin.y = MIN( vecScreenMin.y, aScreenPoints[iPoint].y );
|
||||
vecScreenMax.x = MAX( vecScreenMax.x, aScreenPoints[iPoint].x );
|
||||
vecScreenMax.y = MAX( vecScreenMax.y, aScreenPoints[iPoint].y );
|
||||
}
|
||||
|
||||
vecScreenMin.x = clamp( vecScreenMin.x, 0.0f, flW );
|
||||
vecScreenMin.y = clamp( vecScreenMin.y, 0.0f, flH );
|
||||
vecScreenMax.x = clamp( vecScreenMax.x, 0.0f, flW );
|
||||
vecScreenMax.y = clamp( vecScreenMax.y, 0.0f, flH );
|
||||
|
||||
// Offset the view port based on the calculated model 2D center and the center of the viewport.
|
||||
Vector2D vecScreenCenter = ( vecScreenMax + vecScreenMin ) * 0.5f;
|
||||
m_pModelInfo->m_vecViewportOffset.x = -( ( flW * 0.5f ) - vecScreenCenter.x );
|
||||
m_pModelInfo->m_vecViewportOffset.y = -( ( flH * 0.5f ) - vecScreenCenter.y );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Calculates the distance the camera should be at to frame the model on the screen.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::CalculateFrameDistance( void )
|
||||
{
|
||||
m_flFrameDistance = 0;
|
||||
if ( !m_hModel )
|
||||
return;
|
||||
|
||||
// Compute a bounding radius for the model
|
||||
const model_t *mod = modelinfo->GetModel( m_hModel->GetModelIndex() );
|
||||
if ( !mod )
|
||||
return;
|
||||
|
||||
if ( m_bStartFramed )
|
||||
{
|
||||
CalculateFrameDistanceInternal( mod );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Moves the camera forward/backward along the current view angle to
|
||||
// frame the model on the screen.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CModelPanel::ZoomToFrameDistance( void )
|
||||
{
|
||||
if ( !m_flFrameDistance || !m_hModel )
|
||||
return;
|
||||
|
||||
const model_t *mod = modelinfo->GetModel( m_hModel->GetModelIndex() );
|
||||
if ( !mod )
|
||||
return;
|
||||
|
||||
// Move the model to the midpoint
|
||||
Vector mins, maxs, vecModelCenter;
|
||||
modelinfo->GetModelRenderBounds( mod, mins, maxs );
|
||||
VectorLerp( mins, maxs, 0.5f, vecModelCenter );
|
||||
|
||||
vecModelCenter += m_pModelInfo->m_vecFramedOriginOffset;
|
||||
|
||||
// Zoom to the frame distance
|
||||
m_pModelInfo->m_vecOriginOffset.x = m_flFrameDistance;
|
||||
m_pModelInfo->m_vecOriginOffset.y = -vecModelCenter.y;
|
||||
m_pModelInfo->m_vecOriginOffset.z = -vecModelCenter.z;
|
||||
}
|
||||
|
||||
233
sp/src/game/client/game_controls/basemodelpanel.h
Normal file
233
sp/src/game/client/game_controls/basemodelpanel.h
Normal file
@@ -0,0 +1,233 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BASEMODELPANEL_H
|
||||
#define BASEMODELPANEL_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui_controls/ImagePanel.h>
|
||||
#include <vgui_controls/EditablePanel.h>
|
||||
#include "GameEventListener.h"
|
||||
#include "KeyValues.h"
|
||||
|
||||
class C_SceneEntity;
|
||||
|
||||
|
||||
class CModelPanelModel : public C_BaseFlex
|
||||
{
|
||||
public:
|
||||
CModelPanelModel(){}
|
||||
DECLARE_CLASS( CModelPanelModel, C_BaseFlex );
|
||||
|
||||
virtual bool IsMenuModel() const{ return true; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CModelPanelModelAnimation
|
||||
{
|
||||
public:
|
||||
CModelPanelModelAnimation()
|
||||
{
|
||||
m_pszName = NULL;
|
||||
m_pszSequence = NULL;
|
||||
m_pszActivity = NULL;
|
||||
m_pPoseParameters = NULL;
|
||||
m_bDefault = false;
|
||||
}
|
||||
|
||||
~CModelPanelModelAnimation()
|
||||
{
|
||||
if ( m_pszName && m_pszName[0] )
|
||||
{
|
||||
delete [] m_pszName;
|
||||
m_pszName = NULL;
|
||||
}
|
||||
|
||||
if ( m_pszSequence && m_pszSequence[0] )
|
||||
{
|
||||
delete [] m_pszSequence;
|
||||
m_pszSequence = NULL;
|
||||
}
|
||||
|
||||
if ( m_pszActivity && m_pszActivity[0] )
|
||||
{
|
||||
delete [] m_pszActivity;
|
||||
m_pszActivity = NULL;
|
||||
}
|
||||
|
||||
if ( m_pPoseParameters )
|
||||
{
|
||||
m_pPoseParameters->deleteThis();
|
||||
m_pPoseParameters = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
const char *m_pszName;
|
||||
const char *m_pszSequence;
|
||||
const char *m_pszActivity;
|
||||
KeyValues *m_pPoseParameters;
|
||||
bool m_bDefault;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CModelPanelAttachedModelInfo
|
||||
{
|
||||
public:
|
||||
CModelPanelAttachedModelInfo()
|
||||
{
|
||||
m_pszModelName = NULL;
|
||||
m_nSkin = 0;
|
||||
}
|
||||
|
||||
~CModelPanelAttachedModelInfo()
|
||||
{
|
||||
if ( m_pszModelName && m_pszModelName[0] )
|
||||
{
|
||||
delete [] m_pszModelName;
|
||||
m_pszModelName = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
const char *m_pszModelName;
|
||||
int m_nSkin;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CModelPanelModelInfo
|
||||
{
|
||||
public:
|
||||
CModelPanelModelInfo()
|
||||
{
|
||||
m_pszModelName = NULL;
|
||||
m_pszModelName_HWM = NULL;
|
||||
m_nSkin = -1;
|
||||
m_vecAbsAngles.Init();
|
||||
m_vecOriginOffset.Init();
|
||||
m_vecFramedOriginOffset.Init();
|
||||
m_bUseSpotlight = false;
|
||||
}
|
||||
|
||||
~CModelPanelModelInfo()
|
||||
{
|
||||
if ( m_pszModelName && m_pszModelName[0] )
|
||||
{
|
||||
delete [] m_pszModelName;
|
||||
m_pszModelName = NULL;
|
||||
}
|
||||
|
||||
if ( m_pszModelName_HWM && m_pszModelName_HWM[0] )
|
||||
{
|
||||
delete [] m_pszModelName_HWM;
|
||||
m_pszModelName_HWM = NULL;
|
||||
}
|
||||
|
||||
if ( m_pszVCD && m_pszVCD[0] )
|
||||
{
|
||||
delete [] m_pszVCD;
|
||||
m_pszVCD = NULL;
|
||||
}
|
||||
|
||||
m_Animations.PurgeAndDeleteElements();
|
||||
m_AttachedModelsInfo.PurgeAndDeleteElements();
|
||||
}
|
||||
|
||||
public:
|
||||
const char *m_pszModelName;
|
||||
const char *m_pszModelName_HWM;
|
||||
int m_nSkin;
|
||||
const char *m_pszVCD;
|
||||
Vector m_vecAbsAngles;
|
||||
Vector m_vecOriginOffset;
|
||||
Vector2D m_vecViewportOffset;
|
||||
Vector m_vecFramedOriginOffset;
|
||||
bool m_bUseSpotlight;
|
||||
|
||||
CUtlVector<CModelPanelModelAnimation*> m_Animations;
|
||||
CUtlVector<CModelPanelAttachedModelInfo*> m_AttachedModelsInfo;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CModelPanel : public vgui::EditablePanel, public CGameEventListener
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS_SIMPLE( CModelPanel, vgui::EditablePanel );
|
||||
|
||||
CModelPanel( vgui::Panel *parent, const char *name );
|
||||
virtual ~CModelPanel();
|
||||
|
||||
virtual void Paint();
|
||||
virtual void ApplySettings( KeyValues *inResourceData );
|
||||
virtual void DeleteVCDData( void );
|
||||
virtual void DeleteModelData( void );
|
||||
|
||||
virtual void SetFOV( int nFOV ){ m_nFOV = nFOV; }
|
||||
virtual void SetPanelDirty( void ){ m_bPanelDirty = true; }
|
||||
virtual bool SetSequence( const char *pszSequence );
|
||||
|
||||
MESSAGE_FUNC_PARAMS( OnAddAnimation, "AddAnimation", data );
|
||||
MESSAGE_FUNC_PARAMS( OnSetAnimation, "SetAnimation", data );
|
||||
|
||||
void SetDefaultAnimation( const char *pszName );
|
||||
void SwapModel( const char *pszName, const char *pszAttached = NULL );
|
||||
|
||||
virtual void ParseModelInfo( KeyValues *inResourceData );
|
||||
|
||||
void ClearAttachedModelInfos( void );
|
||||
|
||||
void CalculateFrameDistance( void );
|
||||
void ZoomToFrameDistance( void );
|
||||
|
||||
void UpdateModel();
|
||||
public: // IGameEventListener:
|
||||
virtual void FireGameEvent( IGameEvent * event );
|
||||
|
||||
protected:
|
||||
virtual void SetupModel( void );
|
||||
virtual void SetupVCD( void );
|
||||
virtual const char *GetModelName( void );
|
||||
|
||||
private:
|
||||
void InitCubeMaps();
|
||||
int FindAnimByName( const char *pszName );
|
||||
void CalculateFrameDistanceInternal( const model_t *pModel );
|
||||
|
||||
public:
|
||||
int m_nFOV;
|
||||
float m_flFrameDistance;
|
||||
bool m_bStartFramed;
|
||||
CModelPanelModelInfo *m_pModelInfo;
|
||||
|
||||
CHandle<CModelPanelModel> m_hModel;
|
||||
CUtlVector<CHandle<C_BaseAnimating> > m_AttachedModels;
|
||||
|
||||
CHandle<C_SceneEntity> m_hScene;
|
||||
|
||||
private:
|
||||
bool m_bPanelDirty;
|
||||
int m_iDefaultAnimation;
|
||||
|
||||
bool m_bAllowOffscreen;
|
||||
|
||||
CTextureReference m_DefaultEnvCubemap;
|
||||
CTextureReference m_DefaultHDREnvCubemap;
|
||||
};
|
||||
|
||||
|
||||
#endif // BASEMODELPANEL_H
|
||||
721
sp/src/game/client/game_controls/baseviewport.cpp
Normal file
721
sp/src/game/client/game_controls/baseviewport.cpp
Normal file
@@ -0,0 +1,721 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Client DLL VGUI2 Viewport
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $Log: $
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#pragma warning( disable : 4800 ) // disable forcing int to bool performance warning
|
||||
|
||||
#include "cbase.h"
|
||||
#include <cdll_client_int.h>
|
||||
#include <cdll_util.h>
|
||||
#include <globalvars_base.h>
|
||||
|
||||
// VGUI panel includes
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include <vgui_controls/AnimationController.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <KeyValues.h>
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui/IVGui.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/IPanel.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
|
||||
#include <igameresources.h>
|
||||
|
||||
// sub dialogs
|
||||
#include "clientscoreboarddialog.h"
|
||||
#include "spectatorgui.h"
|
||||
#include "teammenu.h"
|
||||
#include "vguitextwindow.h"
|
||||
#include "IGameUIFuncs.h"
|
||||
#include "mapoverview.h"
|
||||
#include "hud.h"
|
||||
#include "NavProgress.h"
|
||||
#include "commentary_modelviewer.h"
|
||||
|
||||
// our definition
|
||||
#include "baseviewport.h"
|
||||
#include <filesystem.h>
|
||||
#include <convar.h>
|
||||
#include "ienginevgui.h"
|
||||
#include "iclientmode.h"
|
||||
|
||||
#include "tier0/etwprof.h"
|
||||
|
||||
#if defined( REPLAY_ENABLED )
|
||||
#include "replay/ireplaysystem.h"
|
||||
#include "replay/ienginereplay.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IViewPort *gViewPortInterface = NULL;
|
||||
|
||||
vgui::Panel *g_lastPanel = NULL; // used for mouseover buttons, keeps track of the last active panel
|
||||
vgui::Button *g_lastButton = NULL; // used for mouseover buttons, keeps track of the last active button
|
||||
using namespace vgui;
|
||||
|
||||
ConVar hud_autoreloadscript("hud_autoreloadscript", "0", FCVAR_NONE, "Automatically reloads the animation script each time one is ran");
|
||||
|
||||
static ConVar cl_leveloverviewmarker( "cl_leveloverviewmarker", "0", FCVAR_CHEAT );
|
||||
|
||||
CON_COMMAND( showpanel, "Shows a viewport panel <name>" )
|
||||
{
|
||||
if ( !gViewPortInterface )
|
||||
return;
|
||||
|
||||
if ( args.ArgC() != 2 )
|
||||
return;
|
||||
|
||||
gViewPortInterface->ShowPanel( args[ 1 ], true );
|
||||
}
|
||||
|
||||
CON_COMMAND( hidepanel, "Hides a viewport panel <name>" )
|
||||
{
|
||||
if ( !gViewPortInterface )
|
||||
return;
|
||||
|
||||
if ( args.ArgC() != 2 )
|
||||
return;
|
||||
|
||||
gViewPortInterface->ShowPanel( args[ 1 ], false );
|
||||
}
|
||||
|
||||
/* global helper functions
|
||||
|
||||
bool Helper_LoadFile( IBaseFileSystem *pFileSystem, const char *pFilename, CUtlVector<char> &buf )
|
||||
{
|
||||
FileHandle_t hFile = pFileSystem->Open( pFilename, "rt" );
|
||||
if ( hFile == FILESYSTEM_INVALID_HANDLE )
|
||||
{
|
||||
Warning( "Helper_LoadFile: missing %s\n", pFilename );
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long len = pFileSystem->Size( hFile );
|
||||
buf.SetSize( len );
|
||||
pFileSystem->Read( buf.Base(), buf.Count(), hFile );
|
||||
pFileSystem->Close( hFile );
|
||||
|
||||
return true;
|
||||
} */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseViewport::LoadHudAnimations( void )
|
||||
{
|
||||
const char *HUDANIMATION_MANIFEST_FILE = "scripts/hudanimations_manifest.txt";
|
||||
KeyValues *manifest = new KeyValues( HUDANIMATION_MANIFEST_FILE );
|
||||
if ( manifest->LoadFromFile( g_pFullFileSystem, HUDANIMATION_MANIFEST_FILE, "GAME" ) == false )
|
||||
{
|
||||
manifest->deleteThis();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bClearScript = true;
|
||||
|
||||
// Load each file defined in the text
|
||||
for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() )
|
||||
{
|
||||
if ( !Q_stricmp( sub->GetName(), "file" ) )
|
||||
{
|
||||
// Add it
|
||||
if ( m_pAnimController->SetScriptFile( GetVPanel(), sub->GetString(), bClearScript ) == false )
|
||||
{
|
||||
Assert( 0 );
|
||||
}
|
||||
|
||||
bClearScript = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
manifest->deleteThis();
|
||||
return true;
|
||||
}
|
||||
|
||||
//================================================================
|
||||
CBaseViewport::CBaseViewport() : vgui::EditablePanel( NULL, "CBaseViewport")
|
||||
{
|
||||
SetSize( 10, 10 ); // Quiet "parent not sized yet" spew
|
||||
gViewPortInterface = this;
|
||||
m_bInitialized = false;
|
||||
|
||||
m_GameuiFuncs = NULL;
|
||||
m_GameEventManager = NULL;
|
||||
SetKeyBoardInputEnabled( false );
|
||||
SetMouseInputEnabled( false );
|
||||
|
||||
#ifndef _XBOX
|
||||
m_pBackGround = NULL;
|
||||
#endif
|
||||
m_bHasParent = false;
|
||||
m_pActivePanel = NULL;
|
||||
m_pLastActivePanel = NULL;
|
||||
g_lastPanel = NULL;
|
||||
|
||||
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
|
||||
SetScheme(scheme);
|
||||
SetProportional( true );
|
||||
|
||||
m_pAnimController = new vgui::AnimationController(this);
|
||||
// create our animation controller
|
||||
m_pAnimController->SetScheme(scheme);
|
||||
m_pAnimController->SetProportional(true);
|
||||
|
||||
// Attempt to load all hud animations
|
||||
if ( LoadHudAnimations() == false )
|
||||
{
|
||||
// Fall back to just the main
|
||||
if ( m_pAnimController->SetScriptFile( GetVPanel(), "scripts/HudAnimations.txt", true ) == false )
|
||||
{
|
||||
Assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
m_OldSize[ 0 ] = m_OldSize[ 1 ] = -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Updates hud to handle the new screen size
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseViewport::OnScreenSizeChanged(int iOldWide, int iOldTall)
|
||||
{
|
||||
BaseClass::OnScreenSizeChanged(iOldWide, iOldTall);
|
||||
|
||||
IViewPortPanel* pSpecGuiPanel = FindPanelByName(PANEL_SPECGUI);
|
||||
bool bSpecGuiWasVisible = pSpecGuiPanel && pSpecGuiPanel->IsVisible();
|
||||
|
||||
// reload the script file, so the screen positions in it are correct for the new resolution
|
||||
ReloadScheme( NULL );
|
||||
|
||||
// recreate all the default panels
|
||||
RemoveAllPanels();
|
||||
#ifndef _XBOX
|
||||
m_pBackGround = new CBackGroundPanel( NULL );
|
||||
m_pBackGround->SetZPos( -20 ); // send it to the back
|
||||
m_pBackGround->SetVisible( false );
|
||||
#endif
|
||||
CreateDefaultPanels();
|
||||
#ifndef _XBOX
|
||||
vgui::ipanel()->MoveToBack( m_pBackGround->GetVPanel() ); // really send it to the back
|
||||
#endif
|
||||
|
||||
// hide all panels when reconnecting
|
||||
ShowPanel( PANEL_ALL, false );
|
||||
|
||||
// re-enable the spectator gui if it was previously visible
|
||||
if ( bSpecGuiWasVisible )
|
||||
{
|
||||
ShowPanel( PANEL_SPECGUI, true );
|
||||
}
|
||||
}
|
||||
|
||||
void CBaseViewport::CreateDefaultPanels( void )
|
||||
{
|
||||
#ifndef _XBOX
|
||||
AddNewPanel( CreatePanelByName( PANEL_SCOREBOARD ), "PANEL_SCOREBOARD" );
|
||||
AddNewPanel( CreatePanelByName( PANEL_INFO ), "PANEL_INFO" );
|
||||
AddNewPanel( CreatePanelByName( PANEL_SPECGUI ), "PANEL_SPECGUI" );
|
||||
AddNewPanel( CreatePanelByName( PANEL_SPECMENU ), "PANEL_SPECMENU" );
|
||||
AddNewPanel( CreatePanelByName( PANEL_NAV_PROGRESS ), "PANEL_NAV_PROGRESS" );
|
||||
// AddNewPanel( CreatePanelByName( PANEL_TEAM ), "PANEL_TEAM" );
|
||||
// AddNewPanel( CreatePanelByName( PANEL_CLASS ), "PANEL_CLASS" );
|
||||
// AddNewPanel( CreatePanelByName( PANEL_BUY ), "PANEL_BUY" );
|
||||
#endif
|
||||
}
|
||||
|
||||
void CBaseViewport::UpdateAllPanels( void )
|
||||
{
|
||||
int count = m_Panels.Count();
|
||||
|
||||
for (int i=0; i< count; i++ )
|
||||
{
|
||||
IViewPortPanel *p = m_Panels[i];
|
||||
|
||||
if ( p->IsVisible() )
|
||||
{
|
||||
p->Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IViewPortPanel* CBaseViewport::CreatePanelByName(const char *szPanelName)
|
||||
{
|
||||
IViewPortPanel* newpanel = NULL;
|
||||
|
||||
#ifndef _XBOX
|
||||
if ( Q_strcmp(PANEL_SCOREBOARD, szPanelName) == 0 )
|
||||
{
|
||||
newpanel = new CClientScoreBoardDialog( this );
|
||||
}
|
||||
else if ( Q_strcmp(PANEL_INFO, szPanelName) == 0 )
|
||||
{
|
||||
newpanel = new CTextWindow( this );
|
||||
}
|
||||
/* else if ( Q_strcmp(PANEL_OVERVIEW, szPanelName) == 0 )
|
||||
{
|
||||
newpanel = new CMapOverview( this );
|
||||
}
|
||||
*/
|
||||
else if ( Q_strcmp(PANEL_TEAM, szPanelName) == 0 )
|
||||
{
|
||||
newpanel = new CTeamMenu( this );
|
||||
}
|
||||
else if ( Q_strcmp(PANEL_SPECMENU, szPanelName) == 0 )
|
||||
{
|
||||
newpanel = new CSpectatorMenu( this );
|
||||
}
|
||||
else if ( Q_strcmp(PANEL_SPECGUI, szPanelName) == 0 )
|
||||
{
|
||||
newpanel = new CSpectatorGUI( this );
|
||||
}
|
||||
#if !defined( TF_CLIENT_DLL )
|
||||
else if ( Q_strcmp(PANEL_NAV_PROGRESS, szPanelName) == 0 )
|
||||
{
|
||||
newpanel = new CNavProgress( this );
|
||||
}
|
||||
#endif // TF_CLIENT_DLL
|
||||
#endif
|
||||
|
||||
if ( Q_strcmp(PANEL_COMMENTARY_MODELVIEWER, szPanelName) == 0 )
|
||||
{
|
||||
newpanel = new CCommentaryModelViewer( this );
|
||||
}
|
||||
|
||||
return newpanel;
|
||||
}
|
||||
|
||||
|
||||
bool CBaseViewport::AddNewPanel( IViewPortPanel* pPanel, char const *pchDebugName )
|
||||
{
|
||||
if ( !pPanel )
|
||||
{
|
||||
DevMsg("CBaseViewport::AddNewPanel(%s): NULL panel.\n", pchDebugName );
|
||||
return false;
|
||||
}
|
||||
|
||||
// we created a new panel, initialize it
|
||||
if ( FindPanelByName( pPanel->GetName() ) != NULL )
|
||||
{
|
||||
DevMsg("CBaseViewport::AddNewPanel: panel with name '%s' already exists.\n", pPanel->GetName() );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Panels.AddToTail( pPanel );
|
||||
pPanel->SetParent( GetVPanel() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IViewPortPanel* CBaseViewport::FindPanelByName(const char *szPanelName)
|
||||
{
|
||||
int count = m_Panels.Count();
|
||||
|
||||
for (int i=0; i< count; i++ )
|
||||
{
|
||||
if ( Q_strcmp(m_Panels[i]->GetName(), szPanelName) == 0 )
|
||||
return m_Panels[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CBaseViewport::PostMessageToPanel( IViewPortPanel* pPanel, KeyValues *pKeyValues )
|
||||
{
|
||||
PostMessage( pPanel->GetVPanel(), pKeyValues );
|
||||
}
|
||||
|
||||
void CBaseViewport::PostMessageToPanel( const char *pName, KeyValues *pKeyValues )
|
||||
{
|
||||
if ( Q_strcmp( pName, PANEL_ALL ) == 0 )
|
||||
{
|
||||
for (int i=0; i< m_Panels.Count(); i++ )
|
||||
{
|
||||
PostMessageToPanel( m_Panels[i], pKeyValues );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
IViewPortPanel * panel = NULL;
|
||||
|
||||
if ( Q_strcmp( pName, PANEL_ACTIVE ) == 0 )
|
||||
{
|
||||
panel = m_pActivePanel;
|
||||
}
|
||||
else
|
||||
{
|
||||
panel = FindPanelByName( pName );
|
||||
}
|
||||
|
||||
if ( !panel )
|
||||
return;
|
||||
|
||||
PostMessageToPanel( panel, pKeyValues );
|
||||
}
|
||||
|
||||
|
||||
void CBaseViewport::ShowPanel( const char *pName, bool state )
|
||||
{
|
||||
if ( Q_strcmp( pName, PANEL_ALL ) == 0 )
|
||||
{
|
||||
for (int i=0; i< m_Panels.Count(); i++ )
|
||||
{
|
||||
ShowPanel( m_Panels[i], state );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
IViewPortPanel * panel = NULL;
|
||||
|
||||
if ( Q_strcmp( pName, PANEL_ACTIVE ) == 0 )
|
||||
{
|
||||
panel = m_pActivePanel;
|
||||
}
|
||||
else
|
||||
{
|
||||
panel = FindPanelByName( pName );
|
||||
}
|
||||
|
||||
if ( !panel )
|
||||
return;
|
||||
|
||||
ShowPanel( panel, state );
|
||||
}
|
||||
|
||||
void CBaseViewport::ShowPanel( IViewPortPanel* pPanel, bool state )
|
||||
{
|
||||
if ( state )
|
||||
{
|
||||
// if this is an 'active' panel, deactivate old active panel
|
||||
if ( pPanel->HasInputElements() )
|
||||
{
|
||||
// don't show input panels during normal demo playback
|
||||
#if defined( REPLAY_ENABLED )
|
||||
if ( engine->IsPlayingDemo() && !engine->IsHLTV() && !g_pEngineClientReplay->IsPlayingReplayDemo() )
|
||||
#else
|
||||
if ( engine->IsPlayingDemo() && !engine->IsHLTV() )
|
||||
#endif
|
||||
return;
|
||||
if ( (m_pActivePanel != NULL) && (m_pActivePanel != pPanel) && (m_pActivePanel->IsVisible()) )
|
||||
{
|
||||
// store a pointer to the currently active panel
|
||||
// so we can restore it later
|
||||
m_pLastActivePanel = m_pActivePanel;
|
||||
m_pActivePanel->ShowPanel( false );
|
||||
}
|
||||
|
||||
m_pActivePanel = pPanel;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if this is our current active panel
|
||||
// update m_pActivePanel pointer
|
||||
if ( m_pActivePanel == pPanel )
|
||||
{
|
||||
m_pActivePanel = NULL;
|
||||
}
|
||||
|
||||
// restore the previous active panel if it exists
|
||||
if( m_pLastActivePanel )
|
||||
{
|
||||
m_pActivePanel = m_pLastActivePanel;
|
||||
m_pLastActivePanel = NULL;
|
||||
|
||||
m_pActivePanel->ShowPanel( true );
|
||||
}
|
||||
}
|
||||
|
||||
// just show/hide panel
|
||||
pPanel->ShowPanel( state );
|
||||
|
||||
UpdateAllPanels(); // let other panels rearrange
|
||||
}
|
||||
|
||||
IViewPortPanel* CBaseViewport::GetActivePanel( void )
|
||||
{
|
||||
return m_pActivePanel;
|
||||
}
|
||||
|
||||
void CBaseViewport::RemoveAllPanels( void)
|
||||
{
|
||||
g_lastPanel = NULL;
|
||||
for ( int i=0; i < m_Panels.Count(); i++ )
|
||||
{
|
||||
vgui::VPANEL vPanel = m_Panels[i]->GetVPanel();
|
||||
vgui::ipanel()->DeletePanel( vPanel );
|
||||
}
|
||||
#ifndef _XBOX
|
||||
if ( m_pBackGround )
|
||||
{
|
||||
m_pBackGround->MarkForDeletion();
|
||||
m_pBackGround = NULL;
|
||||
}
|
||||
#endif
|
||||
m_Panels.Purge();
|
||||
m_pActivePanel = NULL;
|
||||
m_pLastActivePanel = NULL;
|
||||
}
|
||||
|
||||
CBaseViewport::~CBaseViewport()
|
||||
{
|
||||
m_bInitialized = false;
|
||||
|
||||
#ifndef _XBOX
|
||||
if ( !m_bHasParent && m_pBackGround )
|
||||
{
|
||||
m_pBackGround->MarkForDeletion();
|
||||
}
|
||||
m_pBackGround = NULL;
|
||||
#endif
|
||||
RemoveAllPanels();
|
||||
|
||||
gameeventmanager->RemoveListener( this );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: called when the VGUI subsystem starts up
|
||||
// Creates the sub panels and initialises them
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseViewport::Start( IGameUIFuncs *pGameUIFuncs, IGameEventManager2 * pGameEventManager )
|
||||
{
|
||||
m_GameuiFuncs = pGameUIFuncs;
|
||||
m_GameEventManager = pGameEventManager;
|
||||
#ifndef _XBOX
|
||||
m_pBackGround = new CBackGroundPanel( NULL );
|
||||
m_pBackGround->SetZPos( -20 ); // send it to the back
|
||||
m_pBackGround->SetVisible( false );
|
||||
#endif
|
||||
CreateDefaultPanels();
|
||||
|
||||
m_GameEventManager->AddListener( this, "game_newmap", false );
|
||||
|
||||
m_bInitialized = true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Updates the spectator panel with new player info
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseViewport::UpdateSpectatorPanel()
|
||||
{
|
||||
char bottomText[128];
|
||||
int player = -1;
|
||||
const char *name;
|
||||
Q_snprintf(bottomText,sizeof( bottomText ), "#Spec_Mode%d", m_pClientDllInterface->SpectatorMode() );
|
||||
|
||||
m_pClientDllInterface->CheckSettings();
|
||||
// check if we're locked onto a target, show the player's name
|
||||
if ( (m_pClientDllInterface->SpectatorTarget() > 0) && (m_pClientDllInterface->SpectatorTarget() <= m_pClientDllInterface->GetMaxPlayers()) && (m_pClientDllInterface->SpectatorMode() != OBS_ROAMING) )
|
||||
{
|
||||
player = m_pClientDllInterface->SpectatorTarget();
|
||||
}
|
||||
|
||||
// special case in free map and inset off, don't show names
|
||||
if ( ((m_pClientDllInterface->SpectatorMode() == OBS_MAP_FREE) && !m_pClientDllInterface->PipInsetOff()) || player == -1 )
|
||||
name = NULL;
|
||||
else
|
||||
name = m_pClientDllInterface->GetPlayerInfo(player).name;
|
||||
|
||||
// create player & health string
|
||||
if ( player && name )
|
||||
{
|
||||
Q_strncpy( bottomText, name, sizeof( bottomText ) );
|
||||
}
|
||||
char szMapName[64];
|
||||
Q_FileBase( const_cast<char *>(m_pClientDllInterface->GetLevelName()), szMapName );
|
||||
|
||||
m_pSpectatorGUI->Update(bottomText, player, m_pClientDllInterface->SpectatorMode(), m_pClientDllInterface->IsSpectateOnly(), m_pClientDllInterface->SpectatorNumber(), szMapName );
|
||||
m_pSpectatorGUI->UpdateSpectatorPlayerList();
|
||||
} */
|
||||
|
||||
// Return TRUE if the HUD's allowed to print text messages
|
||||
bool CBaseViewport::AllowedToPrintText( void )
|
||||
{
|
||||
|
||||
/* int iId = GetCurrentMenuID();
|
||||
if ( iId == MENU_TEAM || iId == MENU_CLASS || iId == MENU_INTRO || iId == MENU_CLASSHELP )
|
||||
return false; */
|
||||
// TODO ask every aktive elemet if it allows to draw text while visible
|
||||
|
||||
return ( m_pActivePanel == NULL);
|
||||
}
|
||||
|
||||
void CBaseViewport::OnThink()
|
||||
{
|
||||
// Clear our active panel pointer if the panel has made
|
||||
// itself invisible. Need this so we don't bring up dead panels
|
||||
// if they are stored as the last active panel
|
||||
if( m_pActivePanel && !m_pActivePanel->IsVisible() )
|
||||
{
|
||||
if( m_pLastActivePanel )
|
||||
{
|
||||
m_pActivePanel = m_pLastActivePanel;
|
||||
ShowPanel( m_pActivePanel, true );
|
||||
m_pLastActivePanel = NULL;
|
||||
}
|
||||
else
|
||||
m_pActivePanel = NULL;
|
||||
}
|
||||
|
||||
m_pAnimController->UpdateAnimations( gpGlobals->curtime );
|
||||
|
||||
// check the auto-reload cvar
|
||||
m_pAnimController->SetAutoReloadScript(hud_autoreloadscript.GetBool());
|
||||
|
||||
int count = m_Panels.Count();
|
||||
|
||||
for (int i=0; i< count; i++ )
|
||||
{
|
||||
IViewPortPanel *panel = m_Panels[i];
|
||||
if ( panel->NeedsUpdate() && panel->IsVisible() )
|
||||
{
|
||||
panel->Update();
|
||||
}
|
||||
}
|
||||
|
||||
int w, h;
|
||||
vgui::ipanel()->GetSize( enginevgui->GetPanel( PANEL_CLIENTDLL ), w, h );
|
||||
|
||||
if ( m_OldSize[ 0 ] != w || m_OldSize[ 1 ] != h )
|
||||
{
|
||||
m_OldSize[ 0 ] = w;
|
||||
m_OldSize[ 1 ] = h;
|
||||
g_pClientMode->Layout();
|
||||
}
|
||||
|
||||
BaseClass::OnThink();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the parent for each panel to use
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseViewport::SetParent(vgui::VPANEL parent)
|
||||
{
|
||||
EditablePanel::SetParent( parent );
|
||||
// force ourselves to be proportional - when we set our parent above, if our new
|
||||
// parent happened to be non-proportional (such as the vgui root panel), we got
|
||||
// slammed to be nonproportional
|
||||
EditablePanel::SetProportional( true );
|
||||
|
||||
#ifndef _XBOX
|
||||
m_pBackGround->SetParent( (vgui::VPANEL)parent );
|
||||
#endif
|
||||
|
||||
// set proportionality on animation controller
|
||||
m_pAnimController->SetProportional( true );
|
||||
|
||||
m_bHasParent = (parent != 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: called when the engine shows the base client VGUI panel (i.e when entering a new level or exiting GameUI )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseViewport::ActivateClientUI()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: called when the engine hides the base client VGUI panel (i.e when the GameUI is comming up )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseViewport::HideClientUI()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: passes death msgs to the scoreboard to display specially
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseViewport::FireGameEvent( IGameEvent * event)
|
||||
{
|
||||
const char * type = event->GetName();
|
||||
|
||||
if ( Q_strcmp(type, "game_newmap") == 0 )
|
||||
{
|
||||
// hide all panels when reconnecting
|
||||
ShowPanel( PANEL_ALL, false );
|
||||
|
||||
if ( engine->IsHLTV() )
|
||||
{
|
||||
ShowPanel( PANEL_SPECGUI, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseViewport::ReloadScheme(const char *fromFile)
|
||||
{
|
||||
CETWScope timer( "CBaseViewport::ReloadScheme" );
|
||||
|
||||
// See if scheme should change
|
||||
|
||||
if ( fromFile != NULL )
|
||||
{
|
||||
// "resource/ClientScheme.res"
|
||||
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), fromFile, "HudScheme" );
|
||||
|
||||
SetScheme(scheme);
|
||||
SetProportional( true );
|
||||
m_pAnimController->SetScheme(scheme);
|
||||
}
|
||||
|
||||
// Force a reload
|
||||
if ( LoadHudAnimations() == false )
|
||||
{
|
||||
// Fall back to just the main
|
||||
if ( m_pAnimController->SetScriptFile( GetVPanel(), "scripts/HudAnimations.txt", true ) == false )
|
||||
{
|
||||
Assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
SetProportional( true );
|
||||
|
||||
KeyValuesAD pConditions( "conditions" );
|
||||
g_pClientMode->ComputeVguiResConditions( pConditions );
|
||||
|
||||
// reload the .res file from disk
|
||||
LoadControlSettings( "scripts/HudLayout.res", NULL, NULL, pConditions );
|
||||
|
||||
gHUD.RefreshHudTextures();
|
||||
|
||||
InvalidateLayout( true, true );
|
||||
|
||||
// reset the hud
|
||||
gHUD.ResetHUD();
|
||||
}
|
||||
|
||||
int CBaseViewport::GetDeathMessageStartHeight( void )
|
||||
{
|
||||
return YRES(2);
|
||||
}
|
||||
|
||||
void CBaseViewport::Paint()
|
||||
{
|
||||
if ( cl_leveloverviewmarker.GetInt() > 0 )
|
||||
{
|
||||
int size = cl_leveloverviewmarker.GetInt();
|
||||
// draw a 1024x1024 pixel box
|
||||
vgui::surface()->DrawSetColor( 255, 0, 0, 255 );
|
||||
vgui::surface()->DrawLine( size, 0, size, size );
|
||||
vgui::surface()->DrawLine( 0, size, size, size );
|
||||
}
|
||||
}
|
||||
148
sp/src/game/client/game_controls/baseviewport.h
Normal file
148
sp/src/game/client/game_controls/baseviewport.h
Normal file
@@ -0,0 +1,148 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef TEAMFORTRESSVIEWPORT_H
|
||||
#define TEAMFORTRESSVIEWPORT_H
|
||||
|
||||
// viewport interface for the rest of the dll
|
||||
#include <game/client/iviewport.h>
|
||||
|
||||
#include <utlqueue.h> // a vector based queue template to manage our VGUI menu queue
|
||||
#include <vgui_controls/Frame.h>
|
||||
#include "vguitextwindow.h"
|
||||
#include "vgui/ISurface.h"
|
||||
#include "commandmenu.h"
|
||||
#include <igameevents.h>
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
class IBaseFileSystem;
|
||||
class IGameUIFuncs;
|
||||
class IGameEventManager;
|
||||
|
||||
//==============================================================================
|
||||
class CBaseViewport : public vgui::EditablePanel, public IViewPort, public IGameEventListener2
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CBaseViewport, vgui::EditablePanel );
|
||||
|
||||
public:
|
||||
CBaseViewport();
|
||||
virtual ~CBaseViewport();
|
||||
|
||||
virtual IViewPortPanel* CreatePanelByName(const char *szPanelName);
|
||||
virtual IViewPortPanel* FindPanelByName(const char *szPanelName);
|
||||
virtual IViewPortPanel* GetActivePanel( void );
|
||||
virtual void RemoveAllPanels( void);
|
||||
|
||||
virtual void ShowPanel( const char *pName, bool state );
|
||||
virtual void ShowPanel( IViewPortPanel* pPanel, bool state );
|
||||
virtual bool AddNewPanel( IViewPortPanel* pPanel, char const *pchDebugName );
|
||||
virtual void CreateDefaultPanels( void );
|
||||
virtual void UpdateAllPanels( void );
|
||||
virtual void PostMessageToPanel( const char *pName, KeyValues *pKeyValues );
|
||||
|
||||
virtual void Start( IGameUIFuncs *pGameUIFuncs, IGameEventManager2 *pGameEventManager );
|
||||
virtual void SetParent(vgui::VPANEL parent);
|
||||
|
||||
virtual void ReloadScheme(const char *fromFile);
|
||||
virtual void ActivateClientUI();
|
||||
virtual void HideClientUI();
|
||||
virtual bool AllowedToPrintText( void );
|
||||
|
||||
#ifndef _XBOX
|
||||
virtual int GetViewPortScheme() { return m_pBackGround->GetScheme(); }
|
||||
virtual VPANEL GetViewPortPanel() { return m_pBackGround->GetVParent(); }
|
||||
#endif
|
||||
virtual AnimationController *GetAnimationController() { return m_pAnimController; }
|
||||
|
||||
virtual void ShowBackGround(bool bShow)
|
||||
{
|
||||
#ifndef _XBOX
|
||||
m_pBackGround->SetVisible( bShow );
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual int GetDeathMessageStartHeight( void );
|
||||
|
||||
// virtual void ChatInputPosition( int *x, int *y );
|
||||
|
||||
public: // IGameEventListener:
|
||||
virtual void FireGameEvent( IGameEvent * event);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
bool LoadHudAnimations( void );
|
||||
|
||||
#ifndef _XBOX
|
||||
class CBackGroundPanel : public vgui::Frame
|
||||
{
|
||||
private:
|
||||
typedef vgui::Frame BaseClass;
|
||||
public:
|
||||
CBackGroundPanel( vgui::Panel *parent) : Frame( parent, "ViewPortBackGround" )
|
||||
{
|
||||
SetScheme("ClientScheme");
|
||||
|
||||
SetTitleBarVisible( false );
|
||||
SetMoveable(false);
|
||||
SetSizeable(false);
|
||||
SetProportional(true);
|
||||
}
|
||||
private:
|
||||
|
||||
virtual void ApplySchemeSettings(IScheme *pScheme)
|
||||
{
|
||||
BaseClass::ApplySchemeSettings(pScheme);
|
||||
SetBgColor(pScheme->GetColor("ViewportBG", Color( 0,0,0,0 ) ));
|
||||
}
|
||||
|
||||
virtual void PerformLayout()
|
||||
{
|
||||
int w,h;
|
||||
GetHudSize(w, h);
|
||||
|
||||
// fill the screen
|
||||
SetBounds(0,0,w,h);
|
||||
|
||||
BaseClass::PerformLayout();
|
||||
}
|
||||
|
||||
virtual void OnMousePressed(MouseCode code) { }// don't respond to mouse clicks
|
||||
virtual vgui::VPANEL IsWithinTraverse( int x, int y, bool traversePopups )
|
||||
{
|
||||
return ( vgui::VPANEL )0;
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
protected:
|
||||
|
||||
virtual void Paint();
|
||||
virtual void OnThink();
|
||||
virtual void OnScreenSizeChanged(int iOldWide, int iOldTall);
|
||||
void PostMessageToPanel( IViewPortPanel* pPanel, KeyValues *pKeyValues );
|
||||
|
||||
protected:
|
||||
IGameUIFuncs* m_GameuiFuncs; // for key binding details
|
||||
IGameEventManager2* m_GameEventManager;
|
||||
#ifndef _XBOX
|
||||
CBackGroundPanel *m_pBackGround;
|
||||
#endif
|
||||
CUtlVector<IViewPortPanel*> m_Panels;
|
||||
|
||||
bool m_bHasParent; // Used to track if child windows have parents or not.
|
||||
bool m_bInitialized;
|
||||
IViewPortPanel *m_pActivePanel;
|
||||
IViewPortPanel *m_pLastActivePanel;
|
||||
vgui::HCursor m_hCursorNone;
|
||||
vgui::AnimationController *m_pAnimController;
|
||||
int m_OldSize[2];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
149
sp/src/game/client/game_controls/buymenu.cpp
Normal file
149
sp/src/game/client/game_controls/buymenu.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "buymenu.h"
|
||||
|
||||
#include "buysubmenu.h"
|
||||
using namespace vgui;
|
||||
|
||||
#include "mouseoverpanelbutton.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CBuyMenu::CBuyMenu(IViewPort *pViewPort) : WizardPanel( NULL, PANEL_BUY )
|
||||
{
|
||||
SetScheme("ClientScheme");
|
||||
SetTitle( "#Cstrike_Buy_Menu", true);
|
||||
|
||||
SetMoveable(false);
|
||||
SetSizeable(false);
|
||||
SetProportional(true);
|
||||
|
||||
// hide the system buttons
|
||||
SetTitleBarVisible( false );
|
||||
|
||||
SetAutoDelete( false ); // we reuse this panel, don't let WizardPanel delete us
|
||||
|
||||
LoadControlSettings( "Resource/UI/BuyMenu.res" );
|
||||
ShowButtons( false );
|
||||
|
||||
m_pViewPort = pViewPort;
|
||||
|
||||
m_pMainMenu = new CBuySubMenu( this, "mainmenu" );
|
||||
m_pMainMenu->LoadControlSettings( "Resource/UI/MainBuyMenu.res" );
|
||||
m_pMainMenu->SetVisible( false );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CBuyMenu::~CBuyMenu()
|
||||
{
|
||||
if ( m_pMainMenu )
|
||||
m_pMainMenu->DeleteSubPanels(); //?
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: shows/hides the buy menu
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBuyMenu::ShowPanel(bool bShow)
|
||||
{
|
||||
if ( BaseClass::IsVisible() == bShow )
|
||||
return;
|
||||
|
||||
if ( bShow )
|
||||
{
|
||||
Update();
|
||||
|
||||
Run( m_pMainMenu );
|
||||
|
||||
SetMouseInputEnabled( true );
|
||||
|
||||
engine->ClientCmd_Unrestricted( "gameui_preventescapetoshow\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" );
|
||||
|
||||
SetVisible( false );
|
||||
SetMouseInputEnabled( false );
|
||||
}
|
||||
|
||||
m_pViewPort->ShowBackGround( bShow );
|
||||
}
|
||||
|
||||
|
||||
void CBuyMenu::Update()
|
||||
{
|
||||
//Don't need to do anything, but do need to implement this function as base is pure virtual
|
||||
}
|
||||
void CBuyMenu::OnClose()
|
||||
{
|
||||
engine->ClientCmd_Unrestricted( "gameui_allowescapetoshow\n" );
|
||||
|
||||
BaseClass::OnClose();
|
||||
ResetHistory();
|
||||
}
|
||||
|
||||
void CBuyMenu::OnKeyCodePressed( vgui::KeyCode code )
|
||||
{
|
||||
int nDir = 0;
|
||||
|
||||
switch ( code )
|
||||
{
|
||||
case KEY_XBUTTON_UP:
|
||||
case KEY_XSTICK1_UP:
|
||||
case KEY_XSTICK2_UP:
|
||||
case KEY_UP:
|
||||
nDir = -1;
|
||||
break;
|
||||
|
||||
case KEY_XBUTTON_DOWN:
|
||||
case KEY_XSTICK1_DOWN:
|
||||
case KEY_XSTICK2_DOWN:
|
||||
case KEY_DOWN:
|
||||
nDir = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( nDir != 0 )
|
||||
{
|
||||
Panel *pSubPanel = ( GetCurrentSubPanel() ? GetCurrentSubPanel() : m_pMainMenu );
|
||||
|
||||
CUtlSortVector< SortedPanel_t, CSortedPanelYLess > vecSortedButtons;
|
||||
VguiPanelGetSortedChildButtonList( pSubPanel, (void*)&vecSortedButtons, "&", 0 );
|
||||
|
||||
if ( VguiPanelNavigateSortedChildButtonList( (void*)&vecSortedButtons, nDir ) != -1 )
|
||||
{
|
||||
// Handled!
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseClass::OnKeyCodePressed( code );
|
||||
}
|
||||
}
|
||||
|
||||
void CBuyMenu::OnKeyCodeTyped( KeyCode code )
|
||||
{
|
||||
if ( code == KEY_ESCAPE )
|
||||
{
|
||||
OnClose();
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseClass::OnKeyCodeTyped( code );
|
||||
}
|
||||
}
|
||||
|
||||
66
sp/src/game/client/game_controls/buymenu.h
Normal file
66
sp/src/game/client/game_controls/buymenu.h
Normal file
@@ -0,0 +1,66 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BUYMENU_H
|
||||
#define BUYMENU_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui_controls/WizardPanel.h>
|
||||
#include <game/client/iviewport.h>
|
||||
#include "vgui/KeyCode.h"
|
||||
|
||||
class CBuySubMenu;
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
class Panel;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draws the class menu
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBuyMenu : public vgui::WizardPanel, public IViewPortPanel
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CBuyMenu, vgui::WizardPanel );
|
||||
|
||||
public:
|
||||
CBuyMenu(IViewPort *pViewPort);
|
||||
~CBuyMenu();
|
||||
|
||||
virtual const char *GetName( void ) { return PANEL_BUY; }
|
||||
virtual void SetData(KeyValues *data) {};
|
||||
virtual void Reset() {};
|
||||
virtual void Update();
|
||||
virtual bool NeedsUpdate( void ) { return false; }
|
||||
virtual bool HasInputElements( void ) { return true; }
|
||||
virtual void ShowPanel( bool bShow );
|
||||
|
||||
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
|
||||
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
|
||||
virtual bool IsVisible() { return BaseClass::IsVisible(); }
|
||||
virtual void SetParent( vgui::VPANEL parent ) { BaseClass::SetParent( parent ); }
|
||||
|
||||
virtual void OnKeyCodePressed( vgui::KeyCode code );
|
||||
virtual void OnKeyCodeTyped( vgui::KeyCode code );
|
||||
|
||||
public:
|
||||
virtual void OnClose();
|
||||
|
||||
protected:
|
||||
|
||||
CBuySubMenu *m_pMainMenu;
|
||||
IViewPort *m_pViewPort;
|
||||
|
||||
int m_iTeam;
|
||||
int m_iClass;
|
||||
};
|
||||
|
||||
|
||||
#endif // BUYMENU_H
|
||||
171
sp/src/game/client/game_controls/buysubmenu.cpp
Normal file
171
sp/src/game/client/game_controls/buysubmenu.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "buysubmenu.h"
|
||||
|
||||
#include <KeyValues.h>
|
||||
#include <vgui_controls/WizardPanel.h>
|
||||
#include <filesystem.h>
|
||||
#include <game/client/iviewport.h>
|
||||
#include <cdll_client_int.h>
|
||||
|
||||
#include "mouseoverpanelbutton.h"
|
||||
// #include "cs_gamerules.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CBuySubMenu::CBuySubMenu(vgui::Panel *parent, const char *name) : WizardSubPanel(parent, name)
|
||||
{
|
||||
m_NextPanel = NULL;
|
||||
m_pFirstButton = NULL;
|
||||
SetProportional(true);
|
||||
|
||||
m_pPanel = new EditablePanel( this, "ItemInfo" );// info window about these items
|
||||
m_pPanel->SetProportional( true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CBuySubMenu::~CBuySubMenu()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: magic override to allow vgui to create mouse over buttons for us
|
||||
//-----------------------------------------------------------------------------
|
||||
Panel *CBuySubMenu::CreateControlByName( const char *controlName )
|
||||
{
|
||||
if( !Q_stricmp( "MouseOverPanelButton", controlName ) )
|
||||
{
|
||||
MouseOverPanelButton *newButton = CreateNewMouseOverPanelButton( m_pPanel );
|
||||
|
||||
if( !m_pFirstButton )
|
||||
{
|
||||
m_pFirstButton = newButton;
|
||||
}
|
||||
return newButton;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::CreateControlByName( controlName );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Make the first buttons page get displayed when the menu becomes visible
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBuySubMenu::SetVisible( bool state )
|
||||
{
|
||||
BaseClass::SetVisible( state );
|
||||
|
||||
for( int i = 0; i< GetChildCount(); i++ ) // get all the buy buttons to performlayout
|
||||
{
|
||||
MouseOverPanelButton *buyButton = dynamic_cast<MouseOverPanelButton *>(GetChild(i));
|
||||
if ( buyButton )
|
||||
{
|
||||
if( buyButton == m_pFirstButton && state == true )
|
||||
buyButton->ShowPage();
|
||||
else
|
||||
buyButton->HidePage();
|
||||
|
||||
buyButton->InvalidateLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CBuySubMenu* CBuySubMenu::CreateNewSubMenu()
|
||||
{
|
||||
return new CBuySubMenu( this );
|
||||
}
|
||||
|
||||
MouseOverPanelButton* CBuySubMenu::CreateNewMouseOverPanelButton(EditablePanel *panel)
|
||||
{
|
||||
return new MouseOverPanelButton(this, NULL, panel);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called when the user picks a class
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBuySubMenu::OnCommand( const char *command)
|
||||
{
|
||||
if ( Q_strstr( command, ".res" ) ) // if its a .res file then its a new menu
|
||||
{
|
||||
int i;
|
||||
// check the cache
|
||||
for ( i = 0; i < m_SubMenus.Count(); i++ )
|
||||
{
|
||||
if ( !Q_stricmp( m_SubMenus[i].filename, command ) )
|
||||
{
|
||||
m_NextPanel = m_SubMenus[i].panel;
|
||||
Assert( m_NextPanel );
|
||||
m_NextPanel->InvalidateLayout(); // force it to reset it prices
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( i == m_SubMenus.Count() )
|
||||
{
|
||||
// not there, add a new entry
|
||||
SubMenuEntry_t newEntry;
|
||||
memset( &newEntry, 0x0, sizeof( newEntry ) );
|
||||
|
||||
CBuySubMenu *newMenu = CreateNewSubMenu();
|
||||
newMenu->LoadControlSettings( command );
|
||||
m_NextPanel = newMenu;
|
||||
Q_strncpy( newEntry.filename, command, sizeof( newEntry.filename ) );
|
||||
newEntry.panel = newMenu;
|
||||
m_SubMenus.AddToTail( newEntry );
|
||||
}
|
||||
|
||||
GetWizardPanel()->OnNextButton();
|
||||
}
|
||||
else
|
||||
{
|
||||
GetWizardPanel()->Close();
|
||||
gViewPortInterface->ShowBackGround( false );
|
||||
|
||||
if ( Q_stricmp( command, "vguicancel" ) != 0 )
|
||||
engine->ClientCmd( command );
|
||||
|
||||
BaseClass::OnCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Causes the panel to delete itself when it closes
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBuySubMenu::DeleteSubPanels()
|
||||
{
|
||||
if ( m_NextPanel )
|
||||
{
|
||||
m_NextPanel->SetVisible( false );
|
||||
m_NextPanel = NULL;
|
||||
}
|
||||
|
||||
m_pFirstButton = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: return the next panel to show
|
||||
//-----------------------------------------------------------------------------
|
||||
vgui::WizardSubPanel *CBuySubMenu::GetNextSubPanel()
|
||||
{
|
||||
return m_NextPanel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
59
sp/src/game/client/game_controls/buysubmenu.h
Normal file
59
sp/src/game/client/game_controls/buysubmenu.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BUYSUBMENU_H
|
||||
#define BUYSUBMENU_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui_controls/WizardSubPanel.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
#include <utlvector.h>
|
||||
#include "mouseoverpanelbutton.h"
|
||||
|
||||
class CBuyMenu;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draws the class menu
|
||||
//-----------------------------------------------------------------------------
|
||||
class CBuySubMenu : public vgui::WizardSubPanel
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CBuySubMenu, vgui::WizardSubPanel );
|
||||
|
||||
public:
|
||||
CBuySubMenu(vgui::Panel *parent,const char *name = "BuySubMenu");
|
||||
~CBuySubMenu();
|
||||
|
||||
virtual void SetVisible( bool state );
|
||||
virtual void DeleteSubPanels();
|
||||
|
||||
protected:
|
||||
|
||||
// command callbacks
|
||||
virtual void OnCommand( const char *command );
|
||||
virtual vgui::WizardSubPanel *GetNextSubPanel(); // this is the last menu in the list
|
||||
virtual vgui::Panel *CreateControlByName(const char *controlName);
|
||||
virtual CBuySubMenu* CreateNewSubMenu();
|
||||
virtual MouseOverPanelButton* CreateNewMouseOverPanelButton(vgui::EditablePanel *panel);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char filename[_MAX_PATH];
|
||||
CBuySubMenu *panel;
|
||||
} SubMenuEntry_t;
|
||||
|
||||
vgui::EditablePanel *m_pPanel;
|
||||
MouseOverPanelButton *m_pFirstButton;
|
||||
|
||||
CUtlVector<SubMenuEntry_t> m_SubMenus; // a cache of buy submenus, so we don't need to construct them each time
|
||||
|
||||
vgui::WizardSubPanel *m_NextPanel;
|
||||
};
|
||||
|
||||
#endif // BUYSUBMENU_H
|
||||
316
sp/src/game/client/game_controls/classmenu.cpp
Normal file
316
sp/src/game/client/game_controls/classmenu.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
|
||||
#include "cbase.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cdll_client_int.h>
|
||||
|
||||
#include "classmenu.h"
|
||||
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <KeyValues.h>
|
||||
#include <vgui_controls/ImageList.h>
|
||||
#include <filesystem.h>
|
||||
|
||||
#include <vgui_controls/TextEntry.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
|
||||
#include "cdll_util.h"
|
||||
#include "IGameUIFuncs.h" // for key bindings
|
||||
#ifndef _XBOX
|
||||
extern IGameUIFuncs *gameuifuncs; // for key binding details
|
||||
#endif
|
||||
#include <game/client/iviewport.h>
|
||||
|
||||
#include <stdlib.h> // MAX_PATH define
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
#ifdef TF_CLIENT_DLL
|
||||
#define HUD_CLASSAUTOKILL_FLAGS ( FCVAR_CLIENTDLL | FCVAR_ARCHIVE | FCVAR_USERINFO )
|
||||
#else
|
||||
#define HUD_CLASSAUTOKILL_FLAGS ( FCVAR_CLIENTDLL | FCVAR_ARCHIVE )
|
||||
#endif // !TF_CLIENT_DLL
|
||||
|
||||
ConVar hud_classautokill( "hud_classautokill", "1", HUD_CLASSAUTOKILL_FLAGS, "Automatically kill player after choosing a new playerclass." );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CClassMenu::CClassMenu(IViewPort *pViewPort) : Frame(NULL, PANEL_CLASS)
|
||||
{
|
||||
m_pViewPort = pViewPort;
|
||||
m_iScoreBoardKey = BUTTON_CODE_INVALID; // this is looked up in Activate()
|
||||
m_iTeam = 0;
|
||||
|
||||
// initialize dialog
|
||||
SetTitle("", true);
|
||||
|
||||
// load the new scheme early!!
|
||||
SetScheme("ClientScheme");
|
||||
SetMoveable(false);
|
||||
SetSizeable(false);
|
||||
|
||||
// hide the system buttons
|
||||
SetTitleBarVisible( false );
|
||||
SetProportional(true);
|
||||
|
||||
// info window about this class
|
||||
m_pPanel = new EditablePanel( this, "ClassInfo" );
|
||||
|
||||
LoadControlSettings( "Resource/UI/ClassMenu.res" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CClassMenu::CClassMenu(IViewPort *pViewPort, const char *panelName) : Frame(NULL, panelName)
|
||||
{
|
||||
m_pViewPort = pViewPort;
|
||||
m_iScoreBoardKey = BUTTON_CODE_INVALID; // this is looked up in Activate()
|
||||
m_iTeam = 0;
|
||||
|
||||
// initialize dialog
|
||||
SetTitle("", true);
|
||||
|
||||
// load the new scheme early!!
|
||||
SetScheme("ClientScheme");
|
||||
SetMoveable(false);
|
||||
SetSizeable(false);
|
||||
|
||||
// hide the system buttons
|
||||
SetTitleBarVisible( false );
|
||||
SetProportional(true);
|
||||
|
||||
// info window about this class
|
||||
m_pPanel = new EditablePanel( this, "ClassInfo" );
|
||||
|
||||
// Inheriting classes are responsible for calling LoadControlSettings()!
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CClassMenu::~CClassMenu()
|
||||
{
|
||||
}
|
||||
|
||||
MouseOverPanelButton* CClassMenu::CreateNewMouseOverPanelButton(EditablePanel *panel)
|
||||
{
|
||||
return new MouseOverPanelButton(this, "MouseOverPanelButton", panel);
|
||||
}
|
||||
|
||||
|
||||
Panel *CClassMenu::CreateControlByName(const char *controlName)
|
||||
{
|
||||
if( !Q_stricmp( "MouseOverPanelButton", controlName ) )
|
||||
{
|
||||
MouseOverPanelButton *newButton = CreateNewMouseOverPanelButton( m_pPanel );
|
||||
|
||||
m_mouseoverButtons.AddToTail( newButton );
|
||||
return newButton;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::CreateControlByName( controlName );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClassMenu::Reset()
|
||||
{
|
||||
for ( int i = 0 ; i < GetChildCount() ; ++i )
|
||||
{
|
||||
// Hide the subpanel for the MouseOverPanelButtons
|
||||
MouseOverPanelButton *pPanel = dynamic_cast<MouseOverPanelButton *>( GetChild( i ) );
|
||||
|
||||
if ( pPanel )
|
||||
{
|
||||
pPanel->HidePage();
|
||||
}
|
||||
}
|
||||
|
||||
// Turn the first button back on again (so we have a default description shown)
|
||||
Assert( m_mouseoverButtons.Count() );
|
||||
for ( int i=0; i<m_mouseoverButtons.Count(); ++i )
|
||||
{
|
||||
if ( i == 0 )
|
||||
{
|
||||
m_mouseoverButtons[i]->ShowPage(); // Show the first page
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mouseoverButtons[i]->HidePage(); // Hide the rest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called when the user picks a class
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClassMenu::OnCommand( const char *command )
|
||||
{
|
||||
if ( Q_stricmp( command, "vguicancel" ) )
|
||||
{
|
||||
engine->ClientCmd( const_cast<char *>( command ) );
|
||||
|
||||
#if !defined( CSTRIKE_DLL ) && !defined( TF_CLIENT_DLL )
|
||||
// They entered a command to change their class, kill them so they spawn with
|
||||
// the new class right away
|
||||
if ( hud_classautokill.GetBool() )
|
||||
{
|
||||
engine->ClientCmd( "kill" );
|
||||
}
|
||||
#endif // !CSTRIKE_DLL && !TF_CLIENT_DLL
|
||||
}
|
||||
|
||||
Close();
|
||||
|
||||
gViewPortInterface->ShowBackGround( false );
|
||||
|
||||
BaseClass::OnCommand( command );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: shows the class menu
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClassMenu::ShowPanel(bool bShow)
|
||||
{
|
||||
if ( bShow )
|
||||
{
|
||||
Activate();
|
||||
SetMouseInputEnabled( true );
|
||||
|
||||
// load a default class page
|
||||
for ( int i=0; i<m_mouseoverButtons.Count(); ++i )
|
||||
{
|
||||
if ( i == 0 )
|
||||
{
|
||||
m_mouseoverButtons[i]->ShowPage(); // Show the first page
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mouseoverButtons[i]->HidePage(); // Hide the rest
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_iScoreBoardKey == BUTTON_CODE_INVALID )
|
||||
{
|
||||
m_iScoreBoardKey = gameuifuncs->GetButtonCodeForBind( "showscores" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetVisible( false );
|
||||
SetMouseInputEnabled( false );
|
||||
}
|
||||
|
||||
m_pViewPort->ShowBackGround( bShow );
|
||||
}
|
||||
|
||||
|
||||
void CClassMenu::SetData(KeyValues *data)
|
||||
{
|
||||
m_iTeam = data->GetInt( "team" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the text of a control by name
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClassMenu::SetLabelText(const char *textEntryName, const char *text)
|
||||
{
|
||||
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
|
||||
if (entry)
|
||||
{
|
||||
entry->SetText(text);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the visibility of a button by name
|
||||
//-----------------------------------------------------------------------------
|
||||
void CClassMenu::SetVisibleButton(const char *textEntryName, bool state)
|
||||
{
|
||||
Button *entry = dynamic_cast<Button *>(FindChildByName(textEntryName));
|
||||
if (entry)
|
||||
{
|
||||
entry->SetVisible(state);
|
||||
}
|
||||
}
|
||||
|
||||
void CClassMenu::OnKeyCodePressed(KeyCode code)
|
||||
{
|
||||
int nDir = 0;
|
||||
|
||||
switch ( code )
|
||||
{
|
||||
case KEY_XBUTTON_UP:
|
||||
case KEY_XSTICK1_UP:
|
||||
case KEY_XSTICK2_UP:
|
||||
case KEY_UP:
|
||||
case KEY_XBUTTON_LEFT:
|
||||
case KEY_XSTICK1_LEFT:
|
||||
case KEY_XSTICK2_LEFT:
|
||||
case KEY_LEFT:
|
||||
nDir = -1;
|
||||
break;
|
||||
|
||||
case KEY_XBUTTON_DOWN:
|
||||
case KEY_XSTICK1_DOWN:
|
||||
case KEY_XSTICK2_DOWN:
|
||||
case KEY_DOWN:
|
||||
case KEY_XBUTTON_RIGHT:
|
||||
case KEY_XSTICK1_RIGHT:
|
||||
case KEY_XSTICK2_RIGHT:
|
||||
case KEY_RIGHT:
|
||||
nDir = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( m_iScoreBoardKey != BUTTON_CODE_INVALID && m_iScoreBoardKey == code )
|
||||
{
|
||||
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, true );
|
||||
gViewPortInterface->PostMessageToPanel( PANEL_SCOREBOARD, new KeyValues( "PollHideCode", "code", code ) );
|
||||
}
|
||||
else if ( nDir != 0 )
|
||||
{
|
||||
CUtlSortVector< SortedPanel_t, CSortedPanelYLess > vecSortedButtons;
|
||||
VguiPanelGetSortedChildButtonList( this, (void*)&vecSortedButtons, "&", 0 );
|
||||
|
||||
int nNewArmed = VguiPanelNavigateSortedChildButtonList( (void*)&vecSortedButtons, nDir );
|
||||
|
||||
if ( nNewArmed != -1 )
|
||||
{
|
||||
// Handled!
|
||||
if ( nNewArmed < m_mouseoverButtons.Count() )
|
||||
{
|
||||
m_mouseoverButtons[ nNewArmed ]->OnCursorEntered();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseClass::OnKeyCodePressed( code );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
79
sp/src/game/client/game_controls/classmenu.h
Normal file
79
sp/src/game/client/game_controls/classmenu.h
Normal file
@@ -0,0 +1,79 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef CLASSMENU_H
|
||||
#define CLASSMENU_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui_controls/Frame.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
#include <vgui_controls/HTML.h>
|
||||
#include <utlvector.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/KeyCode.h>
|
||||
#include <game/client/iviewport.h>
|
||||
|
||||
#include "mouseoverpanelbutton.h"
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
class TextEntry;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draws the class menu
|
||||
//-----------------------------------------------------------------------------
|
||||
class CClassMenu : public vgui::Frame, public IViewPortPanel
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CClassMenu, vgui::Frame );
|
||||
|
||||
public:
|
||||
CClassMenu(IViewPort *pViewPort);
|
||||
CClassMenu(IViewPort *pViewPort, const char *panelName );
|
||||
virtual ~CClassMenu();
|
||||
|
||||
virtual const char *GetName( void ) { return PANEL_CLASS; }
|
||||
virtual void SetData(KeyValues *data);
|
||||
virtual void Reset();
|
||||
virtual void Update() {};
|
||||
virtual bool NeedsUpdate( void ) { return false; }
|
||||
virtual bool HasInputElements( void ) { return true; }
|
||||
virtual void ShowPanel( bool bShow );
|
||||
|
||||
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
|
||||
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
|
||||
virtual bool IsVisible() { return BaseClass::IsVisible(); }
|
||||
virtual void SetParent( vgui::VPANEL parent ) { BaseClass::SetParent( parent ); }
|
||||
|
||||
protected:
|
||||
|
||||
virtual vgui::Panel *CreateControlByName(const char *controlName);
|
||||
virtual MouseOverPanelButton* CreateNewMouseOverPanelButton(vgui::EditablePanel *panel);
|
||||
|
||||
//vgui2 overrides
|
||||
virtual void OnKeyCodePressed(vgui::KeyCode code);
|
||||
|
||||
// helper functions
|
||||
void SetLabelText(const char *textEntryName, const char *text);
|
||||
void SetVisibleButton(const char *textEntryName, bool state);
|
||||
|
||||
// command callbacks
|
||||
void OnCommand( const char *command );
|
||||
|
||||
IViewPort *m_pViewPort;
|
||||
ButtonCode_t m_iScoreBoardKey;
|
||||
int m_iTeam;
|
||||
vgui::EditablePanel *m_pPanel;
|
||||
|
||||
CUtlVector< MouseOverPanelButton * > m_mouseoverButtons;
|
||||
};
|
||||
|
||||
|
||||
#endif // CLASSMENU_H
|
||||
127
sp/src/game/client/game_controls/clientscoreboarddialog.h
Normal file
127
sp/src/game/client/game_controls/clientscoreboarddialog.h
Normal file
@@ -0,0 +1,127 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef CLIENTSCOREBOARDDIALOG_H
|
||||
#define CLIENTSCOREBOARDDIALOG_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui_controls/EditablePanel.h>
|
||||
#include <game/client/iviewport.h>
|
||||
#include "GameEventListener.h"
|
||||
|
||||
#define TYPE_NOTEAM 0 // NOTEAM must be zero :)
|
||||
#define TYPE_TEAM 1 // a section for a single team
|
||||
#define TYPE_PLAYERS 2
|
||||
#define TYPE_SPECTATORS 3 // a section for a spectator group
|
||||
#define TYPE_BLANK 4
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Game ScoreBoard
|
||||
//-----------------------------------------------------------------------------
|
||||
class CClientScoreBoardDialog : public vgui::EditablePanel, public IViewPortPanel, public CGameEventListener
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CClientScoreBoardDialog, vgui::EditablePanel );
|
||||
|
||||
protected:
|
||||
// column widths at 640
|
||||
enum { NAME_WIDTH = 160, SCORE_WIDTH = 60, DEATH_WIDTH = 60, PING_WIDTH = 80, VOICE_WIDTH = 0, FRIENDS_WIDTH = 0 };
|
||||
// total = 340
|
||||
|
||||
public:
|
||||
CClientScoreBoardDialog( IViewPort *pViewPort );
|
||||
~CClientScoreBoardDialog();
|
||||
|
||||
virtual const char *GetName( void ) { return PANEL_SCOREBOARD; }
|
||||
virtual void SetData(KeyValues *data) {};
|
||||
virtual void Reset();
|
||||
virtual void Update();
|
||||
virtual bool NeedsUpdate( void );
|
||||
virtual bool HasInputElements( void ) { return true; }
|
||||
virtual void ShowPanel( bool bShow );
|
||||
|
||||
virtual bool ShowAvatars()
|
||||
{
|
||||
#ifdef CSS_PERF_TEST
|
||||
return false;
|
||||
#endif
|
||||
return IsPC();
|
||||
}
|
||||
|
||||
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
|
||||
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
|
||||
virtual bool IsVisible() { return BaseClass::IsVisible(); }
|
||||
virtual void SetParent( vgui::VPANEL parent ) { BaseClass::SetParent( parent ); }
|
||||
|
||||
// IGameEventListener interface:
|
||||
virtual void FireGameEvent( IGameEvent *event);
|
||||
|
||||
virtual void UpdatePlayerAvatar( int playerIndex, KeyValues *kv );
|
||||
|
||||
protected:
|
||||
MESSAGE_FUNC_INT( OnPollHideCode, "PollHideCode", code );
|
||||
|
||||
// functions to override
|
||||
virtual bool GetPlayerScoreInfo(int playerIndex, KeyValues *outPlayerInfo);
|
||||
virtual void InitScoreboardSections();
|
||||
virtual void UpdateTeamInfo();
|
||||
virtual void UpdatePlayerInfo();
|
||||
virtual void OnThink();
|
||||
virtual void AddHeader(); // add the start header of the scoreboard
|
||||
virtual void AddSection(int teamType, int teamNumber); // add a new section header for a team
|
||||
virtual int GetAdditionalHeight() { return 0; }
|
||||
|
||||
// sorts players within a section
|
||||
static bool StaticPlayerSortFunc(vgui::SectionedListPanel *list, int itemID1, int itemID2);
|
||||
|
||||
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
|
||||
|
||||
virtual void PostApplySchemeSettings( vgui::IScheme *pScheme );
|
||||
|
||||
// finds the player in the scoreboard
|
||||
int FindItemIDForPlayerIndex(int playerIndex);
|
||||
|
||||
int m_iNumTeams;
|
||||
|
||||
vgui::SectionedListPanel *m_pPlayerList;
|
||||
int m_iSectionId; // the current section we are entering into
|
||||
|
||||
int s_VoiceImage[5];
|
||||
int TrackerImage;
|
||||
int m_HLTVSpectators;
|
||||
int m_ReplaySpectators;
|
||||
float m_fNextUpdateTime;
|
||||
|
||||
void MoveLabelToFront(const char *textEntryName);
|
||||
void MoveToCenterOfScreen();
|
||||
|
||||
vgui::ImageList *m_pImageList;
|
||||
CUtlMap<CSteamID,int> m_mapAvatarsToImageList;
|
||||
|
||||
CPanelAnimationVar( int, m_iAvatarWidth, "avatar_width", "34" ); // Avatar width doesn't scale with resolution
|
||||
CPanelAnimationVarAliasType( int, m_iNameWidth, "name_width", "136", "proportional_int" );
|
||||
CPanelAnimationVarAliasType( int, m_iClassWidth, "class_width", "35", "proportional_int" );
|
||||
CPanelAnimationVarAliasType( int, m_iScoreWidth, "score_width", "35", "proportional_int" );
|
||||
CPanelAnimationVarAliasType( int, m_iDeathWidth, "death_width", "35", "proportional_int" );
|
||||
CPanelAnimationVarAliasType( int, m_iPingWidth, "ping_width", "23", "proportional_int" );
|
||||
|
||||
private:
|
||||
int m_iPlayerIndexSymbol;
|
||||
int m_iDesiredHeight;
|
||||
IViewPort *m_pViewPort;
|
||||
ButtonCode_t m_nCloseKey;
|
||||
|
||||
|
||||
// methods
|
||||
void FillScoreBoard();
|
||||
};
|
||||
|
||||
|
||||
#endif // CLIENTSCOREBOARDDIALOG_H
|
||||
361
sp/src/game/client/game_controls/commandmenu.cpp
Normal file
361
sp/src/game/client/game_controls/commandmenu.cpp
Normal file
@@ -0,0 +1,361 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include <cdll_client_int.h>
|
||||
#include <cdll_util.h>
|
||||
#include <globalvars_base.h>
|
||||
#include <icvar.h>
|
||||
#include <filesystem.h>
|
||||
|
||||
#include "commandmenu.h"
|
||||
#include "vgui_controls/MenuItem.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
CommandMenu::CommandMenu( Panel *parent, const char *panelName, IViewPort * viewport) : Menu( parent, panelName )
|
||||
{
|
||||
if ( !viewport )
|
||||
return;
|
||||
|
||||
m_ViewPort = viewport;
|
||||
SetVisible( false );
|
||||
m_CurrentMenu = this;
|
||||
|
||||
m_MenuKeys = NULL;
|
||||
}
|
||||
|
||||
bool CommandMenu::LoadFromFile( const char * fileName) // load menu from KeyValues
|
||||
{
|
||||
KeyValues * kv = new KeyValues(fileName);
|
||||
|
||||
if ( !kv->LoadFromFile( g_pFullFileSystem, fileName, "GAME" ) )
|
||||
return false;
|
||||
|
||||
bool ret = LoadFromKeyValues( kv );
|
||||
|
||||
kv->deleteThis();
|
||||
return ret;
|
||||
}
|
||||
|
||||
CommandMenu::~CommandMenu()
|
||||
{
|
||||
ClearMenu();
|
||||
}
|
||||
|
||||
void CommandMenu::OnMessage(const KeyValues *params, VPANEL fromPanel)
|
||||
{
|
||||
char text[255];
|
||||
bool bHandled = false;
|
||||
|
||||
KeyValues *param1 = const_cast<KeyValues *>(params);
|
||||
|
||||
// toggle attached cvar, if any
|
||||
Q_strncpy( text, param1->GetString("toggle"), sizeof( text ) );
|
||||
|
||||
if ( text[0] )
|
||||
{
|
||||
ConVarRef convar( text );
|
||||
if ( convar.IsValid() )
|
||||
{
|
||||
// toggle cvar
|
||||
|
||||
if ( convar.GetInt() )
|
||||
{
|
||||
convar.SetValue( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
convar.SetValue( 1 );
|
||||
}
|
||||
|
||||
UpdateMenu();
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg("CommandComboBox::OnMessage: cvar %s not found.\n", param1->GetString("typedata") );
|
||||
}
|
||||
|
||||
bHandled = true;
|
||||
}
|
||||
|
||||
// execute attached command, if any
|
||||
Q_strncpy( text, param1->GetString("command"), sizeof( text ) );
|
||||
if ( text[0] )
|
||||
{
|
||||
engine->ClientCmd( text );
|
||||
bHandled = true;
|
||||
}
|
||||
|
||||
// fire custom message, if any
|
||||
Q_strncpy( text, param1->GetString("custom"), sizeof( text ) );
|
||||
if ( text[0] )
|
||||
{
|
||||
OnCustomItem( param1 ); // let derived class decide what to do
|
||||
bHandled = true;
|
||||
}
|
||||
|
||||
if ( bHandled )
|
||||
{
|
||||
PostMessage( GetParent(), new KeyValues("CommandMenuClosed") );
|
||||
}
|
||||
|
||||
BaseClass::OnMessage( params, fromPanel );
|
||||
}
|
||||
|
||||
void CommandMenu::StartNewSubMenu(KeyValues * params)
|
||||
{
|
||||
CommandMenuItem menuitem;
|
||||
menuitem.menu = m_CurrentMenu;
|
||||
|
||||
Menu * menu = new Menu( this, params->GetString("name") ); // create new menu
|
||||
|
||||
menuitem.itemnr = m_CurrentMenu->AddCascadingMenuItem( params->GetString("label"), this, menu, params ); // add to current menu as item
|
||||
|
||||
m_MenuItems.AddToTail( menuitem ); // add to global list
|
||||
|
||||
m_pMenuStack.Push( m_CurrentMenu ); // remember current menu
|
||||
|
||||
m_CurrentMenu = menu; // continue adding items in new menu
|
||||
}
|
||||
|
||||
void CommandMenu::FinishSubMenu()
|
||||
{
|
||||
m_CurrentMenu = m_pMenuStack.Top(); // get menu one level above
|
||||
m_pMenuStack.Pop(); // remove it from stack
|
||||
}
|
||||
|
||||
void CommandMenu::AddMenuCommandItem(KeyValues * params)
|
||||
{
|
||||
CommandMenuItem menuitem; // create new menuItem
|
||||
menuitem.menu = m_CurrentMenu; // save the current menu context
|
||||
menuitem.itemnr = m_CurrentMenu->AddMenuItem( params->GetString("label"), params->MakeCopy(), this, params ); // add it
|
||||
m_MenuItems.AddToTail( menuitem ); // add to global list
|
||||
}
|
||||
|
||||
void CommandMenu::AddMenuToggleItem(KeyValues * params)
|
||||
{
|
||||
CommandMenuItem menuitem; // create new menuItem
|
||||
menuitem.menu = m_CurrentMenu; // save the current menu context
|
||||
menuitem.itemnr = m_CurrentMenu->AddCheckableMenuItem( params->GetString("label"), params->MakeCopy(), this, params ); // add it
|
||||
m_MenuItems.AddToTail( menuitem ); // add to global list
|
||||
}
|
||||
|
||||
void CommandMenu::AddMenuCustomItem(KeyValues * params)
|
||||
{
|
||||
CommandMenuItem menuitem; // create new menuItem
|
||||
menuitem.menu = m_CurrentMenu; // save the current menu context
|
||||
menuitem.itemnr = AddCustomItem( params, m_CurrentMenu );
|
||||
m_MenuItems.AddToTail( menuitem ); // add to global list
|
||||
}
|
||||
|
||||
void CommandMenu::ClearMenu()
|
||||
{
|
||||
SetVisible( false );
|
||||
m_pMenuStack.Clear();
|
||||
m_MenuItems.RemoveAll();
|
||||
// DeleteAllItems();
|
||||
MarkForDeletion();
|
||||
|
||||
if ( m_MenuKeys )
|
||||
{
|
||||
m_MenuKeys->deleteThis();
|
||||
m_MenuKeys = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CommandMenu::RebuildMenu()
|
||||
{
|
||||
if ( !m_MenuKeys )
|
||||
return;
|
||||
|
||||
m_pMenuStack.Clear();
|
||||
m_MenuItems.RemoveAll();
|
||||
DeleteAllItems();
|
||||
|
||||
LoadFromKeyValues( m_MenuKeys ); // and reload respecting new team, mapname etc.
|
||||
}
|
||||
|
||||
void CommandMenu::UpdateMenu()
|
||||
{
|
||||
char text[255];
|
||||
|
||||
int num = m_MenuItems.Count();
|
||||
|
||||
for (int i=0; i < num; i++)
|
||||
{
|
||||
CommandMenuItem menuitem = m_MenuItems.Element(i);
|
||||
KeyValues * keys = menuitem.menu->GetItemUserData( menuitem.itemnr );
|
||||
|
||||
if ( !keys )
|
||||
continue;
|
||||
|
||||
// let custom menu items update themself
|
||||
Q_strncpy( text, keys->GetString("custom"), sizeof(text) );
|
||||
|
||||
if ( text[0] )
|
||||
{
|
||||
// let derived class modify the menu item
|
||||
UpdateCustomItem( keys, menuitem.menu->GetMenuItem(menuitem.itemnr) );
|
||||
continue;
|
||||
}
|
||||
|
||||
// update toggle buttons
|
||||
Q_strncpy( text, keys->GetString("toggle"), sizeof(text) );
|
||||
|
||||
if ( text[0] )
|
||||
{
|
||||
// set toggle state equal to cvar state
|
||||
ConVarRef convar( text );
|
||||
|
||||
if ( convar.IsValid() )
|
||||
{
|
||||
menuitem.menu->SetMenuItemChecked( menuitem.itemnr, convar.GetBool() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommandMenu::SetVisible(bool state)
|
||||
{
|
||||
if ( state && !IsVisible() )
|
||||
{
|
||||
UpdateMenu();
|
||||
}
|
||||
|
||||
BaseClass::SetVisible( state );
|
||||
}
|
||||
|
||||
bool CommandMenu::CheckRules(const char *rule, const char *ruledata)
|
||||
{
|
||||
if ( !rule || !ruledata )
|
||||
{
|
||||
return true; // no rule defined, show item
|
||||
}
|
||||
|
||||
if ( Q_strcmp( rule, "team") == 0 )
|
||||
{
|
||||
// if team is same as specified in rule, show item
|
||||
return ( Q_strcmp( m_CurrentTeam, ruledata ) == 0 );
|
||||
}
|
||||
else if ( Q_strcmp( rule, "map") == 0 )
|
||||
{
|
||||
// if team is same as specified in rule, show item
|
||||
return ( Q_strcmp( m_CurrentMap, ruledata ) == 0 );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
KeyValues * CommandMenu::GetKeyValues()
|
||||
{
|
||||
return m_MenuKeys;
|
||||
}
|
||||
|
||||
bool CommandMenu::LoadFromKeyValues( KeyValues * params )
|
||||
{
|
||||
if ( !params )
|
||||
return false;
|
||||
|
||||
Q_snprintf( m_CurrentTeam, 4, "%i", GetLocalPlayerTeam() );
|
||||
|
||||
Q_FileBase( engine->GetLevelName(), m_CurrentMap, sizeof(m_CurrentMap) );
|
||||
|
||||
if ( params != m_MenuKeys )
|
||||
{
|
||||
if ( m_MenuKeys )
|
||||
m_MenuKeys->deleteThis();
|
||||
|
||||
m_MenuKeys = params->MakeCopy(); // save keyvalues
|
||||
}
|
||||
|
||||
// iterate through all menu items
|
||||
|
||||
KeyValues * subkey = m_MenuKeys->GetFirstSubKey();
|
||||
|
||||
while ( subkey )
|
||||
{
|
||||
if ( subkey->GetDataType() == KeyValues::TYPE_NONE )
|
||||
{
|
||||
if ( !LoadFromKeyValuesInternal( subkey, 0 ) ) // recursive call
|
||||
return false;
|
||||
}
|
||||
|
||||
subkey = subkey->GetNextKey();
|
||||
}
|
||||
|
||||
UpdateMenu();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandMenu::LoadFromKeyValuesInternal(KeyValues * key, int depth)
|
||||
{
|
||||
char text[255];
|
||||
KeyValues * subkey = NULL;
|
||||
|
||||
if ( depth > 100 )
|
||||
{
|
||||
Msg("CommandMenu::LoadFromKeyValueInternal: depth > 100.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Q_strncpy( text, key->GetString("custom"), sizeof(text) ); // get type
|
||||
|
||||
if ( text[0] )
|
||||
{
|
||||
AddMenuCustomItem( key ); // do whatever custom item wants to
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !CheckRules( key->GetString("rule"), key->GetString("ruledata") ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// rules OK add subkey
|
||||
Q_strncpy( text, key->GetString("toggle"), sizeof(text) ); // get type
|
||||
|
||||
if ( text[0] )
|
||||
{
|
||||
AddMenuToggleItem( key );
|
||||
return true;
|
||||
}
|
||||
|
||||
Q_strncpy( text, key->GetString("command"), sizeof(text) ); // get type
|
||||
|
||||
if ( text[0] )
|
||||
{
|
||||
AddMenuCommandItem( key );
|
||||
return true;
|
||||
}
|
||||
|
||||
// not a command, nor a toggle. Must be a submenu:
|
||||
|
||||
StartNewSubMenu( key ); // create submenu
|
||||
|
||||
// iterate through all subkeys
|
||||
|
||||
subkey = key->GetFirstSubKey();
|
||||
|
||||
while ( subkey )
|
||||
{
|
||||
if ( subkey->GetDataType() == KeyValues::TYPE_NONE )
|
||||
{
|
||||
LoadFromKeyValuesInternal( subkey, depth+1 ); // recursive call
|
||||
}
|
||||
|
||||
subkey = subkey->GetNextKey();
|
||||
}
|
||||
|
||||
FinishSubMenu(); // go one level back
|
||||
|
||||
return true;
|
||||
}
|
||||
77
sp/src/game/client/game_controls/commandmenu.h
Normal file
77
sp/src/game/client/game_controls/commandmenu.h
Normal file
@@ -0,0 +1,77 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef COMMANDMENU_H
|
||||
#define COMMANDMENU_H
|
||||
|
||||
#include <vgui_controls/Menu.h>
|
||||
#include <game/client/iviewport.h>
|
||||
#include <filesystem.h>
|
||||
#include "utlstack.h"
|
||||
#include "utlvector.h"
|
||||
#include <KeyValues.h>
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
class CommandMenu : public Menu
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CommandMenu, Menu );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Menu * menu;
|
||||
int itemnr;
|
||||
} CommandMenuItem;
|
||||
|
||||
public:
|
||||
CommandMenu( Panel *parent, const char *panelName, IViewPort * viewport );
|
||||
~CommandMenu();
|
||||
|
||||
bool LoadFromFile(const char * fileName); // load menu from file (via KeyValues)
|
||||
void UpdateMenu(); // call to update all menu items, check buttons etc
|
||||
void RebuildMenu(); // rebuilds menu respecting changed game state (map, team etc)
|
||||
void ClearMenu(); // destroy menu
|
||||
|
||||
public:
|
||||
// overwrite these in your derived class
|
||||
// virtual CommandMenu * CommandMenu::Factory(Panel *parent, const char *panelName, IViewPort * viewport = NULL, IFileSystem * pFileSytem = NULL); // overwrite
|
||||
virtual int AddCustomItem(KeyValues * params, Menu * menu) {return 0;} // return MenuItem nr
|
||||
virtual void UpdateCustomItem(KeyValues * params, MenuItem * item ) {}; // maybe change your item
|
||||
virtual void OnCustomItem(KeyValues * params) {}; // a custom item was pressed
|
||||
virtual bool CheckRules(const char *rule, const char *ruledata); // check a menu item rule
|
||||
virtual void SetVisible(bool state);
|
||||
|
||||
// DON'T touch anything below !
|
||||
|
||||
protected:
|
||||
|
||||
void OnMessage(const KeyValues *params, VPANEL fromPanel);
|
||||
void StartNewSubMenu(KeyValues * params);
|
||||
void FinishSubMenu();
|
||||
void AddMenuCommandItem(KeyValues * params);
|
||||
void AddMenuCustomItem(KeyValues * params);
|
||||
void AddMenuToggleItem(KeyValues * params);
|
||||
bool LoadFromKeyValuesInternal(KeyValues * key, int depth);
|
||||
bool LoadFromKeyValues( KeyValues * key); //
|
||||
|
||||
KeyValues * GetKeyValues(); // returns keyValues for current menu or NULL
|
||||
|
||||
|
||||
IViewPort * m_ViewPort; // viewport interface
|
||||
Menu * m_CurrentMenu; // Current menu while building CommandComoboBox
|
||||
char m_CurrentTeam[4];
|
||||
char m_CurrentMap[256];
|
||||
|
||||
KeyValues* m_MenuKeys;
|
||||
|
||||
CUtlStack<vgui::Menu*>m_pMenuStack;
|
||||
CUtlVector<CommandMenuItem>m_MenuItems;
|
||||
};
|
||||
|
||||
#endif // COMMANDMENU_H
|
||||
256
sp/src/game/client/game_controls/imagemouseoverbutton.h
Normal file
256
sp/src/game/client/game_controls/imagemouseoverbutton.h
Normal file
@@ -0,0 +1,256 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef IMAGE_MOUSE_OVER_BUTTON_H
|
||||
#define IMAGE_MOUSE_OVER_BUTTON_H
|
||||
|
||||
#include "vgui/ISurface.h"
|
||||
#include "vgui/IScheme.h"
|
||||
#include "mouseoverpanelbutton.h"
|
||||
|
||||
//===============================================
|
||||
// CImageMouseOverButton - used for class images
|
||||
//===============================================
|
||||
|
||||
template <class T>
|
||||
class CImageMouseOverButton : public MouseOverButton<T>
|
||||
{
|
||||
private:
|
||||
//DECLARE_CLASS_SIMPLE( CImageMouseOverButton, MouseOverButton );
|
||||
|
||||
public:
|
||||
CImageMouseOverButton( vgui::Panel *parent, const char *panelName, T *templatePanel );
|
||||
|
||||
virtual void ApplySettings( KeyValues *inResourceData );
|
||||
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
|
||||
virtual void OnSizeChanged( int newWide, int newTall );
|
||||
|
||||
void RecalculateImageSizes( void );
|
||||
void SetActiveImage( const char *imagename );
|
||||
void SetInactiveImage( const char *imagename );
|
||||
void SetActiveImage( vgui::IImage *image );
|
||||
void SetInactiveImage( vgui::IImage *image );
|
||||
|
||||
public:
|
||||
virtual void Paint();
|
||||
virtual void ShowPage( void );
|
||||
virtual void HidePage( void );
|
||||
|
||||
private:
|
||||
vgui::IImage *m_pActiveImage;
|
||||
char *m_pszActiveImageName;
|
||||
|
||||
vgui::IImage *m_pInactiveImage;
|
||||
char *m_pszInactiveImageName;
|
||||
|
||||
bool m_bScaleImage;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
CImageMouseOverButton<T>::CImageMouseOverButton( vgui::Panel *parent, const char *panelName, T *templatePanel ) :
|
||||
MouseOverButton<T>( parent, panelName, templatePanel )
|
||||
{
|
||||
m_pszActiveImageName = NULL;
|
||||
m_pszInactiveImageName = NULL;
|
||||
|
||||
m_pActiveImage = NULL;
|
||||
m_pInactiveImage = NULL;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::ApplySettings( KeyValues *inResourceData )
|
||||
{
|
||||
m_bScaleImage = inResourceData->GetInt( "scaleImage", 0 );
|
||||
|
||||
// Active Image
|
||||
delete [] m_pszActiveImageName;
|
||||
m_pszActiveImageName = NULL;
|
||||
|
||||
const char *activeImageName = inResourceData->GetString( "activeimage", "" );
|
||||
if ( *activeImageName )
|
||||
{
|
||||
this->SetActiveImage( activeImageName );
|
||||
}
|
||||
|
||||
// Inactive Image
|
||||
delete [] m_pszInactiveImageName;
|
||||
m_pszInactiveImageName = NULL;
|
||||
|
||||
const char *inactiveImageName = inResourceData->GetString( "inactiveimage", "" );
|
||||
if ( *inactiveImageName )
|
||||
{
|
||||
this->SetInactiveImage( inactiveImageName );
|
||||
}
|
||||
|
||||
MouseOverButton<T>::ApplySettings( inResourceData );
|
||||
|
||||
this->InvalidateLayout( false, true ); // force applyschemesettings to run
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||||
{
|
||||
MouseOverButton<T>::ApplySchemeSettings( pScheme );
|
||||
|
||||
if ( m_pszActiveImageName && strlen( m_pszActiveImageName ) > 0 )
|
||||
{
|
||||
this->SetActiveImage( vgui::scheme()->GetImage( m_pszActiveImageName, m_bScaleImage ) );
|
||||
}
|
||||
|
||||
if ( m_pszInactiveImageName && strlen( m_pszInactiveImageName ) > 0 )
|
||||
{
|
||||
this->SetInactiveImage( vgui::scheme()->GetImage( m_pszInactiveImageName, m_bScaleImage ) );
|
||||
}
|
||||
|
||||
vgui::IBorder *pBorder = pScheme->GetBorder( "NoBorder" );
|
||||
this->SetDefaultBorder( pBorder);
|
||||
this->SetDepressedBorder( pBorder );
|
||||
this->SetKeyFocusBorder( pBorder );
|
||||
|
||||
Color blank(0,0,0,0);
|
||||
this->SetDefaultColor( this->GetButtonFgColor(), blank );
|
||||
this->SetArmedColor( this->GetButtonArmedFgColor(), blank );
|
||||
this->SetDepressedColor( this->GetButtonDepressedFgColor(), blank );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::RecalculateImageSizes( void )
|
||||
{
|
||||
// Reset our images, which will force them to recalculate their size.
|
||||
// Necessary for images shared with other scaling buttons.
|
||||
this->SetActiveImage( m_pActiveImage );
|
||||
this->SetInactiveImage( m_pInactiveImage );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::SetActiveImage( const char *imagename )
|
||||
{
|
||||
int len = Q_strlen( imagename ) + 1;
|
||||
m_pszActiveImageName = new char[ len ];
|
||||
Q_strncpy( m_pszActiveImageName, imagename, len );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::SetInactiveImage( const char *imagename )
|
||||
{
|
||||
int len = Q_strlen( imagename ) + 1;
|
||||
m_pszInactiveImageName = new char[ len ];
|
||||
Q_strncpy( m_pszInactiveImageName, imagename, len );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::SetActiveImage( vgui::IImage *image )
|
||||
{
|
||||
m_pActiveImage = image;
|
||||
|
||||
if ( m_pActiveImage )
|
||||
{
|
||||
int wide, tall;
|
||||
if ( m_bScaleImage )
|
||||
{
|
||||
// scaling, force the image size to be our size
|
||||
this->GetSize( wide, tall );
|
||||
m_pActiveImage->SetSize( wide, tall );
|
||||
}
|
||||
else
|
||||
{
|
||||
// not scaling, so set our size to the image size
|
||||
m_pActiveImage->GetSize( wide, tall );
|
||||
this->SetSize( wide, tall );
|
||||
}
|
||||
}
|
||||
|
||||
this->Repaint();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::SetInactiveImage( vgui::IImage *image )
|
||||
{
|
||||
m_pInactiveImage = image;
|
||||
|
||||
if ( m_pInactiveImage )
|
||||
{
|
||||
int wide, tall;
|
||||
if ( m_bScaleImage)
|
||||
{
|
||||
// scaling, force the image size to be our size
|
||||
this->GetSize( wide, tall );
|
||||
m_pInactiveImage->SetSize( wide, tall );
|
||||
}
|
||||
else
|
||||
{
|
||||
// not scaling, so set our size to the image size
|
||||
m_pInactiveImage->GetSize( wide, tall );
|
||||
this->SetSize( wide, tall );
|
||||
}
|
||||
}
|
||||
|
||||
this->Repaint();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::OnSizeChanged( int newWide, int newTall )
|
||||
{
|
||||
if ( m_bScaleImage )
|
||||
{
|
||||
// scaling, force the image size to be our size
|
||||
|
||||
if ( m_pActiveImage )
|
||||
m_pActiveImage->SetSize( newWide, newTall );
|
||||
|
||||
if ( m_pInactiveImage )
|
||||
m_pInactiveImage->SetSize( newWide, newTall );
|
||||
}
|
||||
MouseOverButton<T>::OnSizeChanged( newWide, newTall );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::Paint()
|
||||
{
|
||||
this->SetActiveImage( m_pActiveImage );
|
||||
this->SetInactiveImage( m_pInactiveImage );
|
||||
|
||||
if ( this->IsArmed() )
|
||||
{
|
||||
// draw the active image
|
||||
if ( m_pActiveImage )
|
||||
{
|
||||
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
|
||||
m_pActiveImage->SetPos( 0, 0 );
|
||||
m_pActiveImage->Paint();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw the inactive image
|
||||
if ( m_pInactiveImage )
|
||||
{
|
||||
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
|
||||
m_pInactiveImage->SetPos( 0, 0 );
|
||||
m_pInactiveImage->Paint();
|
||||
}
|
||||
}
|
||||
|
||||
MouseOverButton<T>::Paint();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::ShowPage( void )
|
||||
{
|
||||
MouseOverButton<T>::ShowPage();
|
||||
|
||||
// send message to parent that we triggered something
|
||||
this->PostActionSignal( new KeyValues( "ShowPage", "page", this->GetName() ) );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void CImageMouseOverButton<T>::HidePage( void )
|
||||
{
|
||||
MouseOverButton<T>::HidePage();
|
||||
}
|
||||
|
||||
#endif //IMAGE_MOUSE_OVER_BUTTON_H
|
||||
122
sp/src/game/client/game_controls/intromenu.cpp
Normal file
122
sp/src/game/client/game_controls/intromenu.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "intromenu.h"
|
||||
#include <networkstringtabledefs.h>
|
||||
#include <cdll_client_int.h>
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <filesystem.h>
|
||||
#include <KeyValues.h>
|
||||
#include <convar.h>
|
||||
#include <game/client/iviewport.h>
|
||||
#include "spectatorgui.h"
|
||||
#include "gamerules.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CIntroMenu::CIntroMenu( IViewPort *pViewPort ) : Frame( NULL, PANEL_INTRO )
|
||||
{
|
||||
// initialize dialog
|
||||
m_pViewPort = pViewPort;
|
||||
|
||||
m_pTitleLabel = NULL;
|
||||
|
||||
// load the new scheme early!!
|
||||
SetScheme( "ClientScheme" );
|
||||
SetMoveable( false );
|
||||
SetSizeable( false );
|
||||
SetProportional( true );
|
||||
|
||||
// hide the system buttons
|
||||
SetTitleBarVisible( false );
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CIntroMenu::~CIntroMenu()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the color of the top and bottom bars
|
||||
//-----------------------------------------------------------------------------
|
||||
void CIntroMenu::ApplySchemeSettings( IScheme *pScheme )
|
||||
{
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
|
||||
LoadControlSettings("Resource/UI/IntroMenu.res");
|
||||
|
||||
m_pTitleLabel = dynamic_cast<Label *>( FindChildByName( "titlelabel" ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CIntroMenu::Reset( void )
|
||||
{
|
||||
Update();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CIntroMenu::Update( void )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CIntroMenu::OnCommand( const char *command )
|
||||
{
|
||||
if ( !Q_strcmp( command, "skip" ) )
|
||||
{
|
||||
engine->ClientCmd( "intro_skip" );
|
||||
m_pViewPort->ShowPanel( this, false );
|
||||
}
|
||||
|
||||
BaseClass::OnCommand( command );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CIntroMenu::ShowPanel( bool bShow )
|
||||
{
|
||||
if ( BaseClass::IsVisible() == bShow )
|
||||
return;
|
||||
|
||||
m_pViewPort->ShowBackGround( bShow );
|
||||
|
||||
if ( bShow )
|
||||
{
|
||||
Activate();
|
||||
|
||||
if ( GameRules() )
|
||||
{
|
||||
SetDialogVariable( "gamemode", g_pVGuiLocalize->Find( GameRules()->GetGameTypeName() ) );
|
||||
}
|
||||
|
||||
SetMouseInputEnabled( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetVisible( false );
|
||||
SetMouseInputEnabled( false );
|
||||
}
|
||||
}
|
||||
57
sp/src/game/client/game_controls/intromenu.h
Normal file
57
sp/src/game/client/game_controls/intromenu.h
Normal file
@@ -0,0 +1,57 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef INTROMENU_H
|
||||
#define INTROMENU_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include <vgui_controls/Frame.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
#include <vgui_controls/Label.h>
|
||||
|
||||
#include <game/client/iviewport.h>
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
class TextEntry;
|
||||
}
|
||||
|
||||
class CIntroMenu : public vgui::Frame, public IViewPortPanel
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CIntroMenu, vgui::Frame );
|
||||
|
||||
public:
|
||||
CIntroMenu( IViewPort *pViewPort );
|
||||
virtual ~CIntroMenu();
|
||||
|
||||
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
|
||||
|
||||
virtual const char *GetName( void ){ return PANEL_INTRO; }
|
||||
virtual void SetData( KeyValues *data ){ return; }
|
||||
virtual void Reset();
|
||||
virtual void Update();
|
||||
virtual bool NeedsUpdate( void ) { return false; }
|
||||
virtual bool HasInputElements( void ) { return true; }
|
||||
virtual void ShowPanel( bool bShow );
|
||||
|
||||
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
|
||||
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
|
||||
virtual bool IsVisible() { return BaseClass::IsVisible(); }
|
||||
virtual void SetParent( vgui::VPANEL parent ) { BaseClass::SetParent( parent ); }
|
||||
|
||||
protected:
|
||||
// vgui overrides
|
||||
virtual void OnCommand( const char *command );
|
||||
|
||||
IViewPort *m_pViewPort;
|
||||
vgui::Label *m_pTitleLabel;
|
||||
};
|
||||
|
||||
#endif // INTROMENU_H
|
||||
275
sp/src/game/client/game_controls/mapoverview.h
Normal file
275
sp/src/game/client/game_controls/mapoverview.h
Normal file
@@ -0,0 +1,275 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: MiniMap.h: interface for the CMiniMap class.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#if !defined HLTVPANEL_H
|
||||
#define HLTVPANEL_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include <game/client/iviewport.h>
|
||||
#include "mathlib/vector.h"
|
||||
#include <igameevents.h>
|
||||
#include <shareddefs.h>
|
||||
#include <const.h>
|
||||
#include "hudelement.h"
|
||||
|
||||
class IMapOverviewPanel
|
||||
{
|
||||
public:
|
||||
virtual void SetMode( int mode ) = 0;
|
||||
virtual int GetMode( void ) = 0;
|
||||
virtual void FlashEntity( int entityID ) = 0;
|
||||
virtual void SetPlayerPositions(int index, const Vector &position, const QAngle &angle) = 0;
|
||||
virtual void SetVisible(bool state) = 0;
|
||||
virtual float GetZoom( void ) = 0;
|
||||
virtual vgui::Panel *GetAsPanel() = 0;
|
||||
virtual bool AllowConCommandsWhileAlive() = 0;
|
||||
virtual void SetPlayerPreferredMode( int mode ) = 0;
|
||||
virtual void SetPlayerPreferredViewSize( float viewSize ) = 0;
|
||||
virtual bool IsVisible() = 0;
|
||||
virtual void GetBounds(int &x, int &y, int &wide, int &tall) = 0;
|
||||
virtual float GetFullZoom( void ) = 0;
|
||||
virtual float GetMapScale( void ) = 0;
|
||||
};
|
||||
|
||||
#define MAX_TRAIL_LENGTH 30
|
||||
#define OVERVIEW_MAP_SIZE 1024 // an overview map is 1024x1024 pixels
|
||||
|
||||
typedef bool ( *FnCustomMapOverviewObjectPaint )( int textureID, Vector pos, float scale, float angle, const char *text, Color *textColor, float status, Color *statusColor );
|
||||
|
||||
|
||||
class CMapOverview : public CHudElement, public vgui::Panel, public IMapOverviewPanel
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CMapOverview, vgui::Panel );
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
MAP_MODE_OFF = 0, // Totally off
|
||||
MAP_MODE_INSET, // A little map up in a corner
|
||||
MAP_MODE_FULL, // Full screen, full map
|
||||
MAP_MODE_RADAR // In game radar, extra functionality
|
||||
};
|
||||
|
||||
CMapOverview( const char *pElementName );
|
||||
virtual ~CMapOverview();
|
||||
|
||||
virtual bool ShouldDraw( void );
|
||||
vgui::Panel *GetAsPanel(){ return this; }
|
||||
virtual bool AllowConCommandsWhileAlive(){return true;}
|
||||
virtual void SetPlayerPreferredMode( int mode ){}
|
||||
virtual void SetPlayerPreferredViewSize( float viewSize ){};
|
||||
|
||||
protected: // private structures & types
|
||||
|
||||
float GetViewAngle( void ); // The angle that determines the viewport twist from map texture to panel drawing.
|
||||
|
||||
// list of game events the hLTV takes care of
|
||||
|
||||
typedef struct {
|
||||
int xpos;
|
||||
int ypos;
|
||||
} FootStep_t;
|
||||
|
||||
typedef struct MapPlayer_s {
|
||||
int index; // player's index
|
||||
int userid; // user ID on server
|
||||
int icon; // players texture icon ID
|
||||
Color color; // players team color
|
||||
char name[MAX_PLAYER_NAME_LENGTH];
|
||||
int team; // N,T,CT
|
||||
int health; // 0..100, 7 bit
|
||||
Vector position; // current x,y pos
|
||||
QAngle angle; // view origin 0..360
|
||||
Vector2D trail[MAX_TRAIL_LENGTH]; // save 1 footstep each second for 1 minute
|
||||
} MapPlayer_t;
|
||||
|
||||
typedef struct MapObject_s {
|
||||
int objectID; // unique object ID
|
||||
int index; // entity index if any
|
||||
int icon; // players texture icon ID
|
||||
Color color; // players team color
|
||||
char name[MAX_PLAYER_NAME_LENGTH]; // show text under icon
|
||||
Vector position; // current x,y pos
|
||||
QAngle angle; // view origin 0..360
|
||||
float endtime; // time stop showing object
|
||||
float size; // object size
|
||||
float status; // green status bar [0..1], -1 = disabled
|
||||
Color statusColor; // color of status bar
|
||||
int flags; // MAB_OBJECT_*
|
||||
const char *text; // text to draw underneath the icon
|
||||
} MapObject_t;
|
||||
|
||||
#define MAP_OBJECT_ALIGN_TO_MAP (1<<0)
|
||||
|
||||
public: // IViewPortPanel interface:
|
||||
|
||||
virtual const char *GetName( void ) { return PANEL_OVERVIEW; }
|
||||
virtual void SetData(KeyValues *data);
|
||||
virtual void Reset();
|
||||
virtual void OnThink();
|
||||
virtual void Update();
|
||||
virtual bool NeedsUpdate( void );
|
||||
virtual bool HasInputElements( void ) { return false; }
|
||||
virtual void ShowPanel( bool bShow );
|
||||
virtual void Init( void );
|
||||
|
||||
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
|
||||
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
|
||||
virtual bool IsVisible() { return BaseClass::IsVisible(); }
|
||||
virtual void GetBounds(int &x, int &y, int &wide, int &tall) { BaseClass::GetBounds(x, y, wide, tall); }
|
||||
virtual void SetParent(vgui::VPANEL parent) { BaseClass::SetParent(parent); }
|
||||
|
||||
public: // IGameEventListener
|
||||
|
||||
virtual void FireGameEvent( IGameEvent *event);
|
||||
|
||||
public: // VGUI overrides
|
||||
|
||||
virtual void Paint();
|
||||
virtual void OnMousePressed( vgui::MouseCode code );
|
||||
virtual void ApplySchemeSettings(vgui::IScheme *scheme);
|
||||
virtual void SetVisible(bool state){BaseClass::SetVisible(state);}
|
||||
|
||||
public:
|
||||
|
||||
virtual float GetZoom( void );
|
||||
virtual int GetMode( void );
|
||||
virtual float GetFullZoom( void ){ return m_fFullZoom; }
|
||||
virtual float GetMapScale( void ){ return m_fMapScale; }
|
||||
|
||||
// Player settings:
|
||||
virtual void ShowPlayerNames(bool state);
|
||||
virtual void ShowPlayerHealth(bool state);
|
||||
virtual void ShowPlayerTracks(float seconds);
|
||||
virtual void SetPlayerPositions(int index, const Vector &position, const QAngle &angle);
|
||||
|
||||
// general settings:
|
||||
virtual void SetMap(const char * map);
|
||||
virtual void SetTime( float time );
|
||||
virtual void SetMode( int mode );
|
||||
virtual bool SetTeamColor(int team, Color color);
|
||||
virtual void SetFollowAngle(bool state);
|
||||
virtual void SetFollowEntity(int entindex); // 0 = off
|
||||
virtual void SetCenter( const Vector2D &mappos);
|
||||
virtual void SetAngle( float angle);
|
||||
virtual Vector2D WorldToMap( const Vector &worldpos );
|
||||
|
||||
// Object settings
|
||||
virtual int AddObject( const char *icon, int entity, float timeToLive ); // returns object ID, 0 = no entity, -1 = forever
|
||||
virtual void SetObjectIcon( int objectID, const char *icon, float size ); // icon world size
|
||||
virtual void SetObjectText( int objectID, const char *text, Color color ); // text under icon
|
||||
virtual void SetObjectStatus( int objectID, float value, Color statusColor ); // status bar under icon
|
||||
virtual void SetObjectPosition( int objectID, const Vector &position, const QAngle &angle ); // world pos/angles
|
||||
virtual void AddObjectFlags( int objectID, int flags );
|
||||
virtual void SetObjectFlags( int objectID, int flags );
|
||||
virtual void RemoveObject( int objectID );
|
||||
virtual void RemoveObjectByIndex( int index );
|
||||
virtual void FlashEntity( int entityID ){}
|
||||
|
||||
// rules that define if you can see a player on the overview or not
|
||||
virtual bool CanPlayerBeSeen(MapPlayer_t *player);
|
||||
|
||||
/// allows mods to restrict health
|
||||
virtual bool CanPlayerHealthBeSeen(MapPlayer_t *player);
|
||||
|
||||
/// allows mods to restrict names (e.g. CS when mp_playerid is non-zero)
|
||||
virtual bool CanPlayerNameBeSeen(MapPlayer_t *player);
|
||||
|
||||
virtual int GetIconNumberFromTeamNumber( int teamNumber ){return teamNumber;}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void DrawCamera();
|
||||
virtual void DrawObjects();
|
||||
virtual void DrawMapTexture();
|
||||
virtual void DrawMapPlayers();
|
||||
virtual void DrawMapPlayerTrails();
|
||||
virtual void UpdatePlayerTrails();
|
||||
virtual void ResetRound();
|
||||
virtual void InitTeamColorsAndIcons();
|
||||
virtual void UpdateSizeAndPosition();
|
||||
virtual bool RunHudAnimations(){ return true; }
|
||||
|
||||
bool IsInPanel(Vector2D &pos);
|
||||
MapPlayer_t* GetPlayerByUserID( int userID );
|
||||
int AddIconTexture(const char *filename);
|
||||
Vector2D MapToPanel( const Vector2D &mappos );
|
||||
int GetPixelOffset( float height );
|
||||
void UpdateFollowEntity();
|
||||
virtual void UpdatePlayers();
|
||||
void UpdateObjects(); // objects bound to entities
|
||||
MapObject_t* FindObjectByID(int objectID);
|
||||
virtual bool IsRadarLocked() {return false;}
|
||||
|
||||
virtual bool DrawIcon( MapObject_t *obj );
|
||||
|
||||
/*virtual bool DrawIcon( int textureID,
|
||||
int offscreenTextureID,
|
||||
Vector pos,
|
||||
float scale,
|
||||
float angle,
|
||||
int alpha = 255,
|
||||
const char *text = NULL,
|
||||
Color *textColor = NULL,
|
||||
float status = -1,
|
||||
Color *statusColor = NULL,
|
||||
int objectType = OBJECT_TYPE_NORMAL );*/
|
||||
|
||||
int m_nMode;
|
||||
Vector2D m_vPosition;
|
||||
Vector2D m_vSize;
|
||||
float m_flChangeSpeed;
|
||||
float m_flIconSize;
|
||||
|
||||
|
||||
IViewPort * m_pViewPort;
|
||||
MapPlayer_t m_Players[MAX_PLAYERS];
|
||||
CUtlDict< int, int> m_TextureIDs;
|
||||
CUtlVector<MapObject_t> m_Objects;
|
||||
|
||||
Color m_TeamColors[MAX_TEAMS];
|
||||
int m_TeamIcons[MAX_TEAMS];
|
||||
int m_ObjectIcons[64];
|
||||
int m_ObjectCounterID;
|
||||
vgui::HFont m_hIconFont;
|
||||
|
||||
|
||||
bool m_bShowNames;
|
||||
bool m_bShowTrails;
|
||||
bool m_bShowHealth;
|
||||
|
||||
int m_nMapTextureID; // texture id for current overview image
|
||||
|
||||
KeyValues * m_MapKeyValues; // keyvalues describing overview parameters
|
||||
|
||||
Vector m_MapOrigin; // read from KeyValues files
|
||||
float m_fMapScale; // origin and scale used when screenshot was made
|
||||
bool m_bRotateMap; // if true roatate map around 90 degress, so it fits better to 4:3 screen ratio
|
||||
|
||||
int m_nFollowEntity;// entity number to follow, 0 = off
|
||||
CPanelAnimationVar( float, m_fZoom, "zoom", "1.0" ); // current zoom n = overview panel shows 1/n^2 of whole map'
|
||||
float m_fFullZoom; // best zoom factor for full map view (1.0 is map is a square)
|
||||
Vector2D m_ViewOrigin; // map coordinates that are in the center of the pverview panel
|
||||
Vector2D m_MapCenter; // map coordinates that are in the center of the pverview panel
|
||||
|
||||
float m_fNextUpdateTime;
|
||||
float m_fViewAngle; // rotation of overview map
|
||||
float m_fWorldTime; // current world time
|
||||
float m_fNextTrailUpdate; // next time to update player trails
|
||||
float m_fTrailUpdateInterval; // if -1 don't show trails
|
||||
bool m_bFollowAngle; // if true, map rotates with view angle
|
||||
|
||||
|
||||
};
|
||||
|
||||
extern IMapOverviewPanel *g_pMapOverview;
|
||||
|
||||
#endif //
|
||||
119
sp/src/game/client/game_controls/mouseoverhtmlbutton.h
Normal file
119
sp/src/game/client/game_controls/mouseoverhtmlbutton.h
Normal file
@@ -0,0 +1,119 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef MOUSEOVERHTMLBUTTON_H
|
||||
#define MOUSEOVERHTMLBUTTON_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Triggers a new html page when the mouse goes over the button
|
||||
//-----------------------------------------------------------------------------
|
||||
class MouseOverHTMLButton : public vgui::Button
|
||||
{
|
||||
public:
|
||||
MouseOverHTMLButton(vgui::Panel *parent, const char *panelName, vgui::HTML *html, const char *page) :
|
||||
Button( parent, panelName, "MouseOverHTMLButton")
|
||||
{
|
||||
m_pHTML = html;
|
||||
m_iClass = 0;
|
||||
m_iIndex = -1;
|
||||
m_bAddShortCut = true;
|
||||
if ( page )
|
||||
{
|
||||
Q_strncpy( m_sPage, page, sizeof( m_sPage ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(m_sPage, 0x0, sizeof( m_sPage ) );
|
||||
}
|
||||
}
|
||||
|
||||
void SetClass(int pClass, int index) { m_iClass = pClass; m_iIndex = index;}
|
||||
int GetClass() { return m_iClass; }
|
||||
|
||||
void SetAddHotKey( bool state ) { m_bAddShortCut = state; }
|
||||
|
||||
void SetPage( const char *page )
|
||||
{
|
||||
if ( page )
|
||||
{
|
||||
Q_strncpy( m_sPage, page, sizeof( m_sPage ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(m_sPage, 0x0, sizeof( m_sPage ) );
|
||||
}
|
||||
}
|
||||
|
||||
void SetHTML( vgui::HTML *html)
|
||||
{
|
||||
m_pHTML = html;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
virtual void OnCursorEntered()
|
||||
{
|
||||
Button::OnCursorEntered();
|
||||
if ( m_pHTML && strlen(m_sPage) > 0 )
|
||||
{
|
||||
m_pHTML->OpenURL(m_sPage);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void SetText(const char *text)
|
||||
{
|
||||
if ( m_iIndex != -1 )
|
||||
{
|
||||
wchar_t newText[ 128 ];
|
||||
wchar_t localizeText[ 128 ];
|
||||
wchar_t *ansiLocal;
|
||||
if ( text[0] == '#' && ( ansiLocal = g_pVGuiLocalize->Find( text ) ) )
|
||||
{
|
||||
// wcsncpy will crash if ansiLocal is null... *sigh*
|
||||
wcsncpy(localizeText, ansiLocal, sizeof(localizeText)/sizeof(wchar_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( text, localizeText, sizeof( localizeText ) );
|
||||
}
|
||||
|
||||
if ( m_bAddShortCut )
|
||||
{
|
||||
#ifdef WIN32
|
||||
_snwprintf( newText, sizeof( newText )/ sizeof( wchar_t ), L"&%i %s", m_iIndex, localizeText);
|
||||
#else
|
||||
_snwprintf( newText, sizeof( newText )/ sizeof( wchar_t ), L"&%i %S", m_iIndex, localizeText);
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( newText, localizeText, sizeof( newText ) );
|
||||
}
|
||||
|
||||
Button::SetText( newText );
|
||||
}
|
||||
else
|
||||
{
|
||||
Button::SetText( text );
|
||||
}
|
||||
}
|
||||
|
||||
vgui::HTML *m_pHTML;
|
||||
char m_sPage[ 255 ];
|
||||
int m_iClass;
|
||||
int m_iIndex;
|
||||
bool m_bAddShortCut;
|
||||
};
|
||||
|
||||
|
||||
#endif // MOUSEOVERHTMLBUTTON_H
|
||||
186
sp/src/game/client/game_controls/mouseoverpanelbutton.h
Normal file
186
sp/src/game/client/game_controls/mouseoverpanelbutton.h
Normal file
@@ -0,0 +1,186 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef MOUSEOVERPANELBUTTON_H
|
||||
#define MOUSEOVERPANELBUTTON_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
#include <vgui/KeyCode.h>
|
||||
#include <filesystem.h>
|
||||
|
||||
extern vgui::Panel *g_lastPanel;
|
||||
extern vgui::Button *g_lastButton;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Triggers a new panel when the mouse goes over the button
|
||||
//
|
||||
// the new panel has the same dimensions as the passed templatePanel and is of
|
||||
// the same class.
|
||||
//
|
||||
// must at least inherit from vgui::EditablePanel to support LoadControlSettings
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T>
|
||||
class MouseOverButton : public vgui::Button
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( MouseOverButton, vgui::Button );
|
||||
|
||||
public:
|
||||
MouseOverButton(vgui::Panel *parent, const char *panelName, T *templatePanel ) :
|
||||
Button( parent, panelName, "MouseOverButton")
|
||||
{
|
||||
m_pPanel = new T( parent, NULL );
|
||||
m_pPanel ->SetVisible( false );
|
||||
|
||||
// copy size&pos from template panel
|
||||
int x,y,wide,tall;
|
||||
templatePanel->GetBounds( x, y, wide, tall );
|
||||
m_pPanel->SetBounds( x, y, wide, tall );
|
||||
int px, py;
|
||||
templatePanel->GetPinOffset( px, py );
|
||||
int rx, ry;
|
||||
templatePanel->GetResizeOffset( rx, ry );
|
||||
// Apply pin settings from template, too
|
||||
m_pPanel->SetAutoResize( templatePanel->GetPinCorner(), templatePanel->GetAutoResize(), px, py, rx, ry );
|
||||
|
||||
m_bPreserveArmedButtons = false;
|
||||
m_bUpdateDefaultButtons = false;
|
||||
}
|
||||
|
||||
virtual void SetPreserveArmedButtons( bool bPreserve ){ m_bPreserveArmedButtons = bPreserve; }
|
||||
virtual void SetUpdateDefaultButtons( bool bUpdate ){ m_bUpdateDefaultButtons = bUpdate; }
|
||||
|
||||
virtual void ShowPage()
|
||||
{
|
||||
if( m_pPanel )
|
||||
{
|
||||
m_pPanel->SetVisible( true );
|
||||
m_pPanel->MoveToFront();
|
||||
g_lastPanel = m_pPanel;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void HidePage()
|
||||
{
|
||||
if ( m_pPanel )
|
||||
{
|
||||
m_pPanel->SetVisible( false );
|
||||
}
|
||||
}
|
||||
|
||||
const char *GetClassPage( const char *className )
|
||||
{
|
||||
static char classPanel[ _MAX_PATH ];
|
||||
Q_snprintf( classPanel, sizeof( classPanel ), "classes/%s.res", className);
|
||||
|
||||
if ( g_pFullFileSystem->FileExists( classPanel, IsX360() ? "MOD" : "GAME" ) )
|
||||
{
|
||||
}
|
||||
else if (g_pFullFileSystem->FileExists( "classes/default.res", IsX360() ? "MOD" : "GAME" ) )
|
||||
{
|
||||
Q_snprintf ( classPanel, sizeof( classPanel ), "classes/default.res" );
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return classPanel;
|
||||
}
|
||||
|
||||
#ifdef REFRESH_CLASSMENU_TOOL
|
||||
|
||||
void RefreshClassPage( void )
|
||||
{
|
||||
m_pPanel->LoadControlSettings( GetClassPage( GetName() ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
virtual void ApplySettings( KeyValues *resourceData )
|
||||
{
|
||||
BaseClass::ApplySettings( resourceData );
|
||||
|
||||
// name, position etc of button is set, now load matching
|
||||
// resource file for associated info panel:
|
||||
m_pPanel->LoadControlSettings( GetClassPage( GetName() ) );
|
||||
}
|
||||
|
||||
T *GetClassPanel( void ) { return m_pPanel; }
|
||||
|
||||
virtual void OnCursorExited()
|
||||
{
|
||||
if ( !m_bPreserveArmedButtons )
|
||||
{
|
||||
BaseClass::OnCursorExited();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnCursorEntered()
|
||||
{
|
||||
BaseClass::OnCursorEntered();
|
||||
|
||||
if ( !IsEnabled() )
|
||||
return;
|
||||
|
||||
// are we updating the default buttons?
|
||||
if ( m_bUpdateDefaultButtons )
|
||||
{
|
||||
SetAsDefaultButton( 1 );
|
||||
}
|
||||
|
||||
// are we preserving the armed state (and need to turn off the old button)?
|
||||
if ( m_bPreserveArmedButtons )
|
||||
{
|
||||
if ( g_lastButton && g_lastButton != this )
|
||||
{
|
||||
g_lastButton->SetArmed( false );
|
||||
}
|
||||
|
||||
g_lastButton = this;
|
||||
}
|
||||
|
||||
// turn on our panel (if it isn't already)
|
||||
if ( m_pPanel && ( !m_pPanel->IsVisible() ) )
|
||||
{
|
||||
// turn off the previous panel
|
||||
if ( g_lastPanel && g_lastPanel->IsVisible() )
|
||||
{
|
||||
g_lastPanel->SetVisible( false );
|
||||
}
|
||||
|
||||
ShowPage();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnKeyCodeReleased( vgui::KeyCode code )
|
||||
{
|
||||
BaseClass::OnKeyCodeReleased( code );
|
||||
|
||||
if ( m_bPreserveArmedButtons )
|
||||
{
|
||||
if ( g_lastButton )
|
||||
{
|
||||
g_lastButton->SetArmed( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T *m_pPanel;
|
||||
bool m_bPreserveArmedButtons;
|
||||
bool m_bUpdateDefaultButtons;
|
||||
};
|
||||
|
||||
#define MouseOverPanelButton MouseOverButton<vgui::EditablePanel>
|
||||
|
||||
#endif // MOUSEOVERPANELBUTTON_H
|
||||
154
sp/src/game/client/game_controls/spectatorgui.h
Normal file
154
sp/src/game/client/game_controls/spectatorgui.h
Normal file
@@ -0,0 +1,154 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef SPECTATORGUI_H
|
||||
#define SPECTATORGUI_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui/KeyCode.h>
|
||||
#include <vgui_controls/Frame.h>
|
||||
#include <vgui_controls/EditablePanel.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
#include <vgui_controls/ComboBox.h>
|
||||
#include <igameevents.h>
|
||||
#include "GameEventListener.h"
|
||||
|
||||
#include <game/client/iviewport.h>
|
||||
|
||||
class KeyValues;
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
class TextEntry;
|
||||
class Button;
|
||||
class Panel;
|
||||
class ImagePanel;
|
||||
class ComboBox;
|
||||
}
|
||||
|
||||
#define BLACK_BAR_COLOR Color(0, 0, 0, 196)
|
||||
|
||||
class IBaseFileSystem;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spectator UI
|
||||
//-----------------------------------------------------------------------------
|
||||
class CSpectatorGUI : public vgui::EditablePanel, public IViewPortPanel
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CSpectatorGUI, vgui::EditablePanel );
|
||||
|
||||
public:
|
||||
CSpectatorGUI( IViewPort *pViewPort );
|
||||
virtual ~CSpectatorGUI();
|
||||
|
||||
virtual const char *GetName( void ) { return PANEL_SPECGUI; }
|
||||
virtual void SetData(KeyValues *data) {};
|
||||
virtual void Reset() {};
|
||||
virtual void Update();
|
||||
virtual bool NeedsUpdate( void ) { return false; }
|
||||
virtual bool HasInputElements( void ) { return false; }
|
||||
virtual void ShowPanel( bool bShow );
|
||||
|
||||
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
|
||||
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
|
||||
virtual bool IsVisible() { return BaseClass::IsVisible(); }
|
||||
virtual void SetParent(vgui::VPANEL parent) { BaseClass::SetParent(parent); }
|
||||
virtual void OnThink();
|
||||
|
||||
virtual int GetTopBarHeight() { return m_pTopBar->GetTall(); }
|
||||
virtual int GetBottomBarHeight() { return m_pBottomBarBlank->GetTall(); }
|
||||
|
||||
virtual bool ShouldShowPlayerLabel( int specmode );
|
||||
|
||||
virtual Color GetBlackBarColor( void ) { return BLACK_BAR_COLOR; }
|
||||
|
||||
virtual const char *GetResFile( void ) { return "Resource/UI/Spectator.res"; }
|
||||
|
||||
protected:
|
||||
|
||||
void SetLabelText(const char *textEntryName, const char *text);
|
||||
void SetLabelText(const char *textEntryName, wchar_t *text);
|
||||
void MoveLabelToFront(const char *textEntryName);
|
||||
void UpdateTimer();
|
||||
void SetLogoImage(const char *image);
|
||||
|
||||
protected:
|
||||
enum { INSET_OFFSET = 2 } ;
|
||||
|
||||
// vgui overrides
|
||||
virtual void PerformLayout();
|
||||
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
|
||||
// virtual void OnCommand( const char *command );
|
||||
|
||||
vgui::Panel *m_pTopBar;
|
||||
vgui::Panel *m_pBottomBarBlank;
|
||||
|
||||
vgui::ImagePanel *m_pBannerImage;
|
||||
vgui::Label *m_pPlayerLabel;
|
||||
|
||||
IViewPort *m_pViewPort;
|
||||
|
||||
// bool m_bHelpShown;
|
||||
// bool m_bInsetVisible;
|
||||
bool m_bSpecScoreboard;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: the bottom bar panel, this is a separate panel because it
|
||||
// wants mouse input and the main window doesn't
|
||||
//----------------------------------------------------------------------------
|
||||
class CSpectatorMenu : public vgui::Frame, public IViewPortPanel, public CGameEventListener
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CSpectatorMenu, vgui::Frame );
|
||||
|
||||
public:
|
||||
CSpectatorMenu( IViewPort *pViewPort );
|
||||
~CSpectatorMenu() {}
|
||||
|
||||
virtual const char *GetName( void ) { return PANEL_SPECMENU; }
|
||||
virtual void SetData(KeyValues *data) {};
|
||||
virtual void Reset( void ) { m_pPlayerList->DeleteAllItems(); }
|
||||
virtual void Update( void );
|
||||
virtual bool NeedsUpdate( void ) { return false; }
|
||||
virtual bool HasInputElements( void ) { return true; }
|
||||
virtual void ShowPanel( bool bShow );
|
||||
virtual void FireGameEvent( IGameEvent *event );
|
||||
|
||||
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
|
||||
virtual bool IsVisible() { return BaseClass::IsVisible(); }
|
||||
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
|
||||
virtual void SetParent(vgui::VPANEL parent) { BaseClass::SetParent(parent); }
|
||||
|
||||
private:
|
||||
// VGUI2 overrides
|
||||
MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data );
|
||||
virtual void OnCommand( const char *command );
|
||||
virtual void OnKeyCodePressed(vgui::KeyCode code);
|
||||
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
|
||||
virtual void PerformLayout();
|
||||
|
||||
void SetViewModeText( const char *text ) { m_pViewOptions->SetText( text ); }
|
||||
void SetPlayerFgColor( Color c1 ) { m_pPlayerList->SetFgColor(c1); }
|
||||
|
||||
vgui::ComboBox *m_pPlayerList;
|
||||
vgui::ComboBox *m_pViewOptions;
|
||||
vgui::ComboBox *m_pConfigSettings;
|
||||
|
||||
vgui::Button *m_pLeftButton;
|
||||
vgui::Button *m_pRightButton;
|
||||
|
||||
IViewPort *m_pViewPort;
|
||||
ButtonCode_t m_iDuckKey;
|
||||
};
|
||||
|
||||
extern CSpectatorGUI * g_pSpectatorGUI;
|
||||
|
||||
#endif // SPECTATORGUI_H
|
||||
444
sp/src/game/client/game_controls/teammenu.cpp
Normal file
444
sp/src/game/client/game_controls/teammenu.cpp
Normal file
@@ -0,0 +1,444 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include <cdll_client_int.h>
|
||||
|
||||
#include "teammenu.h"
|
||||
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <KeyValues.h>
|
||||
#include <vgui_controls/ImageList.h>
|
||||
#include <filesystem.h>
|
||||
|
||||
#include <vgui_controls/RichText.h>
|
||||
#include <vgui_controls/Label.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
#include <vgui_controls/HTML.h>
|
||||
|
||||
#include "IGameUIFuncs.h" // for key bindings
|
||||
#include <igameresources.h>
|
||||
#include <game/client/iviewport.h>
|
||||
#include <stdlib.h> // MAX_PATH define
|
||||
#include <stdio.h>
|
||||
#include "byteswap.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern IGameUIFuncs *gameuifuncs; // for key binding details
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
void UpdateCursorState();
|
||||
// void DuckMessage(const char *str);
|
||||
|
||||
// helper function
|
||||
const char *GetStringTeamColor( int i )
|
||||
{
|
||||
switch( i )
|
||||
{
|
||||
case 0:
|
||||
return "team0";
|
||||
|
||||
case 1:
|
||||
return "team1";
|
||||
|
||||
case 2:
|
||||
return "team2";
|
||||
|
||||
case 3:
|
||||
return "team3";
|
||||
|
||||
case 4:
|
||||
default:
|
||||
return "team4";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CTeamMenu::CTeamMenu(IViewPort *pViewPort) : Frame(NULL, PANEL_TEAM )
|
||||
{
|
||||
m_pViewPort = pViewPort;
|
||||
m_iJumpKey = BUTTON_CODE_INVALID; // this is looked up in Activate()
|
||||
m_iScoreBoardKey = BUTTON_CODE_INVALID; // this is looked up in Activate()
|
||||
|
||||
// initialize dialog
|
||||
SetTitle("", true);
|
||||
|
||||
// load the new scheme early!!
|
||||
SetScheme("ClientScheme");
|
||||
SetMoveable(false);
|
||||
SetSizeable(false);
|
||||
|
||||
// hide the system buttons
|
||||
SetTitleBarVisible( false );
|
||||
SetProportional(true);
|
||||
|
||||
// info window about this map
|
||||
m_pMapInfo = new RichText( this, "MapInfo" );
|
||||
|
||||
#if defined( ENABLE_HTML_WINDOW )
|
||||
m_pMapInfoHTML = new HTML( this, "MapInfoHTML");
|
||||
#endif
|
||||
|
||||
LoadControlSettings("Resource/UI/TeamMenu.res");
|
||||
InvalidateLayout();
|
||||
|
||||
m_szMapName[0] = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CTeamMenu::~CTeamMenu()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the text color of the map description field
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTeamMenu::ApplySchemeSettings(IScheme *pScheme)
|
||||
{
|
||||
BaseClass::ApplySchemeSettings(pScheme);
|
||||
m_pMapInfo->SetFgColor( pScheme->GetColor("MapDescriptionText", Color(255, 255, 255, 0)) );
|
||||
|
||||
if ( *m_szMapName )
|
||||
{
|
||||
LoadMapPage( m_szMapName ); // reload the map description to pick up the color
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: makes the user choose the auto assign option
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTeamMenu::AutoAssign()
|
||||
{
|
||||
engine->ClientCmd("jointeam 0");
|
||||
OnClose();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: shows the team menu
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTeamMenu::ShowPanel(bool bShow)
|
||||
{
|
||||
if ( BaseClass::IsVisible() == bShow )
|
||||
return;
|
||||
|
||||
if ( bShow )
|
||||
{
|
||||
Activate();
|
||||
|
||||
SetMouseInputEnabled( true );
|
||||
|
||||
// get key bindings if shown
|
||||
|
||||
if( m_iJumpKey == BUTTON_CODE_INVALID ) // you need to lookup the jump key AFTER the engine has loaded
|
||||
{
|
||||
m_iJumpKey = gameuifuncs->GetButtonCodeForBind( "jump" );
|
||||
}
|
||||
|
||||
if ( m_iScoreBoardKey == BUTTON_CODE_INVALID )
|
||||
{
|
||||
m_iScoreBoardKey = gameuifuncs->GetButtonCodeForBind( "showscores" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetVisible( false );
|
||||
SetMouseInputEnabled( false );
|
||||
}
|
||||
|
||||
m_pViewPort->ShowBackGround( bShow );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: updates the UI with a new map name and map html page, and sets up the team buttons
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTeamMenu::Update()
|
||||
{
|
||||
char mapname[MAX_MAP_NAME];
|
||||
|
||||
Q_FileBase( engine->GetLevelName(), mapname, sizeof(mapname) );
|
||||
|
||||
SetLabelText( "mapname", mapname );
|
||||
|
||||
LoadMapPage( mapname );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: chooses and loads the text page to display that describes mapName map
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTeamMenu::LoadMapPage( const char *mapName )
|
||||
{
|
||||
// Save off the map name so we can re-load the page in ApplySchemeSettings().
|
||||
Q_strncpy( m_szMapName, mapName, strlen( mapName ) + 1 );
|
||||
|
||||
char mapRES[ MAX_PATH ];
|
||||
|
||||
char uilanguage[ 64 ];
|
||||
engine->GetUILanguage( uilanguage, sizeof( uilanguage ) );
|
||||
|
||||
Q_snprintf( mapRES, sizeof( mapRES ), "resource/maphtml/%s_%s.html", mapName, uilanguage );
|
||||
|
||||
bool bFoundHTML = false;
|
||||
|
||||
if ( !g_pFullFileSystem->FileExists( mapRES ) )
|
||||
{
|
||||
// try english
|
||||
Q_snprintf( mapRES, sizeof( mapRES ), "resource/maphtml/%s_english.html", mapName );
|
||||
}
|
||||
else
|
||||
{
|
||||
bFoundHTML = true;
|
||||
}
|
||||
|
||||
if( bFoundHTML || g_pFullFileSystem->FileExists( mapRES ) )
|
||||
{
|
||||
// it's a local HTML file
|
||||
char localURL[ _MAX_PATH + 7 ];
|
||||
Q_strncpy( localURL, "file://", sizeof( localURL ) );
|
||||
|
||||
char pPathData[ _MAX_PATH ];
|
||||
g_pFullFileSystem->GetLocalPath( mapRES, pPathData, sizeof(pPathData) );
|
||||
Q_strncat( localURL, pPathData, sizeof( localURL ), COPY_ALL_CHARACTERS );
|
||||
|
||||
// force steam to dump a local copy
|
||||
g_pFullFileSystem->GetLocalCopy( pPathData );
|
||||
|
||||
m_pMapInfo->SetVisible( false );
|
||||
|
||||
#if defined( ENABLE_HTML_WINDOW )
|
||||
m_pMapInfoHTML->SetVisible( true );
|
||||
m_pMapInfoHTML->OpenURL( localURL, NULL );
|
||||
#endif
|
||||
InvalidateLayout();
|
||||
Repaint();
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pMapInfo->SetVisible( true );
|
||||
|
||||
#if defined( ENABLE_HTML_WINDOW )
|
||||
m_pMapInfoHTML->SetVisible( false );
|
||||
#endif
|
||||
}
|
||||
|
||||
Q_snprintf( mapRES, sizeof( mapRES ), "maps/%s.txt", mapName);
|
||||
|
||||
// if no map specific description exists, load default text
|
||||
if( !g_pFullFileSystem->FileExists( mapRES ) )
|
||||
{
|
||||
if ( g_pFullFileSystem->FileExists( "maps/default.txt" ) )
|
||||
{
|
||||
Q_snprintf ( mapRES, sizeof( mapRES ), "maps/default.txt");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pMapInfo->SetText( "" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FileHandle_t f = g_pFullFileSystem->Open( mapRES, "r" );
|
||||
|
||||
// read into a memory block
|
||||
int fileSize = g_pFullFileSystem->Size(f);
|
||||
int dataSize = fileSize + sizeof( wchar_t );
|
||||
if ( dataSize % 2 )
|
||||
++dataSize;
|
||||
wchar_t *memBlock = (wchar_t *)malloc(dataSize);
|
||||
memset( memBlock, 0x0, dataSize);
|
||||
int bytesRead = g_pFullFileSystem->Read(memBlock, fileSize, f);
|
||||
if ( bytesRead < fileSize )
|
||||
{
|
||||
// NULL-terminate based on the length read in, since Read() can transform \r\n to \n and
|
||||
// return fewer bytes than we were expecting.
|
||||
char *data = reinterpret_cast<char *>( memBlock );
|
||||
data[ bytesRead ] = 0;
|
||||
data[ bytesRead+1 ] = 0;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
if ( ((ucs2 *)memBlock)[0] == 0xFEFF )
|
||||
{
|
||||
// convert the win32 ucs2 data to wchar_t
|
||||
dataSize*=2;// need to *2 to account for ucs2 to wchar_t (4byte) growth
|
||||
wchar_t *memBlockConverted = (wchar_t *)malloc(dataSize);
|
||||
V_UCS2ToUnicode( (ucs2 *)memBlock, memBlockConverted, dataSize );
|
||||
free(memBlock);
|
||||
memBlock = memBlockConverted;
|
||||
}
|
||||
#else
|
||||
// null-terminate the stream (redundant, since we memset & then trimmed the transformed buffer already)
|
||||
memBlock[dataSize / sizeof(wchar_t) - 1] = 0x0000;
|
||||
#endif
|
||||
// ensure little-endian unicode reads correctly on all platforms
|
||||
CByteswap byteSwap;
|
||||
byteSwap.SetTargetBigEndian( false );
|
||||
byteSwap.SwapBufferToTargetEndian( memBlock, memBlock, dataSize/sizeof(wchar_t) );
|
||||
|
||||
// check the first character, make sure this a little-endian unicode file
|
||||
if ( memBlock[0] != 0xFEFF )
|
||||
{
|
||||
// its a ascii char file
|
||||
m_pMapInfo->SetText( reinterpret_cast<char *>( memBlock ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pMapInfo->SetText( memBlock+1 );
|
||||
}
|
||||
// go back to the top of the text buffer
|
||||
m_pMapInfo->GotoTextStart();
|
||||
|
||||
g_pFullFileSystem->Close( f );
|
||||
free(memBlock);
|
||||
|
||||
InvalidateLayout();
|
||||
Repaint();
|
||||
}
|
||||
|
||||
/*
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the text on and displays the team buttons
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTeamMenu::MakeTeamButtons(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for( i = 0; i< m_pTeamButtons.Count(); i++ )
|
||||
{
|
||||
m_pTeamButtons[i]->SetVisible(false);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
const char *teamname = GameResources()->GetTeamName( i );
|
||||
|
||||
if ( !teamname || !teamname[0] )
|
||||
return; // no more teams
|
||||
|
||||
char buttonText[32];
|
||||
Q_snprintf( buttonText, sizeof(buttonText), "&%i %s", i +1, teamname );
|
||||
m_pTeamButtons[i]->SetText( buttonText );
|
||||
|
||||
m_pTeamButtons[i]->SetCommand( new KeyValues("TeamButton", "team", i ) );
|
||||
IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
|
||||
m_pTeamButtons[i]->SetArmedColor(pScheme->GetColor(GetStringTeamColor(i), Color(255, 255, 255, 255)) , pScheme->GetColor("SelectionBG", Color(255, 255, 255, 0)) );
|
||||
m_pTeamButtons[i]->SetDepressedColor( pScheme->GetColor(GetStringTeamColor(i), Color(255, 255, 255, 255)), pScheme->GetColor("ButtonArmedBgColor", Color(255, 255, 255, 0)) );
|
||||
m_pTeamButtons[i]->SetDefaultColor( pScheme->GetColor(GetStringTeamColor(i), Color(255, 255, 255, 255)), pScheme->GetColor("ButtonDepressedBgColor", Color(255, 255, 255, 0)) );
|
||||
m_pTeamButtons[i]->SetVisible(true);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: When a team button is pressed it triggers this function to cause the player to join a team
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTeamMenu::OnTeamButton( int team )
|
||||
{
|
||||
char cmd[64];
|
||||
if( team >= m_iNumTeams ) // its a special button
|
||||
{
|
||||
if( team == m_iNumTeams ) // first extra team is auto assign
|
||||
{
|
||||
Q_snprintf( cmd, sizeof( cmd ), "jointeam 5" );
|
||||
}
|
||||
else // next is spectate
|
||||
{
|
||||
// DuckMessage( "#Spec_Duck" );
|
||||
gViewPortInterface->ShowBackGround( false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_snprintf( cmd, sizeof( cmd ), "jointeam %i", team + 1 );
|
||||
//g_iTeamNumber = team + 1;
|
||||
}
|
||||
|
||||
engine->ClientCmd(cmd);
|
||||
SetVisible( false );
|
||||
OnClose();
|
||||
} */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the text of a control by name
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTeamMenu::SetLabelText(const char *textEntryName, const char *text)
|
||||
{
|
||||
Label *entry = dynamic_cast<Label *>(FindChildByName(textEntryName));
|
||||
if (entry)
|
||||
{
|
||||
entry->SetText(text);
|
||||
}
|
||||
}
|
||||
|
||||
void CTeamMenu::OnKeyCodePressed(KeyCode code)
|
||||
{
|
||||
int nDir = 0;
|
||||
|
||||
switch ( code )
|
||||
{
|
||||
case KEY_XBUTTON_UP:
|
||||
case KEY_XSTICK1_UP:
|
||||
case KEY_XSTICK2_UP:
|
||||
case KEY_UP:
|
||||
case KEY_XBUTTON_LEFT:
|
||||
case KEY_XSTICK1_LEFT:
|
||||
case KEY_XSTICK2_LEFT:
|
||||
case KEY_LEFT:
|
||||
nDir = -1;
|
||||
break;
|
||||
|
||||
case KEY_XBUTTON_DOWN:
|
||||
case KEY_XSTICK1_DOWN:
|
||||
case KEY_XSTICK2_DOWN:
|
||||
case KEY_DOWN:
|
||||
case KEY_XBUTTON_RIGHT:
|
||||
case KEY_XSTICK1_RIGHT:
|
||||
case KEY_XSTICK2_RIGHT:
|
||||
case KEY_RIGHT:
|
||||
nDir = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( m_iScoreBoardKey != BUTTON_CODE_INVALID && m_iScoreBoardKey == code )
|
||||
{
|
||||
gViewPortInterface->ShowPanel( PANEL_SCOREBOARD, true );
|
||||
gViewPortInterface->PostMessageToPanel( PANEL_SCOREBOARD, new KeyValues( "PollHideCode", "code", code ) );
|
||||
}
|
||||
else if ( nDir != 0 )
|
||||
{
|
||||
CUtlSortVector< SortedPanel_t, CSortedPanelYLess > vecSortedButtons;
|
||||
VguiPanelGetSortedChildButtonList( this, (void*)&vecSortedButtons, "&", 0 );
|
||||
|
||||
if ( VguiPanelNavigateSortedChildButtonList( (void*)&vecSortedButtons, nDir ) != -1 )
|
||||
{
|
||||
// Handled!
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseClass::OnKeyCodePressed( code );
|
||||
}
|
||||
}
|
||||
86
sp/src/game/client/game_controls/teammenu.h
Normal file
86
sp/src/game/client/game_controls/teammenu.h
Normal file
@@ -0,0 +1,86 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef TEAMMENU_H
|
||||
#define TEAMMENU_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui_controls/Frame.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
|
||||
#include <game/client/iviewport.h>
|
||||
|
||||
#include <vgui/KeyCode.h>
|
||||
#include <utlvector.h>
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
class RichText;
|
||||
class HTML;
|
||||
}
|
||||
class TeamFortressViewport;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Displays the team menu
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTeamMenu : public vgui::Frame, public IViewPortPanel
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CTeamMenu, vgui::Frame );
|
||||
|
||||
public:
|
||||
CTeamMenu(IViewPort *pViewPort);
|
||||
virtual ~CTeamMenu();
|
||||
|
||||
virtual const char *GetName( void ) { return PANEL_TEAM; }
|
||||
virtual void SetData(KeyValues *data) {};
|
||||
virtual void Reset() {};
|
||||
virtual void Update();
|
||||
virtual bool NeedsUpdate( void ) { return false; }
|
||||
virtual bool HasInputElements( void ) { return true; }
|
||||
virtual void ShowPanel( bool bShow );
|
||||
|
||||
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
|
||||
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
|
||||
virtual bool IsVisible() { return BaseClass::IsVisible(); }
|
||||
virtual void SetParent( vgui::VPANEL parent ) { BaseClass::SetParent( parent ); }
|
||||
|
||||
public:
|
||||
|
||||
void AutoAssign();
|
||||
|
||||
protected:
|
||||
|
||||
// int GetNumTeams() { return m_iNumTeams; }
|
||||
|
||||
// VGUI2 overrides
|
||||
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
|
||||
virtual void OnKeyCodePressed(vgui::KeyCode code);
|
||||
|
||||
// helper functions
|
||||
virtual void SetLabelText(const char *textEntryName, const char *text);
|
||||
virtual void LoadMapPage( const char *mapName );
|
||||
// virtual void MakeTeamButtons( void );
|
||||
|
||||
// command callbacks
|
||||
// MESSAGE_FUNC_INT( OnTeamButton, "TeamButton", team );
|
||||
|
||||
IViewPort *m_pViewPort;
|
||||
vgui::RichText *m_pMapInfo;
|
||||
vgui::HTML *m_pMapInfoHTML;
|
||||
// int m_iNumTeams;
|
||||
ButtonCode_t m_iJumpKey;
|
||||
ButtonCode_t m_iScoreBoardKey;
|
||||
|
||||
char m_szMapName[ MAX_PATH ];
|
||||
};
|
||||
|
||||
|
||||
#endif // TEAMMENU_H
|
||||
446
sp/src/game/client/game_controls/vguitextwindow.cpp
Normal file
446
sp/src/game/client/game_controls/vguitextwindow.cpp
Normal file
@@ -0,0 +1,446 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "vguitextwindow.h"
|
||||
#include <networkstringtabledefs.h>
|
||||
#include <cdll_client_int.h>
|
||||
#include <clientmode_shared.h>
|
||||
|
||||
#include <vgui/IScheme.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <filesystem.h>
|
||||
#include <KeyValues.h>
|
||||
#include <convar.h>
|
||||
#include <vgui_controls/ImageList.h>
|
||||
|
||||
#include <vgui_controls/TextEntry.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
|
||||
#include <game/client/iviewport.h>
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
using namespace vgui;
|
||||
extern INetworkStringTable *g_pStringTableInfoPanel;
|
||||
|
||||
#define TEMP_HTML_FILE "textwindow_temp.html"
|
||||
|
||||
ConVar cl_disablehtmlmotd( "cl_disablehtmlmotd", "0", FCVAR_ARCHIVE, "Disable HTML motds." );
|
||||
|
||||
//=============================================================================
|
||||
// HPE_BEGIN:
|
||||
// [Forrest] Replaced text window command string with TEXTWINDOW_CMD enumeration
|
||||
// of options. Passing a command string is dangerous and allowed a server network
|
||||
// message to run arbitrary commands on the client.
|
||||
//=============================================================================
|
||||
CON_COMMAND( showinfo, "Shows a info panel: <type> <title> <message> [<command number>]" )
|
||||
{
|
||||
if ( !gViewPortInterface )
|
||||
return;
|
||||
|
||||
if ( args.ArgC() < 4 )
|
||||
return;
|
||||
|
||||
IViewPortPanel * panel = gViewPortInterface->FindPanelByName( PANEL_INFO );
|
||||
|
||||
if ( panel )
|
||||
{
|
||||
KeyValues *kv = new KeyValues("data");
|
||||
kv->SetInt( "type", Q_atoi(args[ 1 ]) );
|
||||
kv->SetString( "title", args[ 2 ] );
|
||||
kv->SetString( "message", args[ 3 ] );
|
||||
|
||||
if ( args.ArgC() == 5 )
|
||||
kv->SetString( "command", args[ 4 ] );
|
||||
|
||||
panel->SetData( kv );
|
||||
|
||||
gViewPortInterface->ShowPanel( panel, true );
|
||||
|
||||
kv->deleteThis();
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg("Couldn't find info panel.\n" );
|
||||
}
|
||||
}
|
||||
//=============================================================================
|
||||
// HPE_END
|
||||
//=============================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CTextWindow::CTextWindow(IViewPort *pViewPort) : Frame(NULL, PANEL_INFO )
|
||||
{
|
||||
// initialize dialog
|
||||
m_pViewPort = pViewPort;
|
||||
|
||||
// SetTitle("", true);
|
||||
|
||||
m_szTitle[0] = '\0';
|
||||
m_szMessage[0] = '\0';
|
||||
m_szMessageFallback[0] = '\0';
|
||||
m_nExitCommand = TEXTWINDOW_CMD_NONE;
|
||||
m_bShownURL = false;
|
||||
m_bUnloadOnDismissal = false;
|
||||
|
||||
// load the new scheme early!!
|
||||
SetScheme("ClientScheme");
|
||||
SetMoveable(false);
|
||||
SetSizeable(false);
|
||||
SetProportional(true);
|
||||
|
||||
// hide the system buttons
|
||||
SetTitleBarVisible( false );
|
||||
|
||||
m_pTextMessage = new TextEntry( this, "TextMessage" );
|
||||
#if defined( ENABLE_CHROMEHTMLWINDOW )
|
||||
m_pHTMLMessage = new CMOTDHTML( this,"HTMLMessage" );
|
||||
#else
|
||||
m_pHTMLMessage = NULL;
|
||||
#endif
|
||||
m_pTitleLabel = new Label( this, "MessageTitle", "Message Title" );
|
||||
m_pOK = new Button(this, "ok", "#PropertyDialog_OK");
|
||||
|
||||
m_pOK->SetCommand("okay");
|
||||
m_pTextMessage->SetMultiline( true );
|
||||
m_nContentType = TYPE_TEXT;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTextWindow::ApplySchemeSettings( IScheme *pScheme )
|
||||
{
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
|
||||
LoadControlSettings("Resource/UI/TextWindow.res");
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CTextWindow::~CTextWindow()
|
||||
{
|
||||
// remove temp file again
|
||||
g_pFullFileSystem->RemoveFile( TEMP_HTML_FILE, "DEFAULT_WRITE_PATH" );
|
||||
}
|
||||
|
||||
void CTextWindow::Reset( void )
|
||||
{
|
||||
//=============================================================================
|
||||
// HPE_BEGIN:
|
||||
// [Forrest] Replace strange hard-coded default message with hard-coded error message.
|
||||
//=============================================================================
|
||||
Q_strcpy( m_szTitle, "Error loading info message." );
|
||||
Q_strcpy( m_szMessage, "" );
|
||||
Q_strcpy( m_szMessageFallback, "" );
|
||||
//=============================================================================
|
||||
// HPE_END
|
||||
//=============================================================================
|
||||
|
||||
m_nExitCommand = TEXTWINDOW_CMD_NONE;
|
||||
m_nContentType = TYPE_TEXT;
|
||||
m_bShownURL = false;
|
||||
m_bUnloadOnDismissal = false;
|
||||
Update();
|
||||
}
|
||||
|
||||
void CTextWindow::ShowText( const char *text )
|
||||
{
|
||||
m_pTextMessage->SetVisible( true );
|
||||
m_pTextMessage->SetText( text );
|
||||
m_pTextMessage->GotoTextStart();
|
||||
}
|
||||
|
||||
void CTextWindow::ShowURL( const char *URL, bool bAllowUserToDisable )
|
||||
{
|
||||
#if defined( ENABLE_CHROMEHTMLWINDOW )
|
||||
#ifdef _DEBUG
|
||||
Msg( "CTextWindow::ShowURL( %s )\n", URL );
|
||||
#endif
|
||||
|
||||
ClientModeShared *mode = ( ClientModeShared * )GetClientModeNormal();
|
||||
if ( ( bAllowUserToDisable && cl_disablehtmlmotd.GetBool() ) || !mode->IsHTMLInfoPanelAllowed() )
|
||||
{
|
||||
Warning( "Blocking HTML info panel '%s'; Using plaintext instead.\n", URL );
|
||||
|
||||
// User has disabled HTML TextWindows. Show the fallback as text only.
|
||||
if ( g_pStringTableInfoPanel )
|
||||
{
|
||||
int index = g_pStringTableInfoPanel->FindStringIndex( "motd_text" );
|
||||
if ( index != ::INVALID_STRING_INDEX )
|
||||
{
|
||||
int length = 0;
|
||||
const char *data = (const char *)g_pStringTableInfoPanel->GetStringUserData( index, &length );
|
||||
if ( data && data[0] )
|
||||
{
|
||||
m_pHTMLMessage->SetVisible( false );
|
||||
ShowText( data );
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
m_pHTMLMessage->SetVisible( true );
|
||||
m_pHTMLMessage->OpenURL( URL, NULL );
|
||||
m_bShownURL = true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void CTextWindow::ShowIndex( const char *entry )
|
||||
{
|
||||
const char *data = NULL;
|
||||
int length = 0;
|
||||
|
||||
if ( NULL == g_pStringTableInfoPanel )
|
||||
return;
|
||||
|
||||
int index = g_pStringTableInfoPanel->FindStringIndex( m_szMessage );
|
||||
|
||||
if ( index != ::INVALID_STRING_INDEX )
|
||||
data = (const char *)g_pStringTableInfoPanel->GetStringUserData( index, &length );
|
||||
|
||||
if ( !data || !data[0] )
|
||||
return; // nothing to show
|
||||
|
||||
// is this a web URL ?
|
||||
if ( !Q_strncmp( data, "http://", 7 ) || !Q_strncmp( data, "https://", 8 ) )
|
||||
{
|
||||
ShowURL( data );
|
||||
return;
|
||||
}
|
||||
|
||||
// try to figure out if this is HTML or not
|
||||
if ( data[0] != '<' )
|
||||
{
|
||||
ShowText( data );
|
||||
return;
|
||||
}
|
||||
|
||||
// data is a HTML, we have to write to a file and then load the file
|
||||
FileHandle_t hFile = g_pFullFileSystem->Open( TEMP_HTML_FILE, "wb", "DEFAULT_WRITE_PATH" );
|
||||
|
||||
if ( hFile == FILESYSTEM_INVALID_HANDLE )
|
||||
return;
|
||||
|
||||
g_pFullFileSystem->Write( data, length, hFile );
|
||||
g_pFullFileSystem->Close( hFile );
|
||||
|
||||
if ( g_pFullFileSystem->Size( TEMP_HTML_FILE ) != (unsigned int)length )
|
||||
return; // something went wrong while writing
|
||||
|
||||
ShowFile( TEMP_HTML_FILE );
|
||||
}
|
||||
|
||||
void CTextWindow::ShowFile( const char *filename )
|
||||
{
|
||||
if ( Q_stristr( filename, ".htm" ) || Q_stristr( filename, ".html" ) )
|
||||
{
|
||||
// it's a local HTML file
|
||||
char localURL[ _MAX_PATH + 7 ];
|
||||
Q_strncpy( localURL, "file://", sizeof( localURL ) );
|
||||
|
||||
char pPathData[ _MAX_PATH ];
|
||||
g_pFullFileSystem->GetLocalPath( filename, pPathData, sizeof(pPathData) );
|
||||
Q_strncat( localURL, pPathData, sizeof( localURL ), COPY_ALL_CHARACTERS );
|
||||
|
||||
ShowURL( localURL );
|
||||
}
|
||||
else
|
||||
{
|
||||
// read from local text from file
|
||||
FileHandle_t f = g_pFullFileSystem->Open( m_szMessage, "rb", "GAME" );
|
||||
|
||||
if ( !f )
|
||||
return;
|
||||
|
||||
char buffer[2048];
|
||||
|
||||
int size = MIN( g_pFullFileSystem->Size( f ), sizeof(buffer)-1 ); // just allow 2KB
|
||||
|
||||
g_pFullFileSystem->Read( buffer, size, f );
|
||||
g_pFullFileSystem->Close( f );
|
||||
|
||||
buffer[size]=0; //terminate string
|
||||
|
||||
ShowText( buffer );
|
||||
}
|
||||
}
|
||||
|
||||
void CTextWindow::Update( void )
|
||||
{
|
||||
SetTitle( m_szTitle, false );
|
||||
|
||||
m_pTitleLabel->SetText( m_szTitle );
|
||||
|
||||
#if defined( ENABLE_CHROMEHTMLWINDOW )
|
||||
m_pHTMLMessage->SetVisible( false );
|
||||
#endif
|
||||
m_pTextMessage->SetVisible( false );
|
||||
|
||||
if ( m_nContentType == TYPE_INDEX )
|
||||
{
|
||||
ShowIndex( m_szMessage );
|
||||
}
|
||||
else if ( m_nContentType == TYPE_URL )
|
||||
{
|
||||
if ( !Q_strncmp( m_szMessage, "http://", 7 ) || !Q_strncmp( m_szMessage, "https://", 8 ) || !Q_stricmp( m_szMessage, "about:blank" ) )
|
||||
{
|
||||
ShowURL( m_szMessage );
|
||||
}
|
||||
else
|
||||
{
|
||||
// We should have trapped this at a higher level
|
||||
Assert( !"URL protocol is missing or blocked" );
|
||||
}
|
||||
}
|
||||
else if ( m_nContentType == TYPE_FILE )
|
||||
{
|
||||
ShowFile( m_szMessage );
|
||||
}
|
||||
else if ( m_nContentType == TYPE_TEXT )
|
||||
{
|
||||
ShowText( m_szMessage );
|
||||
}
|
||||
else
|
||||
{
|
||||
DevMsg("CTextWindow::Update: unknown content type %i\n", m_nContentType );
|
||||
}
|
||||
}
|
||||
|
||||
void CTextWindow::OnCommand( const char *command )
|
||||
{
|
||||
if (!Q_strcmp(command, "okay"))
|
||||
{
|
||||
//=============================================================================
|
||||
// HPE_BEGIN:
|
||||
// [Forrest] Replaced text window command string with TEXTWINDOW_CMD enumeration
|
||||
// of options. Passing a command string is dangerous and allowed a server network
|
||||
// message to run arbitrary commands on the client.
|
||||
//=============================================================================
|
||||
const char *pszCommand = NULL;
|
||||
switch ( m_nExitCommand )
|
||||
{
|
||||
case TEXTWINDOW_CMD_NONE:
|
||||
break;
|
||||
|
||||
case TEXTWINDOW_CMD_JOINGAME:
|
||||
pszCommand = "joingame";
|
||||
break;
|
||||
|
||||
case TEXTWINDOW_CMD_CHANGETEAM:
|
||||
pszCommand = "changeteam";
|
||||
break;
|
||||
|
||||
case TEXTWINDOW_CMD_IMPULSE101:
|
||||
pszCommand = "impulse 101";
|
||||
break;
|
||||
|
||||
case TEXTWINDOW_CMD_MAPINFO:
|
||||
pszCommand = "mapinfo";
|
||||
break;
|
||||
|
||||
case TEXTWINDOW_CMD_CLOSED_HTMLPAGE:
|
||||
pszCommand = "closed_htmlpage";
|
||||
break;
|
||||
|
||||
case TEXTWINDOW_CMD_CHOOSETEAM:
|
||||
pszCommand = "chooseteam";
|
||||
break;
|
||||
|
||||
default:
|
||||
DevMsg("CTextWindow::OnCommand: unknown exit command value %i\n", m_nExitCommand );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( pszCommand != NULL )
|
||||
{
|
||||
engine->ClientCmd_Unrestricted( pszCommand );
|
||||
}
|
||||
//=============================================================================
|
||||
// HPE_END
|
||||
//=============================================================================
|
||||
|
||||
m_pViewPort->ShowPanel( this, false );
|
||||
}
|
||||
|
||||
BaseClass::OnCommand(command);
|
||||
}
|
||||
|
||||
void CTextWindow::OnKeyCodePressed( vgui::KeyCode code )
|
||||
{
|
||||
if ( code == KEY_XBUTTON_A || code == KEY_XBUTTON_B )
|
||||
{
|
||||
OnCommand( "okay" );
|
||||
return;
|
||||
}
|
||||
|
||||
BaseClass::OnKeyCodePressed(code);
|
||||
}
|
||||
|
||||
void CTextWindow::SetData(KeyValues *data)
|
||||
{
|
||||
SetData( data->GetInt( "type" ), data->GetString( "title" ), data->GetString( "msg" ), data->GetString( "msg_fallback" ), data->GetInt( "cmd" ), data->GetBool( "unload" ) );
|
||||
}
|
||||
|
||||
void CTextWindow::SetData( int type, const char *title, const char *message, const char *message_fallback, int command, bool bUnload )
|
||||
{
|
||||
Q_strncpy( m_szTitle, title, sizeof( m_szTitle ) );
|
||||
Q_strncpy( m_szMessage, message, sizeof( m_szMessage ) );
|
||||
Q_strncpy( m_szMessageFallback, message_fallback, sizeof( m_szMessageFallback ) );
|
||||
|
||||
m_nExitCommand = command;
|
||||
|
||||
m_nContentType = type;
|
||||
m_bUnloadOnDismissal = bUnload;
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
void CTextWindow::ShowPanel( bool bShow )
|
||||
{
|
||||
if ( BaseClass::IsVisible() == bShow )
|
||||
return;
|
||||
|
||||
m_pViewPort->ShowBackGround( bShow );
|
||||
|
||||
if ( bShow )
|
||||
{
|
||||
Activate();
|
||||
SetMouseInputEnabled( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetVisible( false );
|
||||
SetMouseInputEnabled( false );
|
||||
|
||||
#if defined( ENABLE_CHROMEHTMLWINDOW )
|
||||
if ( m_bUnloadOnDismissal && m_bShownURL )
|
||||
{
|
||||
m_pHTMLMessage->OpenURL( "about:blank", NULL );
|
||||
m_bShownURL = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool CTextWindow::CMOTDHTML::OnStartRequest( const char *url, const char *target, const char *pchPostData, bool bIsRedirect )
|
||||
{
|
||||
if ( Q_strstr( url, "steam://" ) )
|
||||
return false;
|
||||
|
||||
return BaseClass::OnStartRequest( url, target, pchPostData, bIsRedirect );
|
||||
}
|
||||
104
sp/src/game/client/game_controls/vguitextwindow.h
Normal file
104
sp/src/game/client/game_controls/vguitextwindow.h
Normal file
@@ -0,0 +1,104 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef VGUITEXTWINDOW_H
|
||||
#define VGUITEXTWINDOW_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <vgui_controls/Frame.h>
|
||||
#include <vgui_controls/Button.h>
|
||||
#include <vgui_controls/HTML.h>
|
||||
|
||||
#include <game/client/iviewport.h>
|
||||
#include "shareddefs.h"
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
class TextEntry;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: displays the MOTD
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CTextWindow : public vgui::Frame, public IViewPortPanel
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CTextWindow, vgui::Frame );
|
||||
|
||||
public:
|
||||
CTextWindow(IViewPort *pViewPort);
|
||||
virtual ~CTextWindow();
|
||||
|
||||
virtual const char *GetName( void ) { return PANEL_INFO; }
|
||||
virtual void SetData(KeyValues *data);
|
||||
virtual void Reset();
|
||||
virtual void Update();
|
||||
virtual bool NeedsUpdate( void ) { return false; }
|
||||
virtual bool HasInputElements( void ) { return true; }
|
||||
virtual void ShowPanel( bool bShow );
|
||||
|
||||
// both vgui::Frame and IViewPortPanel define these, so explicitly define them here as passthroughs to vgui
|
||||
vgui::VPANEL GetVPanel( void ) { return BaseClass::GetVPanel(); }
|
||||
virtual bool IsVisible() { return BaseClass::IsVisible(); }
|
||||
virtual void SetParent( vgui::VPANEL parent ) { BaseClass::SetParent( parent ); }
|
||||
|
||||
public:
|
||||
|
||||
virtual void SetData( int type, const char *title, const char *message, const char *message_fallback, int command, bool bUnload );
|
||||
virtual void ShowFile( const char *filename );
|
||||
virtual void ShowText( const char *text );
|
||||
virtual void ShowURL( const char *URL, bool bAllowUserToDisable = true );
|
||||
virtual void ShowIndex( const char *entry );
|
||||
|
||||
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
|
||||
|
||||
protected:
|
||||
// vgui overrides
|
||||
virtual void OnCommand( const char *command );
|
||||
|
||||
void OnKeyCodePressed( vgui::KeyCode code );
|
||||
|
||||
IViewPort *m_pViewPort;
|
||||
char m_szTitle[255];
|
||||
char m_szMessage[2048];
|
||||
char m_szMessageFallback[2048];
|
||||
//=============================================================================
|
||||
// HPE_BEGIN:
|
||||
// [Forrest] Replaced text window command string with TEXTWINDOW_CMD enumeration
|
||||
// of options. Passing a command string is dangerous and allowed a server network
|
||||
// message to run arbitrary commands on the client.
|
||||
//=============================================================================
|
||||
int m_nExitCommand;
|
||||
//=============================================================================
|
||||
// HPE_END
|
||||
//=============================================================================
|
||||
int m_nContentType;
|
||||
bool m_bShownURL;
|
||||
bool m_bUnloadOnDismissal;
|
||||
|
||||
vgui::TextEntry *m_pTextMessage;
|
||||
|
||||
class CMOTDHTML : public vgui::HTML
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CMOTDHTML, vgui::HTML );
|
||||
|
||||
public:
|
||||
CMOTDHTML( Panel *parent, const char *pchName ) : vgui::HTML( parent, pchName ) {}
|
||||
virtual bool OnStartRequest( const char *url, const char *target, const char *pchPostData, bool bIsRedirect ) OVERRIDE;
|
||||
};
|
||||
CMOTDHTML *m_pHTMLMessage;
|
||||
|
||||
vgui::Button *m_pOK;
|
||||
vgui::Label *m_pTitleLabel;
|
||||
};
|
||||
|
||||
|
||||
#endif // VGUITEXTWINDOW_H
|
||||
29
sp/src/game/client/hl2/C_Func_Monitor.cpp
Normal file
29
sp/src/game/client/hl2/C_Func_Monitor.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
//========= Copyright 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"
|
||||
|
||||
class C_FuncMonitor : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_FuncMonitor, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
// C_BaseEntity.
|
||||
public:
|
||||
virtual bool ShouldDraw();
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_FuncMonitor, DT_FuncMonitor, CFuncMonitor )
|
||||
END_RECV_TABLE()
|
||||
|
||||
bool C_FuncMonitor::ShouldDraw()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
219
sp/src/game/client/hl2/c_antlion_dust.cpp
Normal file
219
sp/src/game/client/hl2/c_antlion_dust.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "fx.h"
|
||||
#include "particlemgr.h"
|
||||
#include "particle_prototype.h"
|
||||
#include "particle_util.h"
|
||||
#include "c_te_particlesystem.h"
|
||||
#include "particles_ez.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define DUST_STARTSIZE 16
|
||||
#define DUST_ENDSIZE 48
|
||||
#define DUST_RADIUS 32.0f
|
||||
#define DUST_STARTALPHA 0.3f
|
||||
#define DUST_ENDALPHA 0.0f
|
||||
#define DUST_LIFETIME 2.0f
|
||||
|
||||
static Vector g_AntlionDustColor( 0.3f, 0.25f, 0.2f );
|
||||
|
||||
extern IPhysicsSurfaceProps *physprops;
|
||||
|
||||
class CAntlionDustEmitter : public CSimpleEmitter
|
||||
{
|
||||
public:
|
||||
static CAntlionDustEmitter *Create( const char *debugname )
|
||||
{
|
||||
return new CAntlionDustEmitter( debugname );
|
||||
}
|
||||
|
||||
void UpdateVelocity( SimpleParticle *pParticle, float timeDelta )
|
||||
{
|
||||
//FIXME: Incorrect
|
||||
pParticle->m_vecVelocity *= 0.9f;
|
||||
}
|
||||
|
||||
private:
|
||||
CAntlionDustEmitter( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
|
||||
CAntlionDustEmitter( const CAntlionDustEmitter & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
//==================================================
|
||||
// C_TEAntlionDust
|
||||
//==================================================
|
||||
|
||||
class C_TEAntlionDust: public C_TEParticleSystem
|
||||
{
|
||||
public:
|
||||
|
||||
DECLARE_CLASS( C_TEAntlionDust, C_TEParticleSystem );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_TEAntlionDust();
|
||||
virtual ~C_TEAntlionDust();
|
||||
|
||||
//C_BaseEntity
|
||||
public:
|
||||
virtual void PostDataUpdate( DataUpdateType_t updateType );
|
||||
virtual bool ShouldDraw() { return true; }
|
||||
|
||||
|
||||
//IParticleEffect
|
||||
public:
|
||||
virtual void RenderParticles( CParticleRenderIterator *pIterator );
|
||||
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
|
||||
|
||||
public:
|
||||
PMaterialHandle m_MaterialHandle;
|
||||
|
||||
Vector m_vecOrigin;
|
||||
QAngle m_vecAngles;
|
||||
bool m_bBlockedSpawner;
|
||||
|
||||
protected:
|
||||
void GetDustColor( Vector &color );
|
||||
};
|
||||
|
||||
// Expose to the particle app.
|
||||
EXPOSE_PROTOTYPE_EFFECT( AntlionDust, C_TEAntlionDust );
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_EVENT_DT( C_TEAntlionDust, DT_TEAntlionDust, CTEAntlionDust )
|
||||
RecvPropVector(RECVINFO( m_vecOrigin )),
|
||||
RecvPropVector(RECVINFO( m_vecAngles )),
|
||||
RecvPropBool(RECVINFO( m_bBlockedSpawner )),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//==================================================
|
||||
// C_TEAntlionDust
|
||||
//==================================================
|
||||
|
||||
C_TEAntlionDust::C_TEAntlionDust()
|
||||
{
|
||||
m_MaterialHandle = INVALID_MATERIAL_HANDLE;
|
||||
m_vecOrigin.Init();
|
||||
m_vecAngles.Init();
|
||||
m_bBlockedSpawner = false;
|
||||
}
|
||||
|
||||
C_TEAntlionDust::~C_TEAntlionDust()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : bNewEntity - whether or not to start a new entity
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void C_TEAntlionDust::PostDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
// This style of creating dust emitters is now deprecated; we use the simple particle singleton exclusively.
|
||||
/*
|
||||
CSmartPtr<CAntlionDustEmitter> pDustEmitter = CAntlionDustEmitter::Create( "TEAntlionDust" );
|
||||
Assert( pDustEmitter );
|
||||
if ( pDustEmitter == NULL )
|
||||
return;
|
||||
|
||||
pDustEmitter->SetSortOrigin( m_vecOrigin );
|
||||
pDustEmitter->SetNearClip( 32, 64 );
|
||||
pDustEmitter->GetBinding().SetBBox( m_vecOrigin - Vector( 32, 32, 32 ), m_vecOrigin + Vector( 32, 32, 32 ) );
|
||||
*/
|
||||
|
||||
Vector offset;
|
||||
Vector vecColor;
|
||||
GetDustColor( vecColor );
|
||||
|
||||
int iParticleCount = 16;
|
||||
|
||||
if ( m_bBlockedSpawner == true )
|
||||
{
|
||||
iParticleCount = 8;
|
||||
}
|
||||
|
||||
//Spawn the dust
|
||||
SimpleParticle particle;
|
||||
for ( int i = 0; i < iParticleCount; i++ )
|
||||
{
|
||||
//Offset this dust puff's origin
|
||||
offset[0] = random->RandomFloat( -DUST_RADIUS, DUST_RADIUS );
|
||||
offset[1] = random->RandomFloat( -DUST_RADIUS, DUST_RADIUS );
|
||||
offset[2] = random->RandomFloat( -16, 8 );
|
||||
|
||||
offset += m_vecOrigin;
|
||||
|
||||
particle.m_Pos = offset;
|
||||
particle.m_flDieTime = random->RandomFloat( 0.75f, 1.25f );
|
||||
particle.m_flLifetime = 0.0f;
|
||||
|
||||
Vector dir = particle.m_Pos - m_vecOrigin;
|
||||
particle.m_vecVelocity = dir * random->RandomFloat( 0.5f, 1.0f );
|
||||
dir.z = fabs(dir.z);
|
||||
|
||||
float colorRamp = random->RandomFloat( 0.5f, 1.0f );
|
||||
Vector color = vecColor*colorRamp;
|
||||
|
||||
color[0] = clamp( color[0], 0.0f, 1.0f );
|
||||
color[1] = clamp( color[1], 0.0f, 1.0f );
|
||||
color[2] = clamp( color[2], 0.0f, 1.0f );
|
||||
|
||||
color *= 255;
|
||||
|
||||
particle.m_uchColor[0] = color[0];
|
||||
particle.m_uchColor[1] = color[1];
|
||||
particle.m_uchColor[2] = color[2];
|
||||
|
||||
particle.m_uchStartAlpha= random->RandomFloat( 64, 128 );
|
||||
particle.m_uchEndAlpha = 0;
|
||||
|
||||
particle.m_uchStartSize = random->RandomInt( 16, 32 );
|
||||
particle.m_uchEndSize = particle.m_uchStartSize * 3;
|
||||
particle.m_flRoll = random->RandomInt( 0, 360 );
|
||||
particle.m_flRollDelta = random->RandomFloat( -0.2f, 0.2f );
|
||||
|
||||
// Though it appears there are two particle handle entries in g_Mat_DustPuff, in fact
|
||||
// only the one present at index 0 actually draws. Trying to spawn a particle with
|
||||
// the other material will give you no particle at all. Therefore while instead of this:
|
||||
// AddSimpleParticle( &particle, g_Mat_DustPuff[random->RandomInt(0,1) );
|
||||
// we have to do this:
|
||||
AddSimpleParticle( &particle, g_Mat_DustPuff[0] );
|
||||
}
|
||||
}
|
||||
|
||||
void GetColorForSurface( trace_t *trace, Vector *color );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &color -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_TEAntlionDust::GetDustColor( Vector &color )
|
||||
{
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( m_vecOrigin+Vector(0,0,1), m_vecOrigin+Vector(0,0,-32),
|
||||
MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction < 1.0f )
|
||||
{
|
||||
GetColorForSurface( &tr, &color );
|
||||
}
|
||||
else
|
||||
{
|
||||
//Fill in a fallback
|
||||
color = g_AntlionDustColor;
|
||||
}
|
||||
}
|
||||
|
||||
void C_TEAntlionDust::RenderParticles( CParticleRenderIterator *pIterator )
|
||||
{
|
||||
}
|
||||
|
||||
void C_TEAntlionDust::SimulateParticles( CParticleSimulateIterator *pIterator )
|
||||
{
|
||||
}
|
||||
|
||||
475
sp/src/game/client/hl2/c_ar2_explosion.cpp
Normal file
475
sp/src/game/client/hl2/c_ar2_explosion.cpp
Normal file
@@ -0,0 +1,475 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "particlemgr.h"
|
||||
#include "particle_prototype.h"
|
||||
#include "particle_util.h"
|
||||
#include "surfinfo.h"
|
||||
#include "baseparticleentity.h"
|
||||
#include "materialsystem/imaterialsystemhardwareconfig.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
// Definitions
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
#define NUM_AR2_EXPLOSION_PARTICLES 70
|
||||
#define AR2_DUST_RADIUS 240 // 340
|
||||
#define AR2_DUST_LIFETIME 4
|
||||
#define AR2_DUST_LIFETIME_DELTA 6
|
||||
#define AR2_DUST_SPEED 10000
|
||||
#define AR2_DUST_STARTSIZE 8
|
||||
#define AR2_DUST_ENDSIZE 32
|
||||
#define AR2_DUST_ALPHA 0.5f
|
||||
#define AR2_DUST_FADE_IN_TIME 0.25f
|
||||
|
||||
static Vector g_AR2DustColor1(0.35, 0.345, 0.33 );
|
||||
static Vector g_AR2DustColor2(0.75, 0.75, 0.7);
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
// Classes
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
class C_AR2Explosion : public C_BaseParticleEntity, public IPrototypeAppEffect
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_AR2Explosion, C_BaseParticleEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_AR2Explosion();
|
||||
~C_AR2Explosion();
|
||||
|
||||
private:
|
||||
|
||||
class AR2ExplosionParticle : public StandardParticle_t
|
||||
{
|
||||
public:
|
||||
float m_Dist;
|
||||
Vector m_Start;
|
||||
float m_Roll;
|
||||
float m_RollSpeed;
|
||||
float m_Dwell;
|
||||
};
|
||||
|
||||
// C_BaseEntity.
|
||||
public:
|
||||
virtual void OnDataChanged(DataUpdateType_t updateType);
|
||||
|
||||
// IPrototypeAppEffect.
|
||||
public:
|
||||
virtual void Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs);
|
||||
|
||||
// IParticleEffect.
|
||||
public:
|
||||
virtual void Update(float fTimeDelta);
|
||||
|
||||
virtual void RenderParticles( CParticleRenderIterator *pIterator );
|
||||
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
|
||||
|
||||
|
||||
public:
|
||||
CParticleMgr *m_pParticleMgr;
|
||||
PMaterialHandle m_MaterialHandle;
|
||||
|
||||
private:
|
||||
|
||||
char m_szMaterialName[255];
|
||||
|
||||
C_AR2Explosion( const C_AR2Explosion & );
|
||||
};
|
||||
|
||||
// Expose to the particle app.
|
||||
EXPOSE_PROTOTYPE_EFFECT(AR2Explosion, C_AR2Explosion);
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_AR2Explosion, DT_AR2Explosion, AR2Explosion)
|
||||
RecvPropString( RECVINFO( m_szMaterialName ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
// Helpers.
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
// Given a line segment from vStart to vEnd
|
||||
// and a list of convex polygons in pSurfInfos and nSurfInfos,
|
||||
// fill in the list of which polygons the segment intersects.
|
||||
// Returns the number of intersected surfaces.
|
||||
static int IntersectSegmentWithSurfInfos(
|
||||
const Vector &vStart,
|
||||
const Vector &vEnd,
|
||||
SurfInfo *pSurfInfos,
|
||||
const int nSurfInfos,
|
||||
SurfInfo ** pIntersections,
|
||||
Vector *pIntersectionPositions,
|
||||
int nMaxIntersections)
|
||||
{
|
||||
if(nMaxIntersections == 0)
|
||||
return 0;
|
||||
|
||||
int nIntersections = 0;
|
||||
for(int i=0; i < nSurfInfos; i++)
|
||||
{
|
||||
SurfInfo *pSurf = &pSurfInfos[i];
|
||||
|
||||
// Does it intersect the plane?
|
||||
float dot1 = pSurf->m_Plane.DistTo(vStart);
|
||||
float dot2 = pSurf->m_Plane.DistTo(vEnd);
|
||||
if((dot1 > 0) != (dot2 > 0))
|
||||
{
|
||||
float t = dot1 / (dot1 - dot2);
|
||||
Vector vIntersection = vStart + (vEnd - vStart) * t;
|
||||
|
||||
// If the intersection is behind any edge plane, then it's not inside the polygon.
|
||||
unsigned long iEdge;
|
||||
for(iEdge=0; iEdge < pSurf->m_nVerts; iEdge++)
|
||||
{
|
||||
VPlane edgePlane;
|
||||
edgePlane.m_Normal = pSurf->m_Plane.m_Normal.Cross(pSurf->m_Verts[iEdge] - pSurf->m_Verts[(iEdge+1)%pSurf->m_nVerts]);
|
||||
VectorNormalize( edgePlane.m_Normal );
|
||||
edgePlane.m_Dist = edgePlane.m_Normal.Dot(pSurf->m_Verts[iEdge]);
|
||||
|
||||
if(edgePlane.DistTo(vIntersection) < 0.0f)
|
||||
break;
|
||||
}
|
||||
|
||||
if(iEdge == pSurf->m_nVerts)
|
||||
{
|
||||
pIntersections[nIntersections] = pSurf;
|
||||
pIntersectionPositions[nIntersections] = vIntersection;
|
||||
++nIntersections;
|
||||
if(nIntersections >= nMaxIntersections)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nIntersections;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
// C_AR2Explosion
|
||||
// ------------------------------------------------------------------------- //
|
||||
C_AR2Explosion::C_AR2Explosion()
|
||||
{
|
||||
m_pParticleMgr = NULL;
|
||||
m_MaterialHandle = INVALID_MATERIAL_HANDLE;
|
||||
}
|
||||
|
||||
|
||||
C_AR2Explosion::~C_AR2Explosion()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void C_AR2Explosion::OnDataChanged(DataUpdateType_t updateType)
|
||||
{
|
||||
C_BaseEntity::OnDataChanged(updateType);
|
||||
|
||||
if(updateType == DATA_UPDATE_CREATED)
|
||||
{
|
||||
Start(ParticleMgr(), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static ConVar mat_reduceparticles( "mat_reduceparticles", "0" );
|
||||
|
||||
void C_AR2Explosion::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
|
||||
{
|
||||
m_pParticleMgr = pParticleMgr;
|
||||
if(!pParticleMgr->AddEffect(&m_ParticleEffect, this))
|
||||
return;
|
||||
|
||||
if (!m_szMaterialName[0])
|
||||
{
|
||||
Q_strncpy(m_szMaterialName, "particle/particle_noisesphere", sizeof( m_szMaterialName ) );
|
||||
}
|
||||
|
||||
m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial(m_szMaterialName);
|
||||
|
||||
// Precalculate stuff for the particle spawning..
|
||||
#define NUM_DUSTEMITTER_SURFINFOS 128
|
||||
SurfInfo surfInfos[NUM_DUSTEMITTER_SURFINFOS];
|
||||
int nSurfInfos;
|
||||
|
||||
// Center of explosion.
|
||||
Vector vCenter = GetAbsOrigin(); // HACKHACK.. when the engine bug is fixed, use origin.
|
||||
|
||||
if ( IsXbox() )
|
||||
{
|
||||
m_ParticleEffect.SetBBox( vCenter-Vector(300,300,300), vCenter+Vector(300,300,300) );
|
||||
}
|
||||
|
||||
#ifdef PARTICLEPROTOTYPE_APP
|
||||
float surfSize = 10000;
|
||||
nSurfInfos = 1;
|
||||
surfInfos[0].m_Verts[0].Init(-surfSize,-surfSize,0);
|
||||
surfInfos[0].m_Verts[1].Init(-surfSize,surfSize,0);
|
||||
surfInfos[0].m_Verts[2].Init(surfSize, surfSize,0);
|
||||
surfInfos[0].m_Verts[3].Init(surfSize,-surfSize,0);
|
||||
surfInfos[0].m_nVerts = 4;
|
||||
surfInfos[0].m_Plane.m_Normal.Init(0,0,1);
|
||||
surfInfos[0].m_Plane.m_Dist = -3;
|
||||
#else
|
||||
{
|
||||
nSurfInfos = 0;
|
||||
C_BaseEntity *ent = cl_entitylist->GetEnt( 0 );
|
||||
if ( ent )
|
||||
{
|
||||
nSurfInfos = engine->GetIntersectingSurfaces(
|
||||
ent->GetModel(),
|
||||
vCenter,
|
||||
AR2_DUST_RADIUS,
|
||||
true,
|
||||
surfInfos,
|
||||
NUM_DUSTEMITTER_SURFINFOS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int nParticles = 0;
|
||||
|
||||
int iParticlesToSpawn = NUM_AR2_EXPLOSION_PARTICLES;
|
||||
|
||||
// In DX7, much fewer particles
|
||||
if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 )
|
||||
{
|
||||
iParticlesToSpawn *= 0.25;
|
||||
}
|
||||
else if ( mat_reduceparticles.GetBool() )
|
||||
{
|
||||
iParticlesToSpawn *= 0.025;
|
||||
}
|
||||
|
||||
if( nSurfInfos > 0 )
|
||||
{
|
||||
// For nParticles*N, generate a ray and cast it out. If it hits anything, spawn a particle there.
|
||||
int nTestsPerParticle=3;
|
||||
for(int i=0; i < iParticlesToSpawn; i++)
|
||||
{
|
||||
for(int iTest=0; iTest < nTestsPerParticle; iTest++)
|
||||
{
|
||||
Vector randVec = RandomVector(-1,1);
|
||||
VectorNormalize( randVec );
|
||||
Vector startPos = vCenter + randVec * AR2_DUST_RADIUS;
|
||||
|
||||
randVec = RandomVector(-1,1);
|
||||
VectorNormalize( randVec );
|
||||
Vector endPos = vCenter + randVec * AR2_DUST_RADIUS;
|
||||
|
||||
#define MAX_SURFINFO_INTERSECTIONS 4
|
||||
SurfInfo *pIntersected[MAX_SURFINFO_INTERSECTIONS];
|
||||
Vector vIntersections[MAX_SURFINFO_INTERSECTIONS];
|
||||
int nIntersections;
|
||||
nIntersections = IntersectSegmentWithSurfInfos(
|
||||
startPos,
|
||||
endPos,
|
||||
surfInfos,
|
||||
nSurfInfos,
|
||||
pIntersected,
|
||||
vIntersections,
|
||||
MAX_SURFINFO_INTERSECTIONS);
|
||||
|
||||
if(nIntersections)
|
||||
{
|
||||
int iIntersection = rand() % nIntersections;
|
||||
|
||||
Vector velocity;
|
||||
//velocity.Init(-1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f, -1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f, -1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f);
|
||||
//velocity = velocity * FRand(m_MinSpeed, m_MaxSpeed);
|
||||
Vector direction = (vIntersections[iIntersection] - vCenter );
|
||||
float dist = VectorNormalize( direction );
|
||||
if(dist > AR2_DUST_RADIUS)
|
||||
dist = AR2_DUST_RADIUS;
|
||||
|
||||
static float power = 2.0f;
|
||||
float falloffMul = pow(1.0f - dist / AR2_DUST_RADIUS, power);
|
||||
|
||||
Vector reflection = direction - 2 * DotProduct( direction, pIntersected[iIntersection]->m_Plane.m_Normal ) * pIntersected[iIntersection]->m_Plane.m_Normal;
|
||||
VectorNormalize( reflection );
|
||||
|
||||
velocity = reflection * AR2_DUST_SPEED * falloffMul;
|
||||
// velocity = velocity + (vIntersections[iIntersection] - vCenter) * falloffMul;
|
||||
|
||||
|
||||
/*
|
||||
debugoverlay->AddLineOverlay( vIntersections[iIntersection],
|
||||
vIntersections[iIntersection] + reflection * 64,
|
||||
128, 128, 255, false, 15.0 );
|
||||
*/
|
||||
#if 1
|
||||
AR2ExplosionParticle *pParticle =
|
||||
(AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );
|
||||
|
||||
if(pParticle)
|
||||
{
|
||||
pParticle->m_Pos = vIntersections[iIntersection];
|
||||
pParticle->m_Start = pParticle->m_Pos;
|
||||
pParticle->m_Dist = 8.0;
|
||||
pParticle->m_Velocity = velocity;
|
||||
// sound == 13031.496062992125984251968503937ips
|
||||
pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
|
||||
pParticle->m_Roll = FRand( 0, M_PI * 2 );
|
||||
pParticle->m_RollSpeed = FRand( -1, 1 ) * 0.4;
|
||||
pParticle->m_Dwell = AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA );
|
||||
nParticles++;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build interior smoke particles
|
||||
for(int i=nParticles; i < iParticlesToSpawn; i++)
|
||||
{
|
||||
Vector randVec = RandomVector(-1,1);
|
||||
VectorNormalize( randVec );
|
||||
Vector endPos = vCenter + randVec * AR2_DUST_RADIUS / 4.0;
|
||||
|
||||
Vector direction = (endPos - vCenter );
|
||||
float dist = VectorNormalize( direction ) + random->RandomFloat( 0, AR2_DUST_RADIUS / 4.0 );
|
||||
if(dist > AR2_DUST_RADIUS)
|
||||
dist = AR2_DUST_RADIUS;
|
||||
|
||||
static float power = 2.0f;
|
||||
float falloffMul = pow(1.0f - dist / (AR2_DUST_RADIUS / 2), power);
|
||||
|
||||
Vector velocity = direction * AR2_DUST_SPEED * falloffMul;
|
||||
AR2ExplosionParticle *pParticle =
|
||||
(AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );
|
||||
|
||||
if(pParticle)
|
||||
{
|
||||
pParticle->m_Pos = endPos;
|
||||
pParticle->m_Start = pParticle->m_Pos;
|
||||
pParticle->m_Dist = 8.0;
|
||||
pParticle->m_Velocity = velocity;
|
||||
// sound == 13031.496062992125984251968503937ips
|
||||
pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
|
||||
pParticle->m_Roll = FRand( 0, M_PI * 2 );
|
||||
pParticle->m_RollSpeed = FRand( -1, 1 ) * 4.0;
|
||||
pParticle->m_Dwell = 0.5 * (AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C_AR2Explosion::Update(float fTimeDelta)
|
||||
{
|
||||
if(!m_pParticleMgr)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void C_AR2Explosion::SimulateParticles( CParticleSimulateIterator *pIterator )
|
||||
{
|
||||
float dt = pIterator->GetTimeDelta();
|
||||
|
||||
AR2ExplosionParticle *pParticle = (AR2ExplosionParticle*)pIterator->GetFirst();
|
||||
while ( pParticle )
|
||||
{
|
||||
if (dt > 0.05)
|
||||
dt = 0.05; // yuck, air resistance function craps out at less then 20fps
|
||||
|
||||
// Update its lifetime.
|
||||
pParticle->m_Lifetime += dt; // pDraw->GetTimeDelta();
|
||||
if(pParticle->m_Lifetime > pParticle->m_Dwell)
|
||||
{
|
||||
// faded to nothing....
|
||||
pIterator->RemoveParticle( pParticle );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Spin the thing
|
||||
pParticle->m_Roll += pParticle->m_RollSpeed * pIterator->GetTimeDelta();
|
||||
|
||||
// delayed?
|
||||
if ( pParticle->m_Lifetime >= 0.0f )
|
||||
{
|
||||
// Move it (this comes after rendering to make it clear that moving the particle here won't change
|
||||
// its rendering for this frame since m_TransformedPos has already been set).
|
||||
pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * dt;
|
||||
|
||||
// keep track of distance traveled
|
||||
pParticle->m_Dist = pParticle->m_Dist + pParticle->m_Velocity.Length() * dt;
|
||||
|
||||
// Dampen velocity.
|
||||
float dist = pParticle->m_Velocity.Length() * dt;
|
||||
float r = dist * dist;
|
||||
// FIXME: this is a really screwy air-resistance function....
|
||||
pParticle->m_Velocity = pParticle->m_Velocity * (100 / (100 + r ));
|
||||
|
||||
// dampen roll
|
||||
static float dtime;
|
||||
static float decay;
|
||||
if (dtime != dt)
|
||||
{
|
||||
dtime = dt;
|
||||
decay = ExponentialDecay( 0.3, 1.0, dtime );
|
||||
}
|
||||
if (fabs(pParticle->m_RollSpeed) > 0.2)
|
||||
pParticle->m_RollSpeed = pParticle->m_RollSpeed * decay;
|
||||
}
|
||||
}
|
||||
|
||||
pParticle = (AR2ExplosionParticle*)pIterator->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C_AR2Explosion::RenderParticles( CParticleRenderIterator *pIterator )
|
||||
{
|
||||
const AR2ExplosionParticle *pParticle = (const AR2ExplosionParticle *)pIterator->GetFirst();
|
||||
while ( pParticle )
|
||||
{
|
||||
float sortKey = 0;
|
||||
if ( pParticle->m_Lifetime >= 0.0f )
|
||||
{
|
||||
// Draw.
|
||||
float lifetimePercent = ( pParticle->m_Lifetime - AR2_DUST_FADE_IN_TIME ) / pParticle->m_Dwell;
|
||||
|
||||
// FIXME: base color should be a dirty version of the material color
|
||||
Vector color = g_AR2DustColor1 * (1.0 - lifetimePercent) + g_AR2DustColor2 * lifetimePercent;
|
||||
|
||||
Vector tPos;
|
||||
TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos);
|
||||
sortKey = tPos.z;
|
||||
|
||||
float alpha;
|
||||
|
||||
if ( pParticle->m_Lifetime < AR2_DUST_FADE_IN_TIME )
|
||||
{
|
||||
alpha = AR2_DUST_ALPHA * ( pParticle->m_Lifetime / AR2_DUST_FADE_IN_TIME );
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = AR2_DUST_ALPHA * ( 1.0f - lifetimePercent );
|
||||
}
|
||||
|
||||
alpha *= GetAlphaDistanceFade( tPos, IsXbox() ? 100 : 50, IsXbox() ? 200 : 150 );
|
||||
|
||||
RenderParticle_ColorSizeAngle(
|
||||
pIterator->GetParticleDraw(),
|
||||
tPos,
|
||||
color,
|
||||
alpha,
|
||||
pParticle->m_Dist, // size based on how far it's traveled
|
||||
pParticle->m_Roll);
|
||||
}
|
||||
|
||||
pParticle = (const AR2ExplosionParticle *)pIterator->GetNext( sortKey );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
313
sp/src/game/client/hl2/c_barnacle.cpp
Normal file
313
sp/src/game/client/hl2/c_barnacle.cpp
Normal file
@@ -0,0 +1,313 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_ai_basenpc.h"
|
||||
#include "engine/ivmodelinfo.h"
|
||||
#include "rope_physics.h"
|
||||
#include "materialsystem/imaterialsystem.h"
|
||||
#include "fx_line.h"
|
||||
#include "engine/ivdebugoverlay.h"
|
||||
#include "bone_setup.h"
|
||||
#include "model_types.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define BARNACLE_TONGUE_POINTS 7
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_NPC_Barnacle : public C_AI_BaseNPC
|
||||
{
|
||||
public:
|
||||
|
||||
DECLARE_CLASS( C_NPC_Barnacle, C_AI_BaseNPC );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_NPC_Barnacle( void );
|
||||
|
||||
virtual void GetRenderBounds( Vector &theMins, Vector &theMaxs )
|
||||
{
|
||||
BaseClass::GetRenderBounds( theMins, theMaxs );
|
||||
|
||||
// Extend our bounding box downwards the length of the tongue
|
||||
theMins -= Vector( 0, 0, m_flAltitude );
|
||||
}
|
||||
|
||||
// Purpose: Initialize absmin & absmax to the appropriate box
|
||||
virtual void ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
|
||||
{
|
||||
// Extend our bounding box downwards the length of the tongue
|
||||
CollisionProp()->WorldSpaceAABB( pVecWorldMins, pVecWorldMaxs );
|
||||
|
||||
// We really care about the tongue tip. The altitude is not really relevant.
|
||||
VectorMin( *pVecWorldMins, m_vecTip, *pVecWorldMins );
|
||||
VectorMax( *pVecWorldMaxs, m_vecTip, *pVecWorldMaxs );
|
||||
|
||||
// pVecWorldMins->z -= m_flAltitude;
|
||||
}
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
void InitTonguePhysics( void );
|
||||
void ClientThink( void );
|
||||
void StandardBlendingRules( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], float currentTime, int boneMask );
|
||||
|
||||
void SetVecTip( const float *pPosition );
|
||||
void SetAltitude( float flAltitude );
|
||||
|
||||
// Purpose:
|
||||
void ComputeVisualTipPoint( Vector *pTip );
|
||||
|
||||
protected:
|
||||
Vector m_vecTipPrevious;
|
||||
Vector m_vecRoot;
|
||||
Vector m_vecTip;
|
||||
Vector m_vecTipDrawOffset;
|
||||
|
||||
private:
|
||||
// Tongue points
|
||||
float m_flAltitude;
|
||||
Vector m_vecTonguePoints[BARNACLE_TONGUE_POINTS];
|
||||
CRopePhysics<BARNACLE_TONGUE_POINTS> m_TonguePhysics;
|
||||
|
||||
// Tongue physics delegate
|
||||
class CBarnaclePhysicsDelegate : public CSimplePhysics::IHelper
|
||||
{
|
||||
public:
|
||||
virtual void GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel );
|
||||
virtual void ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes );
|
||||
|
||||
C_NPC_Barnacle *m_pBarnacle;
|
||||
};
|
||||
friend class CBarnaclePhysicsDelegate;
|
||||
CBarnaclePhysicsDelegate m_PhysicsDelegate;
|
||||
|
||||
private:
|
||||
C_NPC_Barnacle( const C_NPC_Barnacle & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
static void RecvProxy_VecTip( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
((C_NPC_Barnacle*)pStruct)->SetVecTip( pData->m_Value.m_Vector );
|
||||
}
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_NPC_Barnacle, DT_Barnacle, CNPC_Barnacle )
|
||||
RecvPropFloat( RECVINFO( m_flAltitude ) ),
|
||||
RecvPropVector( RECVINFO( m_vecRoot ) ),
|
||||
RecvPropVector( RECVINFO( m_vecTip ), 0, RecvProxy_VecTip ),
|
||||
RecvPropVector( RECVINFO( m_vecTipDrawOffset ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_NPC_Barnacle::C_NPC_Barnacle( void )
|
||||
{
|
||||
m_PhysicsDelegate.m_pBarnacle = this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Barnacle::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
InitTonguePhysics();
|
||||
|
||||
// We want to think every frame.
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the tongue altitude
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Barnacle::SetAltitude( float flAltitude )
|
||||
{
|
||||
m_flAltitude = flAltitude;
|
||||
}
|
||||
|
||||
void C_NPC_Barnacle::SetVecTip( const float *pPosition )
|
||||
{
|
||||
Vector vecNewTip;
|
||||
vecNewTip.Init( pPosition[0], pPosition[1], pPosition[2] );
|
||||
if ( vecNewTip != m_vecTip )
|
||||
{
|
||||
m_vecTip = vecNewTip;
|
||||
CollisionProp()->MarkSurroundingBoundsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Barnacle::InitTonguePhysics( void )
|
||||
{
|
||||
// Init tongue spline
|
||||
// First point is at the top
|
||||
m_TonguePhysics.SetupSimulation( m_flAltitude / (BARNACLE_TONGUE_POINTS-1), &m_PhysicsDelegate );
|
||||
m_TonguePhysics.Restart();
|
||||
|
||||
// Initialize the positions of the nodes.
|
||||
m_TonguePhysics.GetFirstNode()->m_vPos = m_vecRoot;
|
||||
m_TonguePhysics.GetFirstNode()->m_vPrevPos = m_TonguePhysics.GetFirstNode()->m_vPos;
|
||||
float flAltitude = m_flAltitude;
|
||||
for( int i = 1; i < m_TonguePhysics.NumNodes(); i++ )
|
||||
{
|
||||
flAltitude *= 0.5;
|
||||
CSimplePhysics::CNode *pNode = m_TonguePhysics.GetNode( i );
|
||||
pNode->m_vPos = m_TonguePhysics.GetNode(i-1)->m_vPos - Vector(0,0,flAltitude);
|
||||
pNode->m_vPrevPos = pNode->m_vPos;
|
||||
|
||||
// Set the length of the node's spring
|
||||
//m_TonguePhysics.ResetNodeSpringLength( i-1, flAltitude );
|
||||
}
|
||||
|
||||
m_vecTipPrevious = m_vecTip;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Barnacle::ClientThink( void )
|
||||
{
|
||||
m_TonguePhysics.Simulate( gpGlobals->frametime );
|
||||
|
||||
// Set the spring's length to that of the tongue's extension
|
||||
m_TonguePhysics.ResetSpringLength( m_flAltitude / (BARNACLE_TONGUE_POINTS-1) );
|
||||
|
||||
// Necessary because ComputeVisualTipPoint depends on m_vecTipPrevious
|
||||
Vector vecTemp;
|
||||
ComputeVisualTipPoint( &vecTemp );
|
||||
m_vecTipPrevious = vecTemp;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Barnacle::StandardBlendingRules( CStudioHdr *hdr, Vector pos[], Quaternion q[], float currentTime, int boneMask )
|
||||
{
|
||||
BaseClass::StandardBlendingRules( hdr, pos, q, currentTime, boneMask );
|
||||
|
||||
if ( !hdr )
|
||||
return;
|
||||
|
||||
int firstBone = Studio_BoneIndexByName( hdr, "Barnacle.tongue1" );
|
||||
|
||||
Vector vecPrevRight;
|
||||
GetVectors( NULL, &vecPrevRight, NULL );
|
||||
|
||||
Vector vecPrev = pos[Studio_BoneIndexByName( hdr, "Barnacle.base" )];
|
||||
Vector vecCurr = vec3_origin;
|
||||
Vector vecForward;
|
||||
for ( int i = 0; i <= BARNACLE_TONGUE_POINTS; i++ )
|
||||
{
|
||||
// We double up the bones at the last node.
|
||||
if ( i == BARNACLE_TONGUE_POINTS )
|
||||
{
|
||||
vecCurr = m_TonguePhysics.GetLastNode()->m_vPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
vecCurr = m_TonguePhysics.GetNode(i)->m_vPos;
|
||||
}
|
||||
|
||||
//debugoverlay->AddBoxOverlay( vecCurr, -Vector(2,2,2), Vector(2,2,2), vec3_angle, 0,255,0, 128, 0.1 );
|
||||
|
||||
// Fill out the positions in local space
|
||||
VectorITransform( vecCurr, EntityToWorldTransform(), pos[firstBone+i] );
|
||||
vecCurr = pos[firstBone+i];
|
||||
|
||||
// Disallow twist in the tongue visually
|
||||
// Forward vector has to follow the tongue, right + up have to minimize twist from
|
||||
// the previous bone
|
||||
|
||||
// Fill out the angles
|
||||
if ( i != BARNACLE_TONGUE_POINTS )
|
||||
{
|
||||
vecForward = (vecCurr - vecPrev);
|
||||
if ( VectorNormalize( vecForward ) < 1e-3 )
|
||||
{
|
||||
vecForward.Init( 0, 0, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
// Project the previous vecRight into a plane perpendicular to vecForward
|
||||
// that's the vector closest to what we want...
|
||||
Vector vecRight, vecUp;
|
||||
VectorMA( vecPrevRight, -DotProduct( vecPrevRight, vecForward ), vecForward, vecRight );
|
||||
VectorNormalize( vecRight );
|
||||
CrossProduct( vecForward, vecRight, vecUp );
|
||||
|
||||
BasisToQuaternion( vecForward, vecRight, vecUp, q[firstBone+i] );
|
||||
|
||||
vecPrev = vecCurr;
|
||||
vecPrevRight = vecRight;
|
||||
}
|
||||
}
|
||||
|
||||
//===============================================================================================================================
|
||||
// BARNACLE TONGUE PHYSICS
|
||||
//===============================================================================================================================
|
||||
#define TONGUE_GRAVITY 0, 0, -1000
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Barnacle::CBarnaclePhysicsDelegate::GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel )
|
||||
{
|
||||
// Gravity.
|
||||
pAccel->Init( TONGUE_GRAVITY );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
#define TIP_SNAP_FACTOR 200
|
||||
// Todo: this really ought to be SIMD.
|
||||
void C_NPC_Barnacle::ComputeVisualTipPoint( Vector *pTip )
|
||||
{
|
||||
float flTipMove = TIP_SNAP_FACTOR * gpGlobals->frametime;
|
||||
Vector tipIdeal;
|
||||
VectorAdd(m_vecTip, m_vecTipDrawOffset, tipIdeal);
|
||||
if ( tipIdeal.DistToSqr( m_vecTipPrevious ) > (flTipMove * flTipMove) )
|
||||
{
|
||||
// Inch the visual tip toward the actual tip
|
||||
VectorSubtract( tipIdeal, m_vecTipPrevious, *pTip );
|
||||
VectorNormalize( *pTip );
|
||||
*pTip *= flTipMove;
|
||||
*pTip += m_vecTipPrevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pTip = tipIdeal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Barnacle::CBarnaclePhysicsDelegate::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes )
|
||||
{
|
||||
// Startpoint always stays at the root
|
||||
pNodes[0].m_vPos = m_pBarnacle->m_vecRoot;
|
||||
|
||||
// Endpoint always stays at the tip
|
||||
m_pBarnacle->ComputeVisualTipPoint( &pNodes[nNodes-1].m_vPos );
|
||||
}
|
||||
41
sp/src/game/client/hl2/c_barney.cpp
Normal file
41
sp/src/game/client/hl2/c_barney.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "c_ai_basenpc.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_Barney : public C_AI_BaseNPC
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_Barney, C_AI_BaseNPC );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_Barney();
|
||||
virtual ~C_Barney();
|
||||
|
||||
private:
|
||||
C_Barney( const C_Barney & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_Barney, DT_NPC_Barney, CNPC_Barney)
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_Barney::C_Barney()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
C_Barney::~C_Barney()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
91
sp/src/game/client/hl2/c_basehelicopter.cpp
Normal file
91
sp/src/game/client/hl2/c_basehelicopter.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_basehelicopter.h"
|
||||
#include "proxyentity.h"
|
||||
#include "materialsystem/imaterial.h"
|
||||
#include "materialsystem/imaterialvar.h"
|
||||
#include "KeyValues.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_BaseHelicopter, DT_BaseHelicopter, CBaseHelicopter )
|
||||
RecvPropTime( RECVINFO( m_flStartupTime ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
C_BaseHelicopter::C_BaseHelicopter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Chopper blade fade-in time
|
||||
//-----------------------------------------------------------------------------
|
||||
#define FADE_IN_TIME 2.0f
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the fade of the blades when the chopper starts up
|
||||
//-----------------------------------------------------------------------------
|
||||
class CHeliBladeMaterialProxy : public CEntityMaterialProxy
|
||||
{
|
||||
public:
|
||||
CHeliBladeMaterialProxy() { m_AlphaVar = NULL; }
|
||||
virtual ~CHeliBladeMaterialProxy() {}
|
||||
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
|
||||
virtual void OnBind( C_BaseEntity *pEntity );
|
||||
virtual IMaterial *GetMaterial();
|
||||
|
||||
private:
|
||||
IMaterialVar *m_AlphaVar;
|
||||
bool m_bFadeOut;
|
||||
};
|
||||
|
||||
bool CHeliBladeMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
|
||||
{
|
||||
bool foundVar;
|
||||
m_AlphaVar = pMaterial->FindVar( "$alpha", &foundVar, false );
|
||||
m_bFadeOut = pKeyValues->GetInt( "$fadeout", 0 ) != 0;
|
||||
return foundVar;
|
||||
}
|
||||
|
||||
void CHeliBladeMaterialProxy::OnBind( C_BaseEntity *pEnt )
|
||||
{
|
||||
if (!m_AlphaVar)
|
||||
return;
|
||||
|
||||
C_BaseHelicopter *pHeli = dynamic_cast<C_BaseHelicopter*>( pEnt );
|
||||
if ( pHeli )
|
||||
{
|
||||
float dt = gpGlobals->curtime - pHeli->StartupTime();
|
||||
dt /= FADE_IN_TIME;
|
||||
dt = clamp( dt, 0.0f, 1.0f );
|
||||
if ( m_bFadeOut )
|
||||
{
|
||||
dt = 1.0f - dt;
|
||||
}
|
||||
|
||||
m_AlphaVar->SetFloatValue( dt );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_AlphaVar->SetFloatValue( 1.0f );
|
||||
}
|
||||
}
|
||||
|
||||
IMaterial *CHeliBladeMaterialProxy::GetMaterial()
|
||||
{
|
||||
if ( !m_AlphaVar )
|
||||
return NULL;
|
||||
|
||||
return m_AlphaVar->GetOwningMaterial();
|
||||
}
|
||||
|
||||
EXPOSE_INTERFACE( CHeliBladeMaterialProxy, IMaterialProxy, "HeliBlade" IMATERIAL_PROXY_INTERFACE_VERSION );
|
||||
|
||||
33
sp/src/game/client/hl2/c_basehelicopter.h
Normal file
33
sp/src/game/client/hl2/c_basehelicopter.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef C_BASEHELICOPTER_H
|
||||
#define C_BASEHELICOPTER_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "c_ai_basenpc.h"
|
||||
|
||||
|
||||
class C_BaseHelicopter : public C_AI_BaseNPC
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_BaseHelicopter, C_AI_BaseNPC );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_BaseHelicopter();
|
||||
|
||||
float StartupTime() const { return m_flStartupTime; }
|
||||
|
||||
private:
|
||||
C_BaseHelicopter( const C_BaseHelicopter &other ) {}
|
||||
float m_flStartupTime;
|
||||
};
|
||||
|
||||
|
||||
#endif // C_BASEHELICOPTER_H
|
||||
21
sp/src/game/client/hl2/c_basehlcombatweapon.cpp
Normal file
21
sp/src/game/client/hl2/c_basehlcombatweapon.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_basehlcombatweapon.h"
|
||||
#include "igamemovement.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_HLMachineGun, DT_HLMachineGun, CHLMachineGun )
|
||||
END_RECV_TABLE()
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_HLSelectFireMachineGun, DT_HLSelectFireMachineGun, CHLSelectFireMachineGun )
|
||||
END_RECV_TABLE()
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_BaseHLBludgeonWeapon, DT_BaseHLBludgeonWeapon, CBaseHLBludgeonWeapon )
|
||||
END_RECV_TABLE()
|
||||
36
sp/src/game/client/hl2/c_basehlcombatweapon.h
Normal file
36
sp/src/game/client/hl2/c_basehlcombatweapon.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "basehlcombatweapon_shared.h"
|
||||
|
||||
#ifndef C_BASEHLCOMBATWEAPON_H
|
||||
#define C_BASEHLCOMBATWEAPON_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
class C_HLMachineGun : public C_BaseHLCombatWeapon
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_HLMachineGun, C_BaseHLCombatWeapon );
|
||||
DECLARE_CLIENTCLASS();
|
||||
};
|
||||
|
||||
class C_HLSelectFireMachineGun : public C_HLMachineGun
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_HLSelectFireMachineGun, C_HLMachineGun );
|
||||
DECLARE_CLIENTCLASS();
|
||||
};
|
||||
|
||||
class C_BaseHLBludgeonWeapon : public C_BaseHLCombatWeapon
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_BaseHLBludgeonWeapon, C_BaseHLCombatWeapon );
|
||||
DECLARE_CLIENTCLASS();
|
||||
};
|
||||
|
||||
#endif // C_BASEHLCOMBATWEAPON_H
|
||||
659
sp/src/game/client/hl2/c_basehlplayer.cpp
Normal file
659
sp/src/game/client/hl2/c_basehlplayer.cpp
Normal file
@@ -0,0 +1,659 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "c_basehlplayer.h"
|
||||
#include "playerandobjectenumerator.h"
|
||||
#include "engine/ivdebugoverlay.h"
|
||||
#include "c_ai_basenpc.h"
|
||||
#include "in_buttons.h"
|
||||
#include "collisionutils.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// How fast to avoid collisions with center of other object, in units per second
|
||||
#define AVOID_SPEED 2000.0f
|
||||
extern ConVar cl_forwardspeed;
|
||||
extern ConVar cl_backspeed;
|
||||
extern ConVar cl_sidespeed;
|
||||
|
||||
extern ConVar zoom_sensitivity_ratio;
|
||||
extern ConVar default_fov;
|
||||
extern ConVar sensitivity;
|
||||
|
||||
ConVar cl_npc_speedmod_intime( "cl_npc_speedmod_intime", "0.25", FCVAR_CLIENTDLL | FCVAR_ARCHIVE );
|
||||
ConVar cl_npc_speedmod_outtime( "cl_npc_speedmod_outtime", "1.5", FCVAR_CLIENTDLL | FCVAR_ARCHIVE );
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_BaseHLPlayer, DT_HL2_Player, CHL2_Player)
|
||||
RecvPropDataTable( RECVINFO_DT(m_HL2Local),0, &REFERENCE_RECV_TABLE(DT_HL2Local) ),
|
||||
RecvPropBool( RECVINFO( m_fIsSprinting ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( C_BaseHLPlayer )
|
||||
DEFINE_PRED_TYPEDESCRIPTION( m_HL2Local, C_HL2PlayerLocalData ),
|
||||
DEFINE_PRED_FIELD( m_fIsSprinting, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
// link to the correct class.
|
||||
#if !defined ( HL2MP ) && !defined ( PORTAL )
|
||||
LINK_ENTITY_TO_CLASS( player, C_BaseHLPlayer );
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Drops player's primary weapon
|
||||
//-----------------------------------------------------------------------------
|
||||
void CC_DropPrimary( void )
|
||||
{
|
||||
C_BasePlayer *pPlayer = (C_BasePlayer *) C_BasePlayer::GetLocalPlayer();
|
||||
|
||||
if ( pPlayer == NULL )
|
||||
return;
|
||||
|
||||
pPlayer->Weapon_DropPrimary();
|
||||
}
|
||||
|
||||
static ConCommand dropprimary("dropprimary", CC_DropPrimary, "dropprimary: Drops the primary weapon of the player.");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_BaseHLPlayer::C_BaseHLPlayer()
|
||||
{
|
||||
AddVar( &m_Local.m_vecPunchAngle, &m_Local.m_iv_vecPunchAngle, LATCH_SIMULATION_VAR );
|
||||
AddVar( &m_Local.m_vecPunchAngleVel, &m_Local.m_iv_vecPunchAngleVel, LATCH_SIMULATION_VAR );
|
||||
|
||||
m_flZoomStart = 0.0f;
|
||||
m_flZoomEnd = 0.0f;
|
||||
m_flZoomRate = 0.0f;
|
||||
m_flZoomStartTime = 0.0f;
|
||||
m_flSpeedMod = cl_forwardspeed.GetFloat();
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVarRef scissor("r_flashlightscissor");
|
||||
scissor.SetValue("0");
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BaseHLPlayer::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
// Make sure we're thinking
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BaseHLPlayer::Weapon_DropPrimary( void )
|
||||
{
|
||||
engine->ServerCmd( "DropPrimary" );
|
||||
}
|
||||
|
||||
float C_BaseHLPlayer::GetFOV()
|
||||
{
|
||||
//Find our FOV with offset zoom value
|
||||
float flFOVOffset = BaseClass::GetFOV() + GetZoom();
|
||||
|
||||
// Clamp FOV in MP
|
||||
int min_fov = ( gpGlobals->maxClients == 1 ) ? 5 : default_fov.GetInt();
|
||||
|
||||
// Don't let it go too low
|
||||
flFOVOffset = MAX( min_fov, flFOVOffset );
|
||||
|
||||
return flFOVOffset;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
float C_BaseHLPlayer::GetZoom( void )
|
||||
{
|
||||
float fFOV = m_flZoomEnd;
|
||||
|
||||
//See if we need to lerp the values
|
||||
if ( ( m_flZoomStart != m_flZoomEnd ) && ( m_flZoomRate > 0.0f ) )
|
||||
{
|
||||
float deltaTime = (float)( gpGlobals->curtime - m_flZoomStartTime ) / m_flZoomRate;
|
||||
|
||||
if ( deltaTime >= 1.0f )
|
||||
{
|
||||
//If we're past the zoom time, just take the new value and stop lerping
|
||||
fFOV = m_flZoomStart = m_flZoomEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
fFOV = SimpleSplineRemapVal( deltaTime, 0.0f, 1.0f, m_flZoomStart, m_flZoomEnd );
|
||||
}
|
||||
}
|
||||
|
||||
return fFOV;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : FOVOffset -
|
||||
// time -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BaseHLPlayer::Zoom( float FOVOffset, float time )
|
||||
{
|
||||
m_flZoomStart = GetZoom();
|
||||
m_flZoomEnd = FOVOffset;
|
||||
m_flZoomRate = time;
|
||||
m_flZoomStartTime = gpGlobals->curtime;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Hack to zero out player's pitch, use value from poseparameter instead
|
||||
// Input : flags -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_BaseHLPlayer::DrawModel( int flags )
|
||||
{
|
||||
// Not pitch for player
|
||||
QAngle saveAngles = GetLocalAngles();
|
||||
|
||||
QAngle useAngles = saveAngles;
|
||||
useAngles[ PITCH ] = 0.0f;
|
||||
|
||||
SetLocalAngles( useAngles );
|
||||
|
||||
int iret = BaseClass::DrawModel( flags );
|
||||
|
||||
SetLocalAngles( saveAngles );
|
||||
|
||||
return iret;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Helper to remove from ladder
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BaseHLPlayer::ExitLadder()
|
||||
{
|
||||
if ( MOVETYPE_LADDER != GetMoveType() )
|
||||
return;
|
||||
|
||||
SetMoveType( MOVETYPE_WALK );
|
||||
SetMoveCollide( MOVECOLLIDE_DEFAULT );
|
||||
// Remove from ladder
|
||||
m_HL2Local.m_hLadder = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Determines if a player can be safely moved towards a point
|
||||
// Input: pos - position to test move to, fVertDist - how far to trace downwards to see if the player would fall,
|
||||
// radius - how close the player can be to the object, objPos - position of the object to avoid,
|
||||
// objDir - direction the object is travelling
|
||||
//-----------------------------------------------------------------------------
|
||||
bool C_BaseHLPlayer::TestMove( const Vector &pos, float fVertDist, float radius, const Vector &objPos, const Vector &objDir )
|
||||
{
|
||||
trace_t trUp;
|
||||
trace_t trOver;
|
||||
trace_t trDown;
|
||||
float flHit1, flHit2;
|
||||
|
||||
UTIL_TraceHull( GetAbsOrigin(), pos, GetPlayerMins(), GetPlayerMaxs(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trOver );
|
||||
if ( trOver.fraction < 1.0f )
|
||||
{
|
||||
// check if the endpos intersects with the direction the object is travelling. if it doesn't, this is a good direction to move.
|
||||
if ( objDir.IsZero() ||
|
||||
( IntersectInfiniteRayWithSphere( objPos, objDir, trOver.endpos, radius, &flHit1, &flHit2 ) &&
|
||||
( ( flHit1 >= 0.0f ) || ( flHit2 >= 0.0f ) ) )
|
||||
)
|
||||
{
|
||||
// our first trace failed, so see if we can go farther if we step up.
|
||||
|
||||
// trace up to see if we have enough room.
|
||||
UTIL_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, m_Local.m_flStepSize ),
|
||||
GetPlayerMins(), GetPlayerMaxs(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trUp );
|
||||
|
||||
// do a trace from the stepped up height
|
||||
UTIL_TraceHull( trUp.endpos, pos + Vector( 0, 0, trUp.endpos.z - trUp.startpos.z ),
|
||||
GetPlayerMins(), GetPlayerMaxs(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trOver );
|
||||
|
||||
if ( trOver.fraction < 1.0f )
|
||||
{
|
||||
// check if the endpos intersects with the direction the object is travelling. if it doesn't, this is a good direction to move.
|
||||
if ( objDir.IsZero() ||
|
||||
( IntersectInfiniteRayWithSphere( objPos, objDir, trOver.endpos, radius, &flHit1, &flHit2 ) && ( ( flHit1 >= 0.0f ) || ( flHit2 >= 0.0f ) ) ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// trace down to see if this position is on the ground
|
||||
UTIL_TraceLine( trOver.endpos, trOver.endpos - Vector( 0, 0, fVertDist ),
|
||||
MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &trDown );
|
||||
|
||||
if ( trDown.fraction == 1.0f )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Client-side obstacle avoidance
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BaseHLPlayer::PerformClientSideObstacleAvoidance( float flFrameTime, CUserCmd *pCmd )
|
||||
{
|
||||
// Don't avoid if noclipping or in movetype none
|
||||
switch ( GetMoveType() )
|
||||
{
|
||||
case MOVETYPE_NOCLIP:
|
||||
case MOVETYPE_NONE:
|
||||
case MOVETYPE_OBSERVER:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Try to steer away from any objects/players we might interpenetrate
|
||||
Vector size = WorldAlignSize();
|
||||
|
||||
float radius = 0.7f * sqrt( size.x * size.x + size.y * size.y );
|
||||
float curspeed = GetLocalVelocity().Length2D();
|
||||
|
||||
//int slot = 1;
|
||||
//engine->Con_NPrintf( slot++, "speed %f\n", curspeed );
|
||||
//engine->Con_NPrintf( slot++, "radius %f\n", radius );
|
||||
|
||||
// If running, use a larger radius
|
||||
float factor = 1.0f;
|
||||
|
||||
if ( curspeed > 150.0f )
|
||||
{
|
||||
curspeed = MIN( 2048.0f, curspeed );
|
||||
factor = ( 1.0f + ( curspeed - 150.0f ) / 150.0f );
|
||||
|
||||
//engine->Con_NPrintf( slot++, "scaleup (%f) to radius %f\n", factor, radius * factor );
|
||||
|
||||
radius = radius * factor;
|
||||
}
|
||||
|
||||
Vector currentdir;
|
||||
Vector rightdir;
|
||||
|
||||
QAngle vAngles = pCmd->viewangles;
|
||||
vAngles.x = 0;
|
||||
|
||||
AngleVectors( vAngles, ¤tdir, &rightdir, NULL );
|
||||
|
||||
bool istryingtomove = false;
|
||||
bool ismovingforward = false;
|
||||
if ( fabs( pCmd->forwardmove ) > 0.0f ||
|
||||
fabs( pCmd->sidemove ) > 0.0f )
|
||||
{
|
||||
istryingtomove = true;
|
||||
if ( pCmd->forwardmove > 1.0f )
|
||||
{
|
||||
ismovingforward = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( istryingtomove == true )
|
||||
radius *= 1.3f;
|
||||
|
||||
CPlayerAndObjectEnumerator avoid( radius );
|
||||
partition->EnumerateElementsInSphere( PARTITION_CLIENT_SOLID_EDICTS, GetAbsOrigin(), radius, false, &avoid );
|
||||
|
||||
// Okay, decide how to avoid if there's anything close by
|
||||
int c = avoid.GetObjectCount();
|
||||
if ( c <= 0 )
|
||||
return;
|
||||
|
||||
//engine->Con_NPrintf( slot++, "moving %s forward %s\n", istryingtomove ? "true" : "false", ismovingforward ? "true" : "false" );
|
||||
|
||||
float adjustforwardmove = 0.0f;
|
||||
float adjustsidemove = 0.0f;
|
||||
|
||||
for ( int i = 0; i < c; i++ )
|
||||
{
|
||||
C_AI_BaseNPC *obj = dynamic_cast< C_AI_BaseNPC *>(avoid.GetObject( i ));
|
||||
|
||||
if( !obj )
|
||||
continue;
|
||||
|
||||
Vector vecToObject = obj->GetAbsOrigin() - GetAbsOrigin();
|
||||
|
||||
float flDist = vecToObject.Length2D();
|
||||
|
||||
// Figure out a 2D radius for the object
|
||||
Vector vecWorldMins, vecWorldMaxs;
|
||||
obj->CollisionProp()->WorldSpaceAABB( &vecWorldMins, &vecWorldMaxs );
|
||||
Vector objSize = vecWorldMaxs - vecWorldMins;
|
||||
|
||||
float objectradius = 0.5f * sqrt( objSize.x * objSize.x + objSize.y * objSize.y );
|
||||
|
||||
//Don't run this code if the NPC is not moving UNLESS we are in stuck inside of them.
|
||||
if ( !obj->IsMoving() && flDist > objectradius )
|
||||
continue;
|
||||
|
||||
if ( flDist > objectradius && obj->IsEffectActive( EF_NODRAW ) )
|
||||
{
|
||||
obj->RemoveEffects( EF_NODRAW );
|
||||
}
|
||||
|
||||
Vector vecNPCVelocity;
|
||||
obj->EstimateAbsVelocity( vecNPCVelocity );
|
||||
float flNPCSpeed = VectorNormalize( vecNPCVelocity );
|
||||
|
||||
Vector vPlayerVel = GetAbsVelocity();
|
||||
VectorNormalize( vPlayerVel );
|
||||
|
||||
float flHit1, flHit2;
|
||||
Vector vRayDir = vecToObject;
|
||||
VectorNormalize( vRayDir );
|
||||
|
||||
float flVelProduct = DotProduct( vecNPCVelocity, vPlayerVel );
|
||||
float flDirProduct = DotProduct( vRayDir, vPlayerVel );
|
||||
|
||||
if ( !IntersectInfiniteRayWithSphere(
|
||||
GetAbsOrigin(),
|
||||
vRayDir,
|
||||
obj->GetAbsOrigin(),
|
||||
radius,
|
||||
&flHit1,
|
||||
&flHit2 ) )
|
||||
continue;
|
||||
|
||||
Vector dirToObject = -vecToObject;
|
||||
VectorNormalize( dirToObject );
|
||||
|
||||
float fwd = 0;
|
||||
float rt = 0;
|
||||
|
||||
float sidescale = 2.0f;
|
||||
float forwardscale = 1.0f;
|
||||
bool foundResult = false;
|
||||
|
||||
Vector vMoveDir = vecNPCVelocity;
|
||||
if ( flNPCSpeed > 0.001f )
|
||||
{
|
||||
// This NPC is moving. First try deflecting the player left or right relative to the NPC's velocity.
|
||||
// Start with whatever side they're on relative to the NPC's velocity.
|
||||
Vector vecNPCTrajectoryRight = CrossProduct( vecNPCVelocity, Vector( 0, 0, 1) );
|
||||
int iDirection = ( vecNPCTrajectoryRight.Dot( dirToObject ) > 0 ) ? 1 : -1;
|
||||
for ( int nTries = 0; nTries < 2; nTries++ )
|
||||
{
|
||||
Vector vecTryMove = vecNPCTrajectoryRight * iDirection;
|
||||
VectorNormalize( vecTryMove );
|
||||
|
||||
Vector vTestPosition = GetAbsOrigin() + vecTryMove * radius * 2;
|
||||
|
||||
if ( TestMove( vTestPosition, size.z * 2, radius * 2, obj->GetAbsOrigin(), vMoveDir ) )
|
||||
{
|
||||
fwd = currentdir.Dot( vecTryMove );
|
||||
rt = rightdir.Dot( vecTryMove );
|
||||
|
||||
//Msg( "PUSH DEFLECT fwd=%f, rt=%f\n", fwd, rt );
|
||||
|
||||
foundResult = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try the other direction.
|
||||
iDirection *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// the object isn't moving, so try moving opposite the way it's facing
|
||||
Vector vecNPCForward;
|
||||
obj->GetVectors( &vecNPCForward, NULL, NULL );
|
||||
|
||||
Vector vTestPosition = GetAbsOrigin() - vecNPCForward * radius * 2;
|
||||
if ( TestMove( vTestPosition, size.z * 2, radius * 2, obj->GetAbsOrigin(), vMoveDir ) )
|
||||
{
|
||||
fwd = currentdir.Dot( -vecNPCForward );
|
||||
rt = rightdir.Dot( -vecNPCForward );
|
||||
|
||||
if ( flDist < objectradius )
|
||||
{
|
||||
obj->AddEffects( EF_NODRAW );
|
||||
}
|
||||
|
||||
//Msg( "PUSH AWAY FACE fwd=%f, rt=%f\n", fwd, rt );
|
||||
|
||||
foundResult = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !foundResult )
|
||||
{
|
||||
// test if we can move in the direction the object is moving
|
||||
Vector vTestPosition = GetAbsOrigin() + vMoveDir * radius * 2;
|
||||
if ( TestMove( vTestPosition, size.z * 2, radius * 2, obj->GetAbsOrigin(), vMoveDir ) )
|
||||
{
|
||||
fwd = currentdir.Dot( vMoveDir );
|
||||
rt = rightdir.Dot( vMoveDir );
|
||||
|
||||
if ( flDist < objectradius )
|
||||
{
|
||||
obj->AddEffects( EF_NODRAW );
|
||||
}
|
||||
|
||||
//Msg( "PUSH ALONG fwd=%f, rt=%f\n", fwd, rt );
|
||||
|
||||
foundResult = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// try moving directly away from the object
|
||||
Vector vTestPosition = GetAbsOrigin() - dirToObject * radius * 2;
|
||||
if ( TestMove( vTestPosition, size.z * 2, radius * 2, obj->GetAbsOrigin(), vMoveDir ) )
|
||||
{
|
||||
fwd = currentdir.Dot( -dirToObject );
|
||||
rt = rightdir.Dot( -dirToObject );
|
||||
foundResult = true;
|
||||
|
||||
//Msg( "PUSH AWAY fwd=%f, rt=%f\n", fwd, rt );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !foundResult )
|
||||
{
|
||||
// test if we can move through the object
|
||||
Vector vTestPosition = GetAbsOrigin() - vMoveDir * radius * 2;
|
||||
fwd = currentdir.Dot( -vMoveDir );
|
||||
rt = rightdir.Dot( -vMoveDir );
|
||||
|
||||
if ( flDist < objectradius )
|
||||
{
|
||||
obj->AddEffects( EF_NODRAW );
|
||||
}
|
||||
|
||||
//Msg( "PUSH THROUGH fwd=%f, rt=%f\n", fwd, rt );
|
||||
|
||||
foundResult = true;
|
||||
}
|
||||
|
||||
// If running, then do a lot more sideways veer since we're not going to do anything to
|
||||
// forward velocity
|
||||
if ( istryingtomove )
|
||||
{
|
||||
sidescale = 6.0f;
|
||||
}
|
||||
|
||||
if ( flVelProduct > 0.0f && flDirProduct > 0.0f )
|
||||
{
|
||||
sidescale = 0.1f;
|
||||
}
|
||||
|
||||
float force = 1.0f;
|
||||
float forward = forwardscale * fwd * force * AVOID_SPEED;
|
||||
float side = sidescale * rt * force * AVOID_SPEED;
|
||||
|
||||
adjustforwardmove += forward;
|
||||
adjustsidemove += side;
|
||||
}
|
||||
|
||||
pCmd->forwardmove += adjustforwardmove;
|
||||
pCmd->sidemove += adjustsidemove;
|
||||
|
||||
// Clamp the move to within legal limits, preserving direction. This is a little
|
||||
// complicated because we have different limits for forward, back, and side
|
||||
|
||||
//Msg( "PRECLAMP: forwardmove=%f, sidemove=%f\n", pCmd->forwardmove, pCmd->sidemove );
|
||||
|
||||
float flForwardScale = 1.0f;
|
||||
if ( pCmd->forwardmove > fabs( cl_forwardspeed.GetFloat() ) )
|
||||
{
|
||||
flForwardScale = fabs( cl_forwardspeed.GetFloat() ) / pCmd->forwardmove;
|
||||
}
|
||||
else if ( pCmd->forwardmove < -fabs( cl_backspeed.GetFloat() ) )
|
||||
{
|
||||
flForwardScale = fabs( cl_backspeed.GetFloat() ) / fabs( pCmd->forwardmove );
|
||||
}
|
||||
|
||||
float flSideScale = 1.0f;
|
||||
if ( fabs( pCmd->sidemove ) > fabs( cl_sidespeed.GetFloat() ) )
|
||||
{
|
||||
flSideScale = fabs( cl_sidespeed.GetFloat() ) / fabs( pCmd->sidemove );
|
||||
}
|
||||
|
||||
float flScale = MIN( flForwardScale, flSideScale );
|
||||
pCmd->forwardmove *= flScale;
|
||||
pCmd->sidemove *= flScale;
|
||||
|
||||
//Msg( "POSTCLAMP: forwardmove=%f, sidemove=%f\n", pCmd->forwardmove, pCmd->sidemove );
|
||||
}
|
||||
|
||||
|
||||
void C_BaseHLPlayer::PerformClientSideNPCSpeedModifiers( float flFrameTime, CUserCmd *pCmd )
|
||||
{
|
||||
if ( m_hClosestNPC == NULL )
|
||||
{
|
||||
if ( m_flSpeedMod != cl_forwardspeed.GetFloat() )
|
||||
{
|
||||
float flDeltaTime = (m_flSpeedModTime - gpGlobals->curtime);
|
||||
m_flSpeedMod = RemapValClamped( flDeltaTime, cl_npc_speedmod_outtime.GetFloat(), 0, m_flExitSpeedMod, cl_forwardspeed.GetFloat() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
C_AI_BaseNPC *pNPC = dynamic_cast< C_AI_BaseNPC *>( m_hClosestNPC.Get() );
|
||||
|
||||
if ( pNPC )
|
||||
{
|
||||
float flDist = (GetAbsOrigin() - pNPC->GetAbsOrigin()).LengthSqr();
|
||||
bool bShouldModSpeed = false;
|
||||
|
||||
// Within range?
|
||||
if ( flDist < pNPC->GetSpeedModifyRadius() )
|
||||
{
|
||||
// Now, only slowdown if we're facing & running parallel to the target's movement
|
||||
// Facing check first (in 2D)
|
||||
Vector vecTargetOrigin = pNPC->GetAbsOrigin();
|
||||
Vector los = ( vecTargetOrigin - EyePosition() );
|
||||
los.z = 0;
|
||||
VectorNormalize( los );
|
||||
Vector facingDir;
|
||||
AngleVectors( GetAbsAngles(), &facingDir );
|
||||
float flDot = DotProduct( los, facingDir );
|
||||
if ( flDot > 0.8 )
|
||||
{
|
||||
/*
|
||||
// Velocity check (abort if the target isn't moving)
|
||||
Vector vecTargetVelocity;
|
||||
pNPC->EstimateAbsVelocity( vecTargetVelocity );
|
||||
float flSpeed = VectorNormalize(vecTargetVelocity);
|
||||
Vector vecMyVelocity = GetAbsVelocity();
|
||||
VectorNormalize(vecMyVelocity);
|
||||
if ( flSpeed > 1.0 )
|
||||
{
|
||||
// Velocity roughly parallel?
|
||||
if ( DotProduct(vecTargetVelocity,vecMyVelocity) > 0.4 )
|
||||
{
|
||||
bShouldModSpeed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// NPC's not moving, slow down if we're moving at him
|
||||
//Msg("Dot: %.2f\n", DotProduct( los, vecMyVelocity ) );
|
||||
if ( DotProduct( los, vecMyVelocity ) > 0.8 )
|
||||
{
|
||||
bShouldModSpeed = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bShouldModSpeed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bShouldModSpeed )
|
||||
{
|
||||
m_hClosestNPC = NULL;
|
||||
m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_outtime.GetFloat();
|
||||
m_flExitSpeedMod = m_flSpeedMod;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_flSpeedMod != pNPC->GetSpeedModifySpeed() )
|
||||
{
|
||||
float flDeltaTime = (m_flSpeedModTime - gpGlobals->curtime);
|
||||
m_flSpeedMod = RemapValClamped( flDeltaTime, cl_npc_speedmod_intime.GetFloat(), 0, cl_forwardspeed.GetFloat(), pNPC->GetSpeedModifySpeed() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( pCmd->forwardmove > 0.0f )
|
||||
{
|
||||
pCmd->forwardmove = clamp( pCmd->forwardmove, -m_flSpeedMod, m_flSpeedMod );
|
||||
}
|
||||
else
|
||||
{
|
||||
pCmd->forwardmove = clamp( pCmd->forwardmove, -m_flSpeedMod, m_flSpeedMod );
|
||||
}
|
||||
pCmd->sidemove = clamp( pCmd->sidemove, -m_flSpeedMod, m_flSpeedMod );
|
||||
|
||||
//Msg( "fwd %f right %f\n", pCmd->forwardmove, pCmd->sidemove );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handling
|
||||
//-----------------------------------------------------------------------------
|
||||
bool C_BaseHLPlayer::CreateMove( float flInputSampleTime, CUserCmd *pCmd )
|
||||
{
|
||||
bool bResult = BaseClass::CreateMove( flInputSampleTime, pCmd );
|
||||
|
||||
if ( !IsInAVehicle() )
|
||||
{
|
||||
PerformClientSideObstacleAvoidance( TICK_INTERVAL, pCmd );
|
||||
PerformClientSideNPCSpeedModifiers( TICK_INTERVAL, pCmd );
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Input handling
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BaseHLPlayer::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed )
|
||||
{
|
||||
BaseClass::BuildTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed );
|
||||
BuildFirstPersonMeathookTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed, "ValveBiped.Bip01_Head1" );
|
||||
}
|
||||
|
||||
87
sp/src/game/client/hl2/c_basehlplayer.h
Normal file
87
sp/src/game/client/hl2/c_basehlplayer.h
Normal file
@@ -0,0 +1,87 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#if !defined( C_BASEHLPLAYER_H )
|
||||
#define C_BASEHLPLAYER_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "c_baseplayer.h"
|
||||
#include "c_hl2_playerlocaldata.h"
|
||||
|
||||
class C_BaseHLPlayer : public C_BasePlayer
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_BaseHLPlayer, C_BasePlayer );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
C_BaseHLPlayer();
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
|
||||
void Weapon_DropPrimary( void );
|
||||
|
||||
float GetFOV();
|
||||
void Zoom( float FOVOffset, float time );
|
||||
float GetZoom( void );
|
||||
bool IsZoomed( void ) { return m_HL2Local.m_bZooming; }
|
||||
|
||||
//Tony; minor cosmetic really, fix confusion by simply renaming this one; everything calls IsSprinting(), and this isn't really even used.
|
||||
bool IsSprintActive( void ) { return m_HL2Local.m_bitsActiveDevices & bits_SUIT_DEVICE_SPRINT; }
|
||||
bool IsFlashlightActive( void ) { return m_HL2Local.m_bitsActiveDevices & bits_SUIT_DEVICE_FLASHLIGHT; }
|
||||
bool IsBreatherActive( void ) { return m_HL2Local.m_bitsActiveDevices & bits_SUIT_DEVICE_BREATHER; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool IsCustomDevice0Active( void ) { return m_HL2Local.m_bitsActiveDevices & bits_SUIT_DEVICE_CUSTOM0; }
|
||||
bool IsCustomDevice1Active( void ) { return m_HL2Local.m_bitsActiveDevices & bits_SUIT_DEVICE_CUSTOM1; }
|
||||
bool IsCustomDevice2Active( void ) { return m_HL2Local.m_bitsActiveDevices & bits_SUIT_DEVICE_CUSTOM2; }
|
||||
#endif
|
||||
|
||||
virtual int DrawModel( int flags );
|
||||
virtual void BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed );
|
||||
|
||||
LadderMove_t *GetLadderMove() { return &m_HL2Local.m_LadderMove; }
|
||||
virtual void ExitLadder();
|
||||
bool IsSprinting() const { return m_fIsSprinting; }
|
||||
|
||||
// Input handling
|
||||
virtual bool CreateMove( float flInputSampleTime, CUserCmd *pCmd );
|
||||
void PerformClientSideObstacleAvoidance( float flFrameTime, CUserCmd *pCmd );
|
||||
void PerformClientSideNPCSpeedModifiers( float flFrameTime, CUserCmd *pCmd );
|
||||
|
||||
bool IsWeaponLowered( void ) { return m_HL2Local.m_bWeaponLowered; }
|
||||
|
||||
public:
|
||||
|
||||
C_HL2PlayerLocalData m_HL2Local;
|
||||
EHANDLE m_hClosestNPC;
|
||||
float m_flSpeedModTime;
|
||||
bool m_fIsSprinting;
|
||||
|
||||
private:
|
||||
C_BaseHLPlayer( const C_BaseHLPlayer & ); // not defined, not accessible
|
||||
|
||||
bool TestMove( const Vector &pos, float fVertDist, float radius, const Vector &objPos, const Vector &objDir );
|
||||
|
||||
float m_flZoomStart;
|
||||
float m_flZoomEnd;
|
||||
float m_flZoomRate;
|
||||
float m_flZoomStartTime;
|
||||
|
||||
bool m_bPlayUseDenySound; // Signaled by PlayerUse, but can be unset by HL2 ladder code...
|
||||
float m_flSpeedMod;
|
||||
float m_flExitSpeedMod;
|
||||
|
||||
|
||||
friend class CHL2GameMovement;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
483
sp/src/game/client/hl2/c_citadel_effects.cpp
Normal file
483
sp/src/game/client/hl2/c_citadel_effects.cpp
Normal file
@@ -0,0 +1,483 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "particles_simple.h"
|
||||
#include "citadel_effects_shared.h"
|
||||
#include "particles_attractor.h"
|
||||
#include "fx_quad.h"
|
||||
|
||||
class C_CitadelEnergyCore : public C_BaseEntity
|
||||
{
|
||||
DECLARE_CLASS( C_CitadelEnergyCore, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
public:
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
RenderGroup_t GetRenderGroup( void );
|
||||
|
||||
void ClientThink( void );
|
||||
void NotifyShouldTransmit( ShouldTransmitState_t state );
|
||||
|
||||
void UpdateIdle( float percentage );
|
||||
void UpdateCharging( float percentage );
|
||||
void UpdateDischarging( void );
|
||||
|
||||
private:
|
||||
|
||||
bool SetupEmitters( void );
|
||||
inline float GetStateDurationPercentage( void );
|
||||
|
||||
float m_flScale;
|
||||
int m_nState;
|
||||
float m_flDuration;
|
||||
float m_flStartTime;
|
||||
int m_spawnflags;
|
||||
|
||||
CSmartPtr<CSimpleEmitter> m_pSimpleEmitter;
|
||||
CSmartPtr<CParticleAttractor> m_pAttractorEmitter;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_CitadelEnergyCore, DT_CitadelEnergyCore, CCitadelEnergyCore )
|
||||
RecvPropFloat( RECVINFO(m_flScale) ),
|
||||
RecvPropInt( RECVINFO(m_nState) ),
|
||||
RecvPropFloat( RECVINFO(m_flDuration) ),
|
||||
RecvPropFloat( RECVINFO(m_flStartTime) ),
|
||||
RecvPropInt( RECVINFO(m_spawnflags) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : RenderGroup_t
|
||||
//-----------------------------------------------------------------------------
|
||||
RenderGroup_t C_CitadelEnergyCore::GetRenderGroup( void )
|
||||
{
|
||||
return RENDER_GROUP_TRANSLUCENT_ENTITY;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_CitadelEnergyCore::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
SetupEmitters();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool C_CitadelEnergyCore::SetupEmitters( void )
|
||||
{
|
||||
// Setup the basic core emitter
|
||||
if ( m_pSimpleEmitter.IsValid() == false )
|
||||
{
|
||||
m_pSimpleEmitter = CSimpleEmitter::Create( "energycore" );
|
||||
|
||||
if ( m_pSimpleEmitter.IsValid() == false )
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup the attractor emitter
|
||||
if ( m_pAttractorEmitter.IsValid() == false )
|
||||
{
|
||||
m_pAttractorEmitter = CParticleAttractor::Create( GetAbsOrigin(), "energyattractor" );
|
||||
|
||||
if ( m_pAttractorEmitter.IsValid() == false )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : percentage -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_CitadelEnergyCore::UpdateIdle( float percentage )
|
||||
{
|
||||
// Only do these particles if required
|
||||
if ( m_spawnflags & SF_ENERGYCORE_NO_PARTICLES )
|
||||
return;
|
||||
|
||||
// Must be active
|
||||
if ( percentage >= 1.0f )
|
||||
return;
|
||||
|
||||
// Emitters must be valid
|
||||
if ( SetupEmitters() == false )
|
||||
return;
|
||||
|
||||
// Reset our sort origin
|
||||
m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
// Do the charging particles
|
||||
m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() );
|
||||
|
||||
Vector forward, right, up;
|
||||
AngleVectors( GetAbsAngles(), &forward, &right, &up );
|
||||
|
||||
Vector offset;
|
||||
float dist;
|
||||
|
||||
int numParticles = floor( 4.0f * percentage );
|
||||
|
||||
for ( int i = 0; i < numParticles; i++ )
|
||||
{
|
||||
dist = random->RandomFloat( 4.0f * percentage, 64.0f * percentage );
|
||||
|
||||
offset = forward * dist;
|
||||
|
||||
dist = RemapValClamped( dist, 4.0f * percentage, 64.0f * percentage, 6.0f, 1.0f );
|
||||
offset += right * random->RandomFloat( -4.0f * dist, 4.0f * dist );
|
||||
offset += up * random->RandomFloat( -4.0f * dist, 4.0f * dist );
|
||||
|
||||
offset += GetAbsOrigin();
|
||||
|
||||
sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( "effects/strider_muzzle" ), offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = Vector(0,0,8);
|
||||
sParticle->m_flDieTime = 0.5f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
|
||||
float alpha = 255 * percentage;
|
||||
|
||||
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_uchStartSize = random->RandomFloat( 1, 2 );
|
||||
sParticle->m_uchEndSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : percentage -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_CitadelEnergyCore::UpdateCharging( float percentage )
|
||||
{
|
||||
// Emitters must be valid
|
||||
if ( SetupEmitters() == false )
|
||||
return;
|
||||
|
||||
if ( percentage <= 0.0f )
|
||||
return;
|
||||
|
||||
// Reset our sort origin
|
||||
m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
float flScale = 4.0f * m_flScale * percentage;
|
||||
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
// Do the core effects
|
||||
for ( int i = 0; i < 2; i++ )
|
||||
{
|
||||
sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( "effects/strider_muzzle" ), GetAbsOrigin() );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = vec3_origin;
|
||||
sParticle->m_flDieTime = 0.1f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.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;
|
||||
|
||||
if ( i < 2 )
|
||||
{
|
||||
sParticle->m_uchStartSize = flScale * (i+1);
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( random->RandomInt( 0, 20 ) == 0 )
|
||||
{
|
||||
sParticle->m_uchStartSize = flScale * (i+1);
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 4.0f;
|
||||
sParticle->m_flDieTime = 0.25f;
|
||||
}
|
||||
else
|
||||
{
|
||||
sParticle->m_uchStartSize = flScale * (i+1);
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only do these particles if required
|
||||
if ( m_spawnflags & SF_ENERGYCORE_NO_PARTICLES )
|
||||
return;
|
||||
|
||||
// Do the charging particles
|
||||
m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() );
|
||||
|
||||
Vector forward, right, up;
|
||||
AngleVectors( GetAbsAngles(), &forward, &right, &up );
|
||||
|
||||
Vector offset;
|
||||
float dist;
|
||||
|
||||
int numParticles = floor( 4.0f * percentage );
|
||||
|
||||
for ( int i = 0; i < numParticles; i++ )
|
||||
{
|
||||
dist = random->RandomFloat( 4.0f * percentage, 64.0f * percentage );
|
||||
|
||||
offset = forward * dist;
|
||||
|
||||
dist = RemapValClamped( dist, 4.0f * percentage, 64.0f * percentage, 6.0f, 1.0f );
|
||||
offset += right * random->RandomFloat( -4.0f * dist, 4.0f * dist );
|
||||
offset += up * random->RandomFloat( -4.0f * dist, 4.0f * dist );
|
||||
|
||||
offset += GetAbsOrigin();
|
||||
|
||||
sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( "effects/strider_muzzle" ), offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = Vector(0,0,8);
|
||||
sParticle->m_flDieTime = 0.5f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
|
||||
float alpha = 255 * percentage;
|
||||
|
||||
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_uchStartSize = random->RandomFloat( 1, 2 );
|
||||
sParticle->m_uchEndSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : percentage -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_CitadelEnergyCore::UpdateDischarging( void )
|
||||
{
|
||||
// Emitters must be valid
|
||||
if ( SetupEmitters() == false )
|
||||
return;
|
||||
|
||||
// Reset our sort origin
|
||||
m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
float flScale = 8.0f * m_flScale;
|
||||
|
||||
Vector forward, right, up;
|
||||
AngleVectors( GetAbsAngles(), &forward, &right, &up );
|
||||
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
// Base of the core effect
|
||||
sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( "effects/strider_muzzle" ), GetAbsOrigin() );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = forward * 32.0f;
|
||||
sParticle->m_flDieTime = 0.2f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
|
||||
float alpha = 128;
|
||||
|
||||
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_uchStartSize = flScale * 2.0f;
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f;
|
||||
|
||||
// Make sure we encompass the complete particle here!
|
||||
m_pSimpleEmitter->SetParticleCullRadius( sParticle->m_uchEndSize );
|
||||
|
||||
// Do the core effects
|
||||
for ( int i = 0; i < 2; i++ )
|
||||
{
|
||||
sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( "effects/combinemuzzle2" ), GetAbsOrigin() );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = forward * ( 32.0f * (i+1) );
|
||||
sParticle->m_flDieTime = 0.2f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
|
||||
float alpha = 100;
|
||||
|
||||
sParticle->m_uchColor[0] = alpha;
|
||||
sParticle->m_uchColor[1] = alpha;
|
||||
sParticle->m_uchColor[2] = alpha;
|
||||
sParticle->m_uchStartAlpha = alpha;
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
|
||||
if ( i < 1 )
|
||||
{
|
||||
sParticle->m_uchStartSize = flScale * (i+1);
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( random->RandomInt( 0, 20 ) == 0 )
|
||||
{
|
||||
sParticle->m_uchStartSize = flScale * (i+1);
|
||||
sParticle->m_uchEndSize = 0.0f;
|
||||
sParticle->m_flDieTime = 0.25f;
|
||||
}
|
||||
else
|
||||
{
|
||||
sParticle->m_uchStartSize = flScale * (i+1);
|
||||
sParticle->m_uchEndSize = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only do these particles if required
|
||||
if ( m_spawnflags & SF_ENERGYCORE_NO_PARTICLES )
|
||||
return;
|
||||
|
||||
// Do the charging particles
|
||||
m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() );
|
||||
|
||||
Vector offset;
|
||||
float dist;
|
||||
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
dist = random->RandomFloat( 4.0f * m_flScale, 64.0f * m_flScale );
|
||||
|
||||
offset = forward * dist;
|
||||
|
||||
dist = RemapValClamped( dist, 4.0f * m_flScale, 64.0f * m_flScale, 6.0f, 1.0f );
|
||||
offset += right * random->RandomFloat( -2.0f * dist * m_flScale, 2.0f * dist * m_flScale );
|
||||
offset += up * random->RandomFloat( -2.0f * dist * m_flScale, 2.0f * dist * m_flScale );
|
||||
|
||||
offset += GetAbsOrigin();
|
||||
|
||||
sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( "effects/combinemuzzle2_dark" ), offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = Vector(0,0,2);
|
||||
sParticle->m_flDieTime = 0.5f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.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_uchStartSize = 1;
|
||||
sParticle->m_uchEndSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : inline float
|
||||
//-----------------------------------------------------------------------------
|
||||
inline float C_CitadelEnergyCore::GetStateDurationPercentage( void )
|
||||
{
|
||||
if ( m_flDuration == 0 )
|
||||
return 0.0f;
|
||||
|
||||
return RemapValClamped( ( gpGlobals->curtime - m_flStartTime ), 0, m_flDuration, 0, 1.0f );;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_CitadelEnergyCore::NotifyShouldTransmit( ShouldTransmitState_t state )
|
||||
{
|
||||
BaseClass::NotifyShouldTransmit( state );
|
||||
|
||||
// Turn off
|
||||
if ( state == SHOULDTRANSMIT_END )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||
}
|
||||
|
||||
// Turn on
|
||||
if ( state == SHOULDTRANSMIT_START )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_CitadelEnergyCore::ClientThink( void )
|
||||
{
|
||||
if ( gpGlobals->frametime <= 0.0f )
|
||||
return;
|
||||
|
||||
float flDuration = GetStateDurationPercentage();
|
||||
|
||||
switch( m_nState )
|
||||
{
|
||||
case ENERGYCORE_STATE_OFF:
|
||||
UpdateIdle( 1.0f - flDuration );
|
||||
break;
|
||||
|
||||
case ENERGYCORE_STATE_CHARGING:
|
||||
UpdateCharging( flDuration );
|
||||
break;
|
||||
|
||||
case ENERGYCORE_STATE_DISCHARGING:
|
||||
UpdateDischarging( );
|
||||
break;
|
||||
}
|
||||
}
|
||||
66
sp/src/game/client/hl2/c_corpse.cpp
Normal file
66
sp/src/game/client/hl2/c_corpse.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Implements C_Corpse
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "c_corpse.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_Corpse, DT_Corpse, CCorpse)
|
||||
RecvPropInt(RECVINFO(m_nReferencePlayer))
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
|
||||
|
||||
C_Corpse::C_Corpse()
|
||||
{
|
||||
m_nReferencePlayer = 0;
|
||||
}
|
||||
|
||||
|
||||
int C_Corpse::DrawModel( int flags )
|
||||
{
|
||||
int drawn = 0;
|
||||
if ( m_nReferencePlayer <= 0 ||
|
||||
m_nReferencePlayer > gpGlobals->maxClients )
|
||||
{
|
||||
return drawn;
|
||||
};
|
||||
|
||||
// Make sure m_pstudiohdr is valid for drawing
|
||||
if ( !GetModelPtr() )
|
||||
{
|
||||
return drawn;
|
||||
}
|
||||
|
||||
if ( !m_bReadyToDraw )
|
||||
return 0;
|
||||
|
||||
// get copy of player
|
||||
C_BasePlayer *player = dynamic_cast< C_BasePlayer *>( cl_entitylist->GetEnt( m_nReferencePlayer ) );
|
||||
if ( player )
|
||||
{
|
||||
Vector zero;
|
||||
zero.Init();
|
||||
|
||||
drawn = modelrender->DrawModel(
|
||||
flags,
|
||||
this,
|
||||
MODEL_INSTANCE_INVALID,
|
||||
m_nReferencePlayer,
|
||||
GetModel(),
|
||||
GetAbsOrigin(),
|
||||
GetAbsAngles(),
|
||||
m_nSkin,
|
||||
m_nBody,
|
||||
m_nHitboxSet );
|
||||
}
|
||||
|
||||
return drawn;
|
||||
}
|
||||
|
||||
32
sp/src/game/client/hl2/c_corpse.h
Normal file
32
sp/src/game/client/hl2/c_corpse.h
Normal file
@@ -0,0 +1,32 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#if !defined( C_CORPSE_H )
|
||||
#define C_CORPSE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
class C_Corpse : public C_BaseAnimating
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_Corpse, C_BaseAnimating );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_Corpse( void );
|
||||
|
||||
virtual int DrawModel( int flags );
|
||||
|
||||
public:
|
||||
// The player whom we are copying our data from
|
||||
int m_nReferencePlayer;
|
||||
|
||||
private:
|
||||
C_Corpse( const C_Corpse & );
|
||||
};
|
||||
|
||||
|
||||
#endif // C_CORPSE_H
|
||||
416
sp/src/game/client/hl2/c_energy_wave.cpp
Normal file
416
sp/src/game/client/hl2/c_energy_wave.cpp
Normal file
@@ -0,0 +1,416 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Client's energy wave
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $Log: $
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "materialsystem/imaterialsystem.h"
|
||||
#include "materialsystem/imesh.h"
|
||||
#include "energy_wave_effect.h"
|
||||
#include "mathlib/vmatrix.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEnergyWave )
|
||||
CLIENTEFFECT_MATERIAL( "effects/energywave/energywave" )
|
||||
CLIENTEFFECT_REGISTER_END()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Energy Wave:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class C_EnergyWave : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_EnergyWave, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_EnergyWave();
|
||||
~C_EnergyWave();
|
||||
|
||||
void PostDataUpdate( DataUpdateType_t updateType );
|
||||
int DrawModel( int flags );
|
||||
void ComputePoint( float s, float t, Vector& pt, Vector& normal, float& opacity );
|
||||
void DrawWireframeModel( );
|
||||
|
||||
CEnergyWaveEffect m_EWaveEffect;
|
||||
|
||||
IMaterial* m_pWireframe;
|
||||
IMaterial* m_pEWaveMat;
|
||||
|
||||
private:
|
||||
C_EnergyWave( const C_EnergyWave & ); // not defined, not accessible
|
||||
|
||||
void ComputeEWavePoints( Vector* pt, Vector* normal, float* opacity );
|
||||
void DrawEWavePoints(Vector* pt, Vector* normal, float* opacity);
|
||||
|
||||
};
|
||||
|
||||
|
||||
EXTERN_RECV_TABLE(DT_BaseEntity);
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_EnergyWave, DT_EWaveEffect, CEnergyWave)
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Functions.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
C_EnergyWave::C_EnergyWave() : m_EWaveEffect(NULL, NULL)
|
||||
{
|
||||
m_pWireframe = materials->FindMaterial("shadertest/wireframevertexcolor", TEXTURE_GROUP_OTHER);
|
||||
m_pEWaveMat = materials->FindMaterial("effects/energywave/energywave", TEXTURE_GROUP_CLIENT_EFFECTS);
|
||||
m_EWaveEffect.Spawn();
|
||||
}
|
||||
|
||||
C_EnergyWave::~C_EnergyWave()
|
||||
{
|
||||
}
|
||||
|
||||
void C_EnergyWave::PostDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
MarkMessageReceived();
|
||||
|
||||
// Make sure that origin points to current origin, at least
|
||||
MoveToLastReceivedPosition();
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
NUM_SUBDIVISIONS = 21,
|
||||
};
|
||||
|
||||
|
||||
static void ComputeIndices( int is, int it, int* idx )
|
||||
{
|
||||
int is0 = (is > 0) ? (is - 1) : is;
|
||||
int it0 = (it > 0) ? (it - 1) : it;
|
||||
int is1 = (is < EWAVE_NUM_HORIZONTAL_POINTS - 1) ? is + 1 : is;
|
||||
int it1 = (it < EWAVE_NUM_HORIZONTAL_POINTS - 1) ? it + 1 : it;
|
||||
int is2 = is + 2;
|
||||
int it2 = it + 2;
|
||||
if (is2 >= EWAVE_NUM_HORIZONTAL_POINTS)
|
||||
is2 = EWAVE_NUM_HORIZONTAL_POINTS - 1;
|
||||
if (it2 >= EWAVE_NUM_HORIZONTAL_POINTS)
|
||||
it2 = EWAVE_NUM_HORIZONTAL_POINTS - 1;
|
||||
|
||||
idx[0] = is0 + it0 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[1] = is + it0 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[2] = is1 + it0 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[3] = is2 + it0 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
|
||||
idx[4] = is0 + it * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[5] = is + it * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[6] = is1 + it * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[7] = is2 + it * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
|
||||
idx[8] = is0 + it1 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[9] = is + it1 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[10] = is1 + it1 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[11] = is2 + it1 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
|
||||
idx[12] = is0 + it2 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[13] = is + it2 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[14] = is1 + it2 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
idx[15] = is2 + it2 * EWAVE_NUM_HORIZONTAL_POINTS;
|
||||
}
|
||||
|
||||
void C_EnergyWave::ComputePoint( float s, float t, Vector& pt, Vector& normal, float& opacity )
|
||||
{
|
||||
int is = (int)s;
|
||||
int it = (int)t;
|
||||
if( is >= EWAVE_NUM_HORIZONTAL_POINTS )
|
||||
is -= 1;
|
||||
|
||||
if( it >= EWAVE_NUM_VERTICAL_POINTS )
|
||||
it -= 1;
|
||||
|
||||
int idx[16];
|
||||
ComputeIndices( is, it, idx );
|
||||
|
||||
// The patch equation is:
|
||||
// px = S * M * Gx * M^T * T^T
|
||||
// py = S * M * Gy * M^T * T^T
|
||||
// pz = S * M * Gz * M^T * T^T
|
||||
// where S = [s^3 s^2 s 1], T = [t^3 t^2 t 1]
|
||||
// M is the patch type matrix, in my case I'm using a catmull-rom
|
||||
// G is the array of control points. rows have constant t
|
||||
static VMatrix catmullRom( -0.5, 1.5, -1.5, 0.5,
|
||||
1, -2.5, 2, -0.5,
|
||||
-0.5, 0, 0.5, 0,
|
||||
0, 1, 0, 0 );
|
||||
|
||||
VMatrix controlPointsX, controlPointsY, controlPointsZ, controlPointsO;
|
||||
|
||||
Vector pos;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
const Vector& v = m_EWaveEffect.GetPoint( idx[i * 4 + j] );
|
||||
|
||||
controlPointsX[j][i] = v.x;
|
||||
controlPointsY[j][i] = v.y;
|
||||
controlPointsZ[j][i] = v.z;
|
||||
|
||||
controlPointsO[j][i] = m_EWaveEffect.ComputeOpacity( v, GetAbsOrigin() );
|
||||
}
|
||||
}
|
||||
|
||||
float fs = s - is;
|
||||
float ft = t - it;
|
||||
|
||||
VMatrix temp, mgm[4];
|
||||
MatrixTranspose( catmullRom, temp );
|
||||
MatrixMultiply( controlPointsX, temp, mgm[0] );
|
||||
MatrixMultiply( controlPointsY, temp, mgm[1] );
|
||||
MatrixMultiply( controlPointsZ, temp, mgm[2] );
|
||||
MatrixMultiply( controlPointsO, temp, mgm[3] );
|
||||
|
||||
MatrixMultiply( catmullRom, mgm[0], mgm[0] );
|
||||
MatrixMultiply( catmullRom, mgm[1], mgm[1] );
|
||||
MatrixMultiply( catmullRom, mgm[2], mgm[2] );
|
||||
MatrixMultiply( catmullRom, mgm[3], mgm[3] );
|
||||
|
||||
Vector4D svec, tvec;
|
||||
float ft2 = ft * ft;
|
||||
tvec[0] = ft2 * ft; tvec[1] = ft2; tvec[2] = ft; tvec[3] = 1.0f;
|
||||
|
||||
float fs2 = fs * fs;
|
||||
svec[0] = fs2 * fs; svec[1] = fs2; svec[2] = fs; svec[3] = 1.0f;
|
||||
|
||||
Vector4D tmp;
|
||||
Vector4DMultiply( mgm[0], tvec, tmp );
|
||||
pt[0] = DotProduct4D( tmp, svec );
|
||||
Vector4DMultiply( mgm[1], tvec, tmp );
|
||||
pt[1] = DotProduct4D( tmp, svec );
|
||||
Vector4DMultiply( mgm[2], tvec, tmp );
|
||||
pt[2] = DotProduct4D( tmp, svec );
|
||||
|
||||
Vector4DMultiply( mgm[3], tvec, tmp );
|
||||
opacity = DotProduct4D( tmp, svec );
|
||||
|
||||
if ((s == 0.0f) || (t == 0.0f) ||
|
||||
(s == (EWAVE_NUM_HORIZONTAL_POINTS-1.0f)) || (t == (EWAVE_NUM_VERTICAL_POINTS-1.0f)) )
|
||||
{
|
||||
opacity = 0.0f;
|
||||
}
|
||||
|
||||
if ((s <= 0.3) || (t < 0.3))
|
||||
{
|
||||
opacity *= 0.35f;
|
||||
}
|
||||
if ((s == (EWAVE_NUM_HORIZONTAL_POINTS-0.7f)) || (t == (EWAVE_NUM_VERTICAL_POINTS-0.7f)) )
|
||||
{
|
||||
opacity *= 0.35f;
|
||||
}
|
||||
|
||||
if (opacity < 0.0f)
|
||||
opacity = 0.0f;
|
||||
else if (opacity > 255.0f)
|
||||
opacity = 255.0f;
|
||||
|
||||
// Normal computation
|
||||
Vector4D dsvec, dtvec;
|
||||
dsvec[0] = 3.0f * fs2; dsvec[1] = 2.0f * fs; dsvec[2] = 1.0f; dsvec[3] = 0.0f;
|
||||
dtvec[0] = 3.0f * ft2; dtvec[1] = 2.0f * ft; dtvec[2] = 1.0f; dtvec[3] = 0.0f;
|
||||
|
||||
Vector ds, dt;
|
||||
Vector4DMultiply( mgm[0], tvec, tmp );
|
||||
ds[0] = DotProduct4D( tmp, dsvec );
|
||||
Vector4DMultiply( mgm[1], tvec, tmp );
|
||||
ds[1] = DotProduct4D( tmp, dsvec );
|
||||
Vector4DMultiply( mgm[2], tvec, tmp );
|
||||
ds[2] = DotProduct4D( tmp, dsvec );
|
||||
|
||||
Vector4DMultiply( mgm[0], dtvec, tmp );
|
||||
dt[0] = DotProduct4D( tmp, svec );
|
||||
Vector4DMultiply( mgm[1], dtvec, tmp );
|
||||
dt[1] = DotProduct4D( tmp, svec );
|
||||
Vector4DMultiply( mgm[2], dtvec, tmp );
|
||||
dt[2] = DotProduct4D( tmp, svec );
|
||||
|
||||
CrossProduct( ds, dt, normal );
|
||||
VectorNormalize( normal );
|
||||
}
|
||||
|
||||
void C_EnergyWave::DrawWireframeModel( )
|
||||
{
|
||||
IMesh* pMesh = materials->GetDynamicMesh( true, NULL, NULL, m_pWireframe );
|
||||
|
||||
int numLines = (EWAVE_NUM_VERTICAL_POINTS - 1) * EWAVE_NUM_HORIZONTAL_POINTS +
|
||||
EWAVE_NUM_VERTICAL_POINTS * (EWAVE_NUM_HORIZONTAL_POINTS - 1);
|
||||
|
||||
CMeshBuilder meshBuilder;
|
||||
meshBuilder.Begin( pMesh, MATERIAL_LINES, numLines );
|
||||
|
||||
Vector tmp;
|
||||
for (int i = 0; i < EWAVE_NUM_VERTICAL_POINTS; ++i)
|
||||
{
|
||||
for (int j = 0; j < EWAVE_NUM_HORIZONTAL_POINTS; ++j)
|
||||
{
|
||||
if ( i > 0 )
|
||||
{
|
||||
meshBuilder.Position3fv( m_EWaveEffect.GetPoint( j, i ).Base() );
|
||||
meshBuilder.Color4ub( 255, 255, 255, 128 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Position3fv( m_EWaveEffect.GetPoint( j, i - 1 ).Base() );
|
||||
meshBuilder.Color4ub( 255, 255, 255, 128 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
}
|
||||
|
||||
if (j > 0)
|
||||
{
|
||||
meshBuilder.Position3fv( m_EWaveEffect.GetPoint( j, i ).Base() );
|
||||
meshBuilder.Color4ub( 255, 255, 255, 128 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Position3fv( m_EWaveEffect.GetPoint( j - 1, i ).Base() );
|
||||
meshBuilder.Color4ub( 255, 255, 255, 128 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
meshBuilder.End();
|
||||
pMesh->Draw();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compute the ewave points using catmull-rom
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void C_EnergyWave::ComputeEWavePoints( Vector* pt, Vector* normal, float* opacity )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < NUM_SUBDIVISIONS; ++i)
|
||||
{
|
||||
float t = (EWAVE_NUM_VERTICAL_POINTS -1 ) * (float)i / (float)(NUM_SUBDIVISIONS - 1);
|
||||
for (int j = 0; j < NUM_SUBDIVISIONS; ++j)
|
||||
{
|
||||
float s = (EWAVE_NUM_HORIZONTAL_POINTS-1) * (float)j / (float)(NUM_SUBDIVISIONS - 1);
|
||||
int idx = i * NUM_SUBDIVISIONS + j;
|
||||
|
||||
ComputePoint( s, t, pt[idx], normal[idx], opacity[idx] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Draws the base ewave
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define TRANSITION_REGION_WIDTH 0.5f
|
||||
|
||||
void C_EnergyWave::DrawEWavePoints(Vector* pt, Vector* normal, float* opacity)
|
||||
{
|
||||
IMesh* pMesh = materials->GetDynamicMesh( true, NULL, NULL, m_pEWaveMat );
|
||||
|
||||
int numTriangles = (NUM_SUBDIVISIONS - 1) * (NUM_SUBDIVISIONS - 1) * 2;
|
||||
|
||||
CMeshBuilder meshBuilder;
|
||||
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, numTriangles );
|
||||
|
||||
float du = 1.0f / (float)(NUM_SUBDIVISIONS - 1);
|
||||
float dv = du;
|
||||
|
||||
unsigned char color[3];
|
||||
color[0] = 255;
|
||||
color[1] = 255;
|
||||
color[2] = 255;
|
||||
|
||||
for ( int i = 0; i < NUM_SUBDIVISIONS - 1; ++i)
|
||||
{
|
||||
float v = i * dv;
|
||||
for (int j = 0; j < NUM_SUBDIVISIONS - 1; ++j)
|
||||
{
|
||||
int idx = i * NUM_SUBDIVISIONS + j;
|
||||
float u = j * du;
|
||||
|
||||
meshBuilder.Position3fv( pt[idx].Base() );
|
||||
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx] );
|
||||
meshBuilder.Normal3fv( normal[idx].Base() );
|
||||
meshBuilder.TexCoord2f( 0, u, v );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Position3fv( pt[idx + NUM_SUBDIVISIONS].Base() );
|
||||
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+NUM_SUBDIVISIONS] );
|
||||
meshBuilder.Normal3fv( normal[idx + NUM_SUBDIVISIONS].Base() );
|
||||
meshBuilder.TexCoord2f( 0, u, v + dv );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Position3fv( pt[idx + 1].Base() );
|
||||
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+1] );
|
||||
meshBuilder.Normal3fv( normal[idx+1].Base() );
|
||||
meshBuilder.TexCoord2f( 0, u + du, v );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Position3fv( pt[idx + 1].Base() );
|
||||
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+1] );
|
||||
meshBuilder.Normal3fv( normal[idx+1].Base() );
|
||||
meshBuilder.TexCoord2f( 0, u + du, v );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Position3fv( pt[idx + NUM_SUBDIVISIONS].Base() );
|
||||
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+NUM_SUBDIVISIONS] );
|
||||
meshBuilder.Normal3fv( normal[idx + NUM_SUBDIVISIONS].Base() );
|
||||
meshBuilder.TexCoord2f( 0, u, v + dv );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Position3fv( pt[idx + NUM_SUBDIVISIONS + 1].Base() );
|
||||
meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+NUM_SUBDIVISIONS+1] );
|
||||
meshBuilder.Normal3fv( normal[idx + NUM_SUBDIVISIONS + 1].Base() );
|
||||
meshBuilder.TexCoord2f( 0, u + du, v + dv );
|
||||
meshBuilder.AdvanceVertex();
|
||||
}
|
||||
}
|
||||
|
||||
meshBuilder.End();
|
||||
pMesh->Draw();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main draw entry point
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int C_EnergyWave::DrawModel( int flags )
|
||||
{
|
||||
if ( !m_bReadyToDraw )
|
||||
return 0;
|
||||
|
||||
// NOTE: We've got a stiff spring case here, we need to simulate at
|
||||
// a fairly fast timestep. A better solution would be to use an
|
||||
// implicit method, which I'm going to not implement for the moment
|
||||
|
||||
float dt = gpGlobals->frametime;
|
||||
m_EWaveEffect.SetPosition( GetAbsOrigin(), GetAbsAngles() );
|
||||
m_EWaveEffect.Simulate(dt);
|
||||
|
||||
Vector pt[NUM_SUBDIVISIONS * NUM_SUBDIVISIONS];
|
||||
Vector normal[NUM_SUBDIVISIONS * NUM_SUBDIVISIONS];
|
||||
float opacity[NUM_SUBDIVISIONS * NUM_SUBDIVISIONS];
|
||||
|
||||
ComputeEWavePoints( pt, normal, opacity );
|
||||
|
||||
DrawEWavePoints( pt, normal, opacity );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
486
sp/src/game/client/hl2/c_env_alyxtemp.cpp
Normal file
486
sp/src/game/client/hl2/c_env_alyxtemp.cpp
Normal file
@@ -0,0 +1,486 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "particles_simple.h"
|
||||
#include "citadel_effects_shared.h"
|
||||
#include "particles_attractor.h"
|
||||
|
||||
class C_AlyxEmpEffect : public C_BaseEntity
|
||||
{
|
||||
DECLARE_CLASS( C_AlyxEmpEffect, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
public:
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
RenderGroup_t GetRenderGroup( void );
|
||||
|
||||
void ClientThink( void );
|
||||
void NotifyShouldTransmit( ShouldTransmitState_t state );
|
||||
|
||||
void UpdateIdle( float percentage );
|
||||
void UpdateCharging( float percentage );
|
||||
void UpdateDischarging( void );
|
||||
|
||||
private:
|
||||
|
||||
bool SetupEmitters( void );
|
||||
inline float GetStateDurationPercentage( void );
|
||||
|
||||
int m_nState;
|
||||
float m_flDuration;
|
||||
float m_flStartTime;
|
||||
TimedEvent m_tParticleSpawn;
|
||||
|
||||
CSmartPtr<CSimpleEmitter> m_pSimpleEmitter;
|
||||
CSmartPtr<CParticleAttractor> m_pAttractorEmitter;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_AlyxEmpEffect, DT_AlyxEmpEffect, CAlyxEmpEffect )
|
||||
RecvPropInt( RECVINFO(m_nState) ),
|
||||
RecvPropFloat( RECVINFO(m_flDuration) ),
|
||||
RecvPropFloat( RECVINFO(m_flStartTime) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : RenderGroup_t
|
||||
//-----------------------------------------------------------------------------
|
||||
RenderGroup_t C_AlyxEmpEffect::GetRenderGroup( void )
|
||||
{
|
||||
return RENDER_GROUP_TRANSLUCENT_ENTITY;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_AlyxEmpEffect::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
m_tParticleSpawn.Init( 32 );
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
SetupEmitters();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool C_AlyxEmpEffect::SetupEmitters( void )
|
||||
{
|
||||
// Setup the basic core emitter
|
||||
if ( m_pSimpleEmitter.IsValid() == false )
|
||||
{
|
||||
m_pSimpleEmitter = CSimpleEmitter::Create( "energycore" );
|
||||
|
||||
if ( m_pSimpleEmitter.IsValid() == false )
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup the attractor emitter
|
||||
if ( m_pAttractorEmitter.IsValid() == false )
|
||||
{
|
||||
m_pAttractorEmitter = CParticleAttractor::Create( GetAbsOrigin(), "energyattractor" );
|
||||
|
||||
if ( m_pAttractorEmitter.IsValid() == false )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define EMP_SCALE 0.5f
|
||||
|
||||
#define EMP_PARTICLES "effects/ar2_altfire1b"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : percentage -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_AlyxEmpEffect::UpdateIdle( float percentage )
|
||||
{
|
||||
#if 0
|
||||
|
||||
// Must be active
|
||||
if ( percentage >= 1.0f )
|
||||
return;
|
||||
|
||||
// Emitters must be valid
|
||||
if ( SetupEmitters() == false )
|
||||
return;
|
||||
|
||||
// Reset our sort origin
|
||||
m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
// Do the charging particles
|
||||
m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() );
|
||||
|
||||
Vector forward, right, up;
|
||||
AngleVectors( GetAbsAngles(), &forward, &right, &up );
|
||||
|
||||
Vector offset;
|
||||
float dist;
|
||||
|
||||
int numParticles = floor( 4.0f * percentage );
|
||||
|
||||
float dTime = gpGlobals->frametime;
|
||||
|
||||
while ( m_tParticleSpawn.NextEvent( dTime ) )
|
||||
{
|
||||
for ( int i = 0; i < numParticles; i++ )
|
||||
{
|
||||
dist = random->RandomFloat( 4.0f * EMP_SCALE * percentage, 64.0f * EMP_SCALE * percentage );
|
||||
|
||||
offset = forward * dist;
|
||||
|
||||
dist = RemapValClamped( dist, 4.0f * EMP_SCALE * percentage, 64.0f * EMP_SCALE * percentage, 6.0f, 1.0f );
|
||||
offset += right * random->RandomFloat( -4.0f * EMP_SCALE * dist, 4.0f * EMP_SCALE * dist );
|
||||
offset += up * random->RandomFloat( -4.0f * EMP_SCALE * dist, 4.0f * EMP_SCALE * dist );
|
||||
|
||||
offset += GetAbsOrigin();
|
||||
|
||||
sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( EMP_PARTICLES ), offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = Vector(0,0,8);
|
||||
sParticle->m_flDieTime = 0.5f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
|
||||
float alpha = 255 * percentage;
|
||||
|
||||
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_uchStartSize = random->RandomFloat( 1, 2 );
|
||||
sParticle->m_uchEndSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : percentage -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_AlyxEmpEffect::UpdateCharging( float percentage )
|
||||
{
|
||||
// Emitters must be valid
|
||||
if ( SetupEmitters() == false )
|
||||
return;
|
||||
|
||||
if ( percentage <= 0.0f )
|
||||
return;
|
||||
|
||||
// Reset our sort origin
|
||||
m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
float flScale = 4.0f * EMP_SCALE * percentage;
|
||||
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
float dTime = gpGlobals->frametime;
|
||||
|
||||
while ( m_tParticleSpawn.NextEvent( dTime ) )
|
||||
{
|
||||
// Do the core effects
|
||||
sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = vec3_origin;
|
||||
sParticle->m_flDieTime = 0.1f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
|
||||
float alpha = 255 * percentage;
|
||||
|
||||
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_uchStartSize = flScale;
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
// Do the charging particles
|
||||
m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() );
|
||||
|
||||
Vector forward, right, up;
|
||||
AngleVectors( GetAbsAngles(), &forward, &right, &up );
|
||||
|
||||
Vector offset;
|
||||
float dist;
|
||||
|
||||
int numParticles = floor( 4.0f * percentage );
|
||||
|
||||
for ( i = 0; i < numParticles; i++ )
|
||||
{
|
||||
dist = random->RandomFloat( 4.0f * percentage, 64.0f * percentage );
|
||||
|
||||
offset = forward * dist;
|
||||
|
||||
dist = RemapValClamped( dist, 4.0f * percentage, 64.0f * percentage, 6.0f, 1.0f );
|
||||
offset += right * random->RandomFloat( -4.0f * dist, 4.0f * dist );
|
||||
offset += up * random->RandomFloat( -4.0f * dist, 4.0f * dist );
|
||||
|
||||
offset += GetAbsOrigin();
|
||||
|
||||
sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( EMP_PARTICLES ), offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = Vector(0,0,8);
|
||||
sParticle->m_flDieTime = 0.5f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
|
||||
float alpha = 255 * percentage;
|
||||
|
||||
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_uchStartSize = random->RandomFloat( 1, 2 );
|
||||
sParticle->m_uchEndSize = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : percentage -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_AlyxEmpEffect::UpdateDischarging( void )
|
||||
{
|
||||
// Emitters must be valid
|
||||
if ( SetupEmitters() == false )
|
||||
return;
|
||||
|
||||
// Reset our sort origin
|
||||
m_pSimpleEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
float flScale = EMP_SCALE * 8.0f;
|
||||
|
||||
Vector forward, right, up;
|
||||
AngleVectors( GetAbsAngles(), &forward, &right, &up );
|
||||
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
float dTime = gpGlobals->frametime;
|
||||
|
||||
while ( m_tParticleSpawn.NextEvent( dTime ) )
|
||||
{
|
||||
// Base of the core effect
|
||||
sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = vec3_origin;
|
||||
sParticle->m_flDieTime = 0.25f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
|
||||
float alpha = 64;
|
||||
|
||||
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_uchStartSize = flScale * 4.0f;
|
||||
sParticle->m_uchEndSize = 0.0f;
|
||||
|
||||
// Base of the core effect
|
||||
sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = vec3_origin;
|
||||
sParticle->m_flDieTime = 0.1f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
|
||||
alpha = 128;
|
||||
|
||||
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_uchStartSize = 0.0f;
|
||||
sParticle->m_uchEndSize = flScale * 2.0f;
|
||||
|
||||
// Make sure we encompass the complete particle here!
|
||||
m_pSimpleEmitter->SetParticleCullRadius( sParticle->m_uchEndSize );
|
||||
|
||||
// Do the core effects
|
||||
sParticle = (SimpleParticle *) m_pSimpleEmitter->AddParticle( sizeof(SimpleParticle), m_pSimpleEmitter->GetPMaterial( EMP_PARTICLES ), GetAbsOrigin() );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = RandomVector( -32.0f, 32.0f );
|
||||
sParticle->m_flDieTime = 0.2f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
|
||||
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_uchStartSize = flScale;
|
||||
sParticle->m_uchEndSize = 0.0f;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
// Do the charging particles
|
||||
m_pAttractorEmitter->SetAttractorOrigin( GetAbsOrigin() );
|
||||
|
||||
Vector offset;
|
||||
float dist;
|
||||
|
||||
for ( i = 0; i < 4; i++ )
|
||||
{
|
||||
dist = random->RandomFloat( 4.0f, 64.0f );
|
||||
|
||||
offset = forward * dist;
|
||||
|
||||
dist = RemapValClamped( dist, 4.0f, 64.0f, 6.0f, 1.0f );
|
||||
offset += right * random->RandomFloat( -2.0f * dist, 2.0f * dist );
|
||||
offset += up * random->RandomFloat( -2.0f * dist, 2.0f * dist );
|
||||
|
||||
offset += GetAbsOrigin();
|
||||
|
||||
sParticle = (SimpleParticle *) m_pAttractorEmitter->AddParticle( sizeof(SimpleParticle), m_pAttractorEmitter->GetPMaterial( "effects/combinemuzzle2_dark" ), offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = Vector(0,0,2);
|
||||
sParticle->m_flDieTime = 0.5f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.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_uchStartSize = 1;
|
||||
sParticle->m_uchEndSize = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : inline float
|
||||
//-----------------------------------------------------------------------------
|
||||
inline float C_AlyxEmpEffect::GetStateDurationPercentage( void )
|
||||
{
|
||||
if ( m_flDuration == 0 )
|
||||
return 0.0f;
|
||||
|
||||
return RemapValClamped( ( gpGlobals->curtime - m_flStartTime ), 0, m_flDuration, 0, 1.0f );;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_AlyxEmpEffect::NotifyShouldTransmit( ShouldTransmitState_t state )
|
||||
{
|
||||
BaseClass::NotifyShouldTransmit( state );
|
||||
|
||||
// Turn off
|
||||
if ( state == SHOULDTRANSMIT_END )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||
}
|
||||
|
||||
// Turn on
|
||||
if ( state == SHOULDTRANSMIT_START )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_AlyxEmpEffect::ClientThink( void )
|
||||
{
|
||||
if ( gpGlobals->frametime <= 0.0f )
|
||||
return;
|
||||
|
||||
float flDuration = GetStateDurationPercentage();
|
||||
|
||||
switch( m_nState )
|
||||
{
|
||||
case ENERGYCORE_STATE_OFF:
|
||||
UpdateIdle( 1.0f - flDuration );
|
||||
break;
|
||||
|
||||
case ENERGYCORE_STATE_CHARGING:
|
||||
UpdateCharging( flDuration );
|
||||
break;
|
||||
|
||||
case ENERGYCORE_STATE_DISCHARGING:
|
||||
UpdateDischarging( );
|
||||
break;
|
||||
}
|
||||
}
|
||||
97
sp/src/game/client/hl2/c_env_headcrabcanister.cpp
Normal file
97
sp/src/game/client/hl2/c_env_headcrabcanister.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "fx_explosion.h"
|
||||
#include "tempentity.h"
|
||||
#include "c_tracer.h"
|
||||
#include "env_headcrabcanister_shared.h"
|
||||
#include "baseparticleentity.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Headcrab canister Class (Client-side only!)
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_EnvHeadcrabCanister : public C_BaseAnimating
|
||||
{
|
||||
DECLARE_CLASS( C_EnvHeadcrabCanister, C_BaseAnimating );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// Initialization/Destruction
|
||||
//-------------------------------------------------------------------------
|
||||
C_EnvHeadcrabCanister();
|
||||
~C_EnvHeadcrabCanister();
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual void ClientThink();
|
||||
|
||||
private:
|
||||
C_EnvHeadcrabCanister( const C_EnvHeadcrabCanister & );
|
||||
|
||||
CEnvHeadcrabCanisterShared m_Shared;
|
||||
CNetworkVar( bool, m_bLanded );
|
||||
};
|
||||
|
||||
|
||||
EXTERN_RECV_TABLE(DT_EnvHeadcrabCanisterShared);
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_EnvHeadcrabCanister, DT_EnvHeadcrabCanister, CEnvHeadcrabCanister )
|
||||
RecvPropDataTable( RECVINFO_DT( m_Shared ), 0, &REFERENCE_RECV_TABLE(DT_EnvHeadcrabCanisterShared) ),
|
||||
RecvPropBool( RECVINFO( m_bLanded ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_EnvHeadcrabCanister::C_EnvHeadcrabCanister()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_EnvHeadcrabCanister::~C_EnvHeadcrabCanister()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// On data update
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_EnvHeadcrabCanister::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
|
||||
// Stop client-side simulation on landing
|
||||
if ( m_bLanded )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compute position
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_EnvHeadcrabCanister::ClientThink()
|
||||
{
|
||||
Vector vecEndPosition;
|
||||
QAngle vecEndAngles;
|
||||
m_Shared.GetPositionAtTime( gpGlobals->curtime, vecEndPosition, vecEndAngles );
|
||||
SetAbsOrigin( vecEndPosition );
|
||||
SetAbsAngles( vecEndAngles );
|
||||
}
|
||||
|
||||
137
sp/src/game/client/hl2/c_env_starfield.cpp
Normal file
137
sp/src/game/client/hl2/c_env_starfield.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "engine/IEngineTrace.h"
|
||||
#include "fx_sparks.h"
|
||||
#include "particles_ez.h"
|
||||
#include "view.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
ConVar cl_starfield_diameter( "cl_starfield_diameter", "128.0", FCVAR_NONE );
|
||||
ConVar cl_starfield_distance( "cl_starfield_distance", "256.0", FCVAR_NONE );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_EnvStarfield : public C_BaseEntity
|
||||
{
|
||||
DECLARE_CLASS( C_EnvStarfield, C_BaseEntity );
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_EnvStarfield();
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual void ClientThink( void );
|
||||
|
||||
private:
|
||||
// Emitter
|
||||
CSmartPtr<CTrailParticles> m_pEmitter;
|
||||
bool m_bOn;
|
||||
float m_flDensity;
|
||||
float m_flNumParticles;
|
||||
|
||||
private:
|
||||
C_EnvStarfield( const C_EnvStarfield & );
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_EnvStarfield, DT_EnvStarfield, CEnvStarfield )
|
||||
RecvPropInt( RECVINFO(m_bOn) ),
|
||||
RecvPropFloat( RECVINFO(m_flDensity) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
// C_EnvStarfield
|
||||
// ------------------------------------------------------------------------- //
|
||||
C_EnvStarfield::C_EnvStarfield()
|
||||
{
|
||||
m_bOn = false;
|
||||
m_flDensity = 1.0;
|
||||
m_flNumParticles = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_EnvStarfield::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
m_pEmitter = CTrailParticles::Create( "EnvStarfield" );
|
||||
Vector vecCenter = MainViewOrigin() + (MainViewForward() * cl_starfield_distance.GetFloat() );
|
||||
m_pEmitter->Setup( (Vector &) vecCenter,
|
||||
NULL,
|
||||
0.0,
|
||||
0,
|
||||
64,
|
||||
0,
|
||||
0,
|
||||
bitsPARTICLE_TRAIL_VELOCITY_DAMPEN | bitsPARTICLE_TRAIL_FADE | bitsPARTICLE_TRAIL_FADE_IN );
|
||||
|
||||
// Start thinking
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_EnvStarfield::ClientThink( void )
|
||||
{
|
||||
if ( !m_bOn || !m_flDensity )
|
||||
return;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( engine->IsPaused() )
|
||||
return;
|
||||
#endif
|
||||
|
||||
PMaterialHandle hParticleMaterial = m_pEmitter->GetPMaterial( "effects/spark_noz" );
|
||||
|
||||
// Find a start & end point for the particle
|
||||
// Start particles straight ahead of the client
|
||||
Vector vecViewOrigin = MainViewOrigin();
|
||||
|
||||
// Determine the number of particles
|
||||
m_flNumParticles += 1.0 * (m_flDensity);
|
||||
int iNumParticles = floor(m_flNumParticles);
|
||||
m_flNumParticles -= iNumParticles;
|
||||
|
||||
// Add particles
|
||||
for ( int i = 0; i < iNumParticles; i++ )
|
||||
{
|
||||
float flDiameter = cl_starfield_diameter.GetFloat();
|
||||
|
||||
Vector vecStart = vecViewOrigin + (MainViewForward() * cl_starfield_distance.GetFloat() );
|
||||
Vector vecEnd = vecViewOrigin + (MainViewRight() * RandomFloat(-flDiameter,flDiameter)) + (MainViewUp() * RandomFloat(-flDiameter,flDiameter));
|
||||
Vector vecDir = (vecEnd - vecStart);
|
||||
float flDistance = VectorNormalize( vecDir );
|
||||
float flTravelTime = 2.0;
|
||||
|
||||
// Start a random amount along the path
|
||||
vecStart += vecDir * ( RandomFloat(0.1,0.3) * flDistance );
|
||||
|
||||
TrailParticle *pParticle = (TrailParticle *) m_pEmitter->AddParticle( sizeof(TrailParticle), hParticleMaterial, vecStart );
|
||||
if ( pParticle )
|
||||
{
|
||||
pParticle->m_vecVelocity = vecDir * (flDistance / flTravelTime);
|
||||
pParticle->m_flDieTime = flTravelTime;
|
||||
pParticle->m_flLifetime = 0;
|
||||
pParticle->m_flWidth = RandomFloat( 1, 3 );
|
||||
pParticle->m_flLength = RandomFloat( 0.05, 0.4 );
|
||||
pParticle->m_color.r = 255;
|
||||
pParticle->m_color.g = 255;
|
||||
pParticle->m_color.b = 255;
|
||||
pParticle->m_color.a = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
413
sp/src/game/client/hl2/c_extinguisher.cpp
Normal file
413
sp/src/game/client/hl2/c_extinguisher.cpp
Normal file
@@ -0,0 +1,413 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "particles_simple.h"
|
||||
#include "baseparticleentity.h"
|
||||
#include "iefx.h"
|
||||
#include "decals.h"
|
||||
#include "beamdraw.h"
|
||||
#include "hud.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
CLIENTEFFECT_REGISTER_BEGIN( PrecacheExtinguisher )
|
||||
CLIENTEFFECT_MATERIAL( "particle/particle_smokegrenade" )
|
||||
CLIENTEFFECT_REGISTER_END()
|
||||
|
||||
class C_ExtinguisherJet : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_CLASS( C_ExtinguisherJet, C_BaseEntity );
|
||||
|
||||
C_ExtinguisherJet();
|
||||
~C_ExtinguisherJet();
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
void Update( float fTimeDelta );
|
||||
void Start( void );
|
||||
int DrawModel( int flags );
|
||||
bool ShouldDraw( void ) { return m_bEmit; }
|
||||
|
||||
protected:
|
||||
|
||||
void AddExtinguisherDecal( trace_t &tr );
|
||||
|
||||
bool m_bEmit;
|
||||
bool m_bUseMuzzlePoint;
|
||||
int m_nLength;
|
||||
int m_nSize;
|
||||
|
||||
PMaterialHandle m_MaterialHandle;
|
||||
PMaterialHandle m_EmberMaterialHandle;
|
||||
TimedEvent m_ParticleSpawn;
|
||||
CSmartPtr<CSimpleEmitter> m_pEmitter;
|
||||
CSmartPtr<CEmberEffect> m_pEmberEmitter;
|
||||
|
||||
private:
|
||||
C_ExtinguisherJet( const C_ExtinguisherJet & );
|
||||
};
|
||||
|
||||
//Datatable
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ExtinguisherJet, DT_ExtinguisherJet, CExtinguisherJet )
|
||||
RecvPropInt(RECVINFO(m_bEmit), 0),
|
||||
RecvPropInt(RECVINFO(m_bUseMuzzlePoint), 0),
|
||||
RecvPropInt(RECVINFO(m_nLength), 0),
|
||||
RecvPropInt(RECVINFO(m_nSize), 0),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_ExtinguisherJet::C_ExtinguisherJet( void )
|
||||
{
|
||||
m_bEmit = false;
|
||||
|
||||
m_pEmitter = NULL;
|
||||
m_pEmberEmitter = NULL;
|
||||
}
|
||||
|
||||
C_ExtinguisherJet::~C_ExtinguisherJet( void )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : bnewentity -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ExtinguisherJet::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
C_BaseEntity::OnDataChanged(updateType);
|
||||
|
||||
if( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
Start();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ExtinguisherJet::Start( void )
|
||||
{
|
||||
AddToLeafSystem( RENDER_GROUP_TRANSLUCENT_ENTITY );
|
||||
|
||||
m_ParticleSpawn.Init( 100 ); //Events per second
|
||||
|
||||
//Create the basic emitter
|
||||
m_pEmitter = CSimpleEmitter::Create("C_ExtinguisherJet::m_pEmitter");
|
||||
|
||||
Assert( m_pEmitter.IsValid() );
|
||||
if ( m_pEmitter.IsValid() )
|
||||
{
|
||||
m_MaterialHandle = g_Mat_DustPuff[0];
|
||||
m_pEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
}
|
||||
|
||||
//Create the "ember" emitter for the smaller flecks
|
||||
m_pEmberEmitter = CEmberEffect::Create( "C_ExtinguisherJet::m_pEmberEmitter" );
|
||||
|
||||
Assert( m_pEmberEmitter.IsValid() );
|
||||
if ( m_pEmberEmitter.IsValid() )
|
||||
{
|
||||
m_EmberMaterialHandle = g_Mat_DustPuff[0];
|
||||
m_pEmberEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ExtinguisherJet::AddExtinguisherDecal( trace_t &tr )
|
||||
{
|
||||
C_BaseEntity *ent = cl_entitylist->GetEnt( 0 );
|
||||
|
||||
if ( ent != NULL )
|
||||
{
|
||||
int index = decalsystem->GetDecalIndexForName( "Extinguish" );
|
||||
if ( index >= 0 )
|
||||
{
|
||||
Vector endpos;
|
||||
endpos.Random( -24.0f, 24.0f );
|
||||
endpos += tr.endpos;
|
||||
|
||||
effects->DecalShoot( index, 0, ent->GetModel(), ent->GetAbsOrigin(), ent->GetAbsAngles(), endpos, 0, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : fTimeDelta -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ExtinguisherJet::Update( float fTimeDelta )
|
||||
{
|
||||
if ( m_bEmit == false )
|
||||
return;
|
||||
|
||||
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
|
||||
|
||||
if ( m_bUseMuzzlePoint )
|
||||
{
|
||||
C_BaseViewModel *vm = player ? player->GetViewModel( 0 ) : NULL;
|
||||
|
||||
if ( vm )
|
||||
{
|
||||
int iAttachment = vm->LookupAttachment( "muzzle" );
|
||||
Vector origin;
|
||||
QAngle angles;
|
||||
vm->GetAttachment( iAttachment, origin, angles );
|
||||
|
||||
Assert( !GetMoveParent() );
|
||||
SetLocalOrigin( origin );
|
||||
SetLocalAngles( angles );
|
||||
}
|
||||
}
|
||||
|
||||
trace_t tr;
|
||||
Vector shotDir, vRight, vUp;
|
||||
|
||||
AngleVectors( GetAbsAngles(), &shotDir, &vRight, &vUp );
|
||||
|
||||
//FIXME: Muzzle point is incorrect on the model!
|
||||
if ( m_bUseMuzzlePoint )
|
||||
{
|
||||
shotDir.Negate();
|
||||
}
|
||||
|
||||
Vector endPoint = GetAbsOrigin() + ( shotDir * 150.0f );
|
||||
|
||||
UTIL_TraceLine( GetAbsOrigin(), endPoint, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
bool hitWall = ( tr.fraction < 1.0f );
|
||||
|
||||
//Add normal jet
|
||||
if ( m_pEmitter.IsValid() )
|
||||
{
|
||||
SimpleParticle *pParticle;
|
||||
|
||||
m_pEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
float tempDelta = fTimeDelta;
|
||||
|
||||
//FIXME: All particles need to be within this loop
|
||||
while( m_ParticleSpawn.NextEvent( tempDelta ) )
|
||||
{
|
||||
pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, GetAbsOrigin() );
|
||||
|
||||
if ( pParticle )
|
||||
{
|
||||
pParticle->m_flDieTime = 0.2f;
|
||||
pParticle->m_flLifetime = 0.0f;
|
||||
|
||||
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
pParticle->m_flRollDelta= random->RandomFloat( -4.0f, 4.0f );
|
||||
|
||||
pParticle->m_uchStartSize = 1;
|
||||
pParticle->m_uchEndSize = random->RandomInt( 32, 48 );
|
||||
pParticle->m_uchStartAlpha = random->RandomInt( 128, 164 );
|
||||
pParticle->m_uchEndAlpha = 0;
|
||||
|
||||
int cScale = random->RandomInt( 192, 255 );
|
||||
pParticle->m_uchColor[0] = cScale;
|
||||
pParticle->m_uchColor[1] = cScale;
|
||||
pParticle->m_uchColor[2] = cScale;
|
||||
|
||||
Vector dir;
|
||||
QAngle ofsAngles;
|
||||
|
||||
ofsAngles.Random( -8.0f, 8.0f );
|
||||
ofsAngles += GetAbsAngles();
|
||||
|
||||
AngleVectors( ofsAngles, &dir );
|
||||
|
||||
if ( m_bUseMuzzlePoint )
|
||||
{
|
||||
dir.Negate();
|
||||
}
|
||||
|
||||
pParticle->m_vecVelocity = dir * random->RandomInt( 400, 800 );
|
||||
}
|
||||
|
||||
//Add muzzle effect
|
||||
pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, GetAbsOrigin() );
|
||||
|
||||
if ( pParticle )
|
||||
{
|
||||
pParticle->m_flDieTime = 0.1f;
|
||||
pParticle->m_flLifetime = 0.0f;
|
||||
|
||||
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
pParticle->m_flRollDelta= random->RandomFloat( -4.0f, 4.0f );
|
||||
|
||||
pParticle->m_uchStartSize = 1;
|
||||
pParticle->m_uchEndSize = random->RandomInt( 8, 16 );
|
||||
pParticle->m_uchStartAlpha = random->RandomInt( 128, 255 );
|
||||
pParticle->m_uchEndAlpha = 0;
|
||||
|
||||
int cScale = random->RandomInt( 192, 255 );
|
||||
pParticle->m_uchColor[0] = cScale;
|
||||
pParticle->m_uchColor[1] = cScale;
|
||||
pParticle->m_uchColor[2] = cScale;
|
||||
|
||||
Vector dir;
|
||||
QAngle ofsAngles;
|
||||
|
||||
ofsAngles.Random( -64.0f, 64.0f );
|
||||
ofsAngles += GetAbsAngles();
|
||||
|
||||
AngleVectors( ofsAngles, &dir );
|
||||
|
||||
if ( m_bUseMuzzlePoint )
|
||||
{
|
||||
dir.Negate();
|
||||
}
|
||||
|
||||
pParticle->m_vecVelocity = dir * random->RandomInt( 32, 64 );
|
||||
}
|
||||
|
||||
//Add a wall effect if needed
|
||||
if ( hitWall )
|
||||
{
|
||||
AddExtinguisherDecal( tr );
|
||||
|
||||
Vector offDir;
|
||||
|
||||
offDir.Random( -16.0f, 16.0f );
|
||||
|
||||
pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, ( tr.endpos + ( tr.plane.normal * 8.0f ) ) + offDir );
|
||||
|
||||
if ( pParticle )
|
||||
{
|
||||
pParticle->m_flDieTime = 0.4f;
|
||||
pParticle->m_flLifetime = 0.0f;
|
||||
|
||||
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
pParticle->m_flRollDelta= random->RandomFloat( -2.0f, 2.0f );
|
||||
|
||||
pParticle->m_uchStartSize = random->RandomInt( 8, 16 );
|
||||
pParticle->m_uchEndSize = random->RandomInt( 24, 32 );
|
||||
pParticle->m_uchStartAlpha = random->RandomInt( 64, 128 );
|
||||
pParticle->m_uchEndAlpha = 0;
|
||||
|
||||
int cScale = random->RandomInt( 192, 255 );
|
||||
pParticle->m_uchColor[0] = cScale;
|
||||
pParticle->m_uchColor[1] = cScale;
|
||||
pParticle->m_uchColor[2] = cScale;
|
||||
|
||||
Vector rDir;
|
||||
|
||||
rDir = tr.plane.normal;
|
||||
rDir[0] += random->RandomFloat( -0.9f, 0.9f );
|
||||
rDir[1] += random->RandomFloat( -0.9f, 0.9f );
|
||||
rDir[2] += random->RandomFloat( -0.9f, 0.9f );
|
||||
|
||||
pParticle->m_vecVelocity = rDir * random->RandomInt( 32, 64 );
|
||||
}
|
||||
}
|
||||
|
||||
//Add small ember-like particles
|
||||
if ( random->RandomInt( 0, 1 ) == 0 )
|
||||
{
|
||||
m_pEmberEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
pParticle = (SimpleParticle *) m_pEmberEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[0], GetAbsOrigin() );
|
||||
|
||||
assert(pParticle);
|
||||
|
||||
if ( pParticle )
|
||||
{
|
||||
pParticle->m_flLifetime = 0.0f;
|
||||
pParticle->m_flDieTime = 1.0f;
|
||||
|
||||
pParticle->m_flRoll = 0;
|
||||
pParticle->m_flRollDelta = 0;
|
||||
|
||||
pParticle->m_uchColor[0] = 255;
|
||||
pParticle->m_uchColor[1] = 255;
|
||||
pParticle->m_uchColor[2] = 255;
|
||||
pParticle->m_uchStartAlpha = 255;
|
||||
pParticle->m_uchEndAlpha = 0;
|
||||
pParticle->m_uchStartSize = 1;
|
||||
pParticle->m_uchEndSize = 0;
|
||||
|
||||
Vector dir;
|
||||
QAngle ofsAngles;
|
||||
|
||||
ofsAngles.Random( -8.0f, 8.0f );
|
||||
ofsAngles += GetAbsAngles();
|
||||
|
||||
AngleVectors( ofsAngles, &dir );
|
||||
|
||||
if ( m_bUseMuzzlePoint )
|
||||
{
|
||||
dir.Negate();
|
||||
}
|
||||
|
||||
pParticle->m_vecVelocity = dir * random->RandomInt( 400, 800 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inner beam
|
||||
|
||||
CBeamSegDraw beamDraw;
|
||||
CBeamSeg seg;
|
||||
const int numPoints = 4;
|
||||
Vector beamPoints[numPoints];
|
||||
|
||||
beamPoints[0] = GetAbsOrigin();
|
||||
|
||||
// Create our beam points
|
||||
int i;
|
||||
for ( i = 0; i < numPoints; i++ )
|
||||
{
|
||||
beamPoints[i] = GetAbsOrigin() + ( shotDir * (32*i*i) );
|
||||
|
||||
beamPoints[i] += vRight * sin( gpGlobals->curtime * 4.0f ) * (2.0f*i);
|
||||
beamPoints[i] += vUp * sin( gpGlobals->curtime * 8.0f ) * (1.0f*i);
|
||||
beamPoints[i] += shotDir * sin( gpGlobals->curtime * (16.0f*i) ) * (1.0f*i);
|
||||
}
|
||||
|
||||
IMaterial *pMat = materials->FindMaterial( "particle/particle_smokegrenade", TEXTURE_GROUP_PARTICLE );
|
||||
|
||||
beamDraw.Start( numPoints, pMat );
|
||||
|
||||
//Setup and draw those points
|
||||
for( i = 0; i < numPoints; i++ )
|
||||
{
|
||||
float t = (float) i / (numPoints - 1);
|
||||
float color = 1.0f * (1.0f - t);
|
||||
|
||||
seg.m_vColor = Vector( color, color, color );
|
||||
seg.m_vPos = beamPoints[i];
|
||||
seg.m_flTexCoord = (float)i/(float)(numPoints-1) - ((gpGlobals->curtime - (int)gpGlobals->curtime) * 4.0f );
|
||||
seg.m_flWidth = 4.0f + ( (64.0f*t) * (fabs( sin( gpGlobals->curtime * 16.0f ) )) );
|
||||
seg.m_flAlpha = color;
|
||||
|
||||
beamDraw.NextSeg( &seg );
|
||||
}
|
||||
|
||||
beamDraw.End();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flags -
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_ExtinguisherJet::DrawModel( int flags )
|
||||
{
|
||||
if ( m_bEmit == false )
|
||||
return 1;
|
||||
|
||||
Update( Helper_GetFrameTime() );
|
||||
|
||||
return 1;
|
||||
}
|
||||
249
sp/src/game/client/hl2/c_func_tankmortar.cpp
Normal file
249
sp/src/game/client/hl2/c_func_tankmortar.cpp
Normal file
@@ -0,0 +1,249 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "fx_quad.h"
|
||||
#include "fx.h"
|
||||
|
||||
class C_MortarShell : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
|
||||
DECLARE_CLASS( C_MortarShell, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
int DrawModel( int flags );
|
||||
|
||||
RenderGroup_t GetRenderGroup( void ) { return RENDER_GROUP_TRANSLUCENT_ENTITY; }
|
||||
|
||||
private:
|
||||
|
||||
void AddRisingParticles( float flPerc );
|
||||
void AddExplodingParticles( float flPerc );
|
||||
|
||||
inline float GetStartPerc( void );
|
||||
inline float GetEndPerc( void );
|
||||
|
||||
CSmartPtr<CSimpleEmitter> m_pEmitter;
|
||||
TimedEvent m_ParticleEvent;
|
||||
|
||||
float m_flLifespan;
|
||||
float m_flRadius;
|
||||
float m_flStarttime;
|
||||
Vector m_vecSurfaceNormal;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_MortarShell, DT_MortarShell, CMortarShell )
|
||||
RecvPropFloat( RECVINFO( m_flLifespan ) ),
|
||||
RecvPropFloat( RECVINFO( m_flRadius ) ),
|
||||
RecvPropVector( RECVINFO( m_vecSurfaceNormal ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_MortarShell::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
m_flStarttime = gpGlobals->curtime;
|
||||
AddToLeafSystem( RENDER_GROUP_TRANSLUCENT_ENTITY );
|
||||
|
||||
m_pEmitter = CSimpleEmitter::Create( "C_EntityDissolve" );
|
||||
m_pEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
m_ParticleEvent.Init( 128 );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flPerc -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_MortarShell::AddRisingParticles( float flPerc )
|
||||
{
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
Vector offset;
|
||||
float radius = m_flRadius * 0.25f * flPerc;
|
||||
|
||||
float val = RemapValClamped( gpGlobals->curtime, m_flStarttime, m_flStarttime + m_flLifespan, 0.0f, 1.0f );
|
||||
|
||||
float flCur = gpGlobals->frametime;
|
||||
|
||||
// Anime ground effects
|
||||
while ( m_ParticleEvent.NextEvent( flCur ) )
|
||||
{
|
||||
offset.x = random->RandomFloat( -radius, radius );
|
||||
offset.y = random->RandomFloat( -radius, radius );
|
||||
offset.z = random->RandomFloat( -8.0f, 8.0f );
|
||||
|
||||
offset += GetAbsOrigin();
|
||||
|
||||
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/spark" ), offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( 32.0f, 256.0f ) * Bias( val, 0.25f ) );
|
||||
|
||||
sParticle->m_uchStartSize = random->RandomFloat( 4, 8 ) * flPerc;
|
||||
|
||||
sParticle->m_flDieTime = random->RandomFloat( 0.5f, 1.0f );
|
||||
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
|
||||
float alpha = 255 * flPerc;
|
||||
|
||||
sParticle->m_flRollDelta = Helper_RandomFloat( -8.0f * flPerc, 8.0f * flPerc );
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flPerc -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_MortarShell::AddExplodingParticles( float flPerc )
|
||||
{
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
Vector offset;
|
||||
float radius = 48.0f * flPerc;
|
||||
|
||||
float flCur = gpGlobals->frametime;
|
||||
|
||||
// Anime ground effects
|
||||
while ( m_ParticleEvent.NextEvent( flCur ) )
|
||||
{
|
||||
offset.x = random->RandomFloat( -radius, radius );
|
||||
offset.y = random->RandomFloat( -radius, radius );
|
||||
offset.z = random->RandomFloat( -8.0f, 8.0f );
|
||||
|
||||
offset += GetAbsOrigin();
|
||||
|
||||
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/spark" ), offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_vecVelocity = RandomVector( -1.0f, 1.0f ) + Vector( 0, 0, 1 );
|
||||
sParticle->m_vecVelocity *= ( 750.0f * flPerc );
|
||||
|
||||
sParticle->m_uchStartSize = random->RandomFloat( 2, 4 ) * flPerc;
|
||||
|
||||
sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
|
||||
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
|
||||
float alpha = 255 * flPerc;
|
||||
|
||||
sParticle->m_flRollDelta = Helper_RandomFloat( -8.0f * flPerc, 8.0f * flPerc );
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : inline float
|
||||
//-----------------------------------------------------------------------------
|
||||
inline float C_MortarShell::GetStartPerc( void )
|
||||
{
|
||||
float val = RemapValClamped( gpGlobals->curtime, m_flStarttime, m_flStarttime + m_flLifespan, 0.0f, 1.0f );
|
||||
|
||||
return ( Gain( val, 0.2f ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : inline float
|
||||
//-----------------------------------------------------------------------------
|
||||
inline float C_MortarShell::GetEndPerc( void )
|
||||
{
|
||||
float val = RemapValClamped( gpGlobals->curtime, m_flStarttime + m_flLifespan, m_flStarttime + m_flLifespan + 1.0f, 1.0f, 0.0f );
|
||||
|
||||
return ( Gain( val, 0.75f ) );
|
||||
}
|
||||
|
||||
#define ALPHA_MIN 0.0f
|
||||
#define ALPHA_MAX 1.0f
|
||||
|
||||
#define SCALE_MIN 8
|
||||
#define SCALE_MAX 200
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_MortarShell::DrawModel( int flags )
|
||||
{
|
||||
if ( gpGlobals->frametime <= 0.0f )
|
||||
return 0;
|
||||
|
||||
float flPerc;
|
||||
bool ending;
|
||||
|
||||
// See if we're in the beginning phase
|
||||
if ( gpGlobals->curtime < ( m_flStarttime + m_flLifespan ) )
|
||||
{
|
||||
flPerc = GetStartPerc();
|
||||
ending = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
flPerc = GetEndPerc();
|
||||
ending = true;
|
||||
}
|
||||
|
||||
float flAlpha = ALPHA_MIN + ( ( ALPHA_MAX - ALPHA_MIN ) * flPerc );
|
||||
float flScale = ( ending ) ? m_flRadius : ( (m_flRadius*0.1f)+ ( ( m_flRadius - (m_flRadius*0.1f) ) * flPerc ) );
|
||||
|
||||
// Do the ground effect
|
||||
FX_AddQuad( GetAbsOrigin() + ( m_vecSurfaceNormal * 2.0f ),
|
||||
m_vecSurfaceNormal,
|
||||
flScale,
|
||||
flScale,
|
||||
1.0f,
|
||||
flAlpha,
|
||||
flAlpha,
|
||||
1.0f,
|
||||
0,
|
||||
0,
|
||||
Vector( 1.0f, 1.0f, 1.0f ),
|
||||
0.0001f,
|
||||
"effects/combinemuzzle2_nocull",
|
||||
0 );
|
||||
|
||||
if ( !ending )
|
||||
{
|
||||
// Add extra effects on startup
|
||||
AddRisingParticles( flPerc );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add exploding particles after the impact
|
||||
AddExplodingParticles( flPerc );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
52
sp/src/game/client/hl2/c_hl2_playerlocaldata.cpp
Normal file
52
sp/src/game/client/hl2/c_hl2_playerlocaldata.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "c_hl2_playerlocaldata.h"
|
||||
#include "dt_recv.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
BEGIN_RECV_TABLE_NOBASE( C_HL2PlayerLocalData, DT_HL2Local )
|
||||
RecvPropFloat( RECVINFO(m_flSuitPower) ),
|
||||
RecvPropInt( RECVINFO(m_bZooming) ),
|
||||
RecvPropInt( RECVINFO(m_bitsActiveDevices) ),
|
||||
RecvPropInt( RECVINFO(m_iSquadMemberCount) ),
|
||||
RecvPropInt( RECVINFO(m_iSquadMedicCount) ),
|
||||
RecvPropBool( RECVINFO(m_fSquadInFollowMode) ),
|
||||
RecvPropBool( RECVINFO(m_bWeaponLowered) ),
|
||||
RecvPropEHandle( RECVINFO(m_hAutoAimTarget) ),
|
||||
RecvPropVector( RECVINFO(m_vecAutoAimPoint) ),
|
||||
RecvPropEHandle( RECVINFO(m_hLadder) ),
|
||||
RecvPropBool( RECVINFO(m_bDisplayReticle) ),
|
||||
RecvPropBool( RECVINFO(m_bStickyAutoAim) ),
|
||||
RecvPropBool( RECVINFO(m_bAutoAimTarget) ),
|
||||
#ifdef HL2_EPISODIC
|
||||
RecvPropFloat( RECVINFO(m_flFlashBattery) ),
|
||||
RecvPropVector( RECVINFO(m_vecLocatorOrigin) ),
|
||||
#endif
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA_NO_BASE( C_HL2PlayerLocalData )
|
||||
DEFINE_PRED_FIELD( m_hLadder, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
C_HL2PlayerLocalData::C_HL2PlayerLocalData()
|
||||
{
|
||||
m_flSuitPower = 0.0;
|
||||
m_bZooming = false;
|
||||
m_iSquadMemberCount = 0;
|
||||
m_iSquadMedicCount = 0;
|
||||
m_fSquadInFollowMode = false;
|
||||
m_bWeaponLowered = false;
|
||||
m_hLadder = NULL;
|
||||
#ifdef HL2_EPISODIC
|
||||
m_flFlashBattery = 0.0f;
|
||||
m_vecLocatorOrigin = vec3_origin;
|
||||
#endif
|
||||
}
|
||||
|
||||
55
sp/src/game/client/hl2/c_hl2_playerlocaldata.h
Normal file
55
sp/src/game/client/hl2/c_hl2_playerlocaldata.h
Normal file
@@ -0,0 +1,55 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#if !defined( C_HL2_PLAYERLOCALDATA_H )
|
||||
#define C_HL2_PLAYERLOCALDATA_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "dt_recv.h"
|
||||
|
||||
#include "hl2/hl_movedata.h"
|
||||
|
||||
EXTERN_RECV_TABLE( DT_HL2Local );
|
||||
|
||||
|
||||
class C_HL2PlayerLocalData
|
||||
{
|
||||
public:
|
||||
DECLARE_PREDICTABLE();
|
||||
DECLARE_CLASS_NOBASE( C_HL2PlayerLocalData );
|
||||
DECLARE_EMBEDDED_NETWORKVAR();
|
||||
|
||||
C_HL2PlayerLocalData();
|
||||
|
||||
float m_flSuitPower;
|
||||
bool m_bZooming;
|
||||
int m_bitsActiveDevices;
|
||||
int m_iSquadMemberCount;
|
||||
int m_iSquadMedicCount;
|
||||
bool m_fSquadInFollowMode;
|
||||
bool m_bWeaponLowered;
|
||||
EHANDLE m_hAutoAimTarget;
|
||||
Vector m_vecAutoAimPoint;
|
||||
bool m_bDisplayReticle;
|
||||
bool m_bStickyAutoAim;
|
||||
bool m_bAutoAimTarget;
|
||||
#ifdef HL2_EPISODIC
|
||||
float m_flFlashBattery;
|
||||
Vector m_vecLocatorOrigin;
|
||||
#endif
|
||||
|
||||
// Ladder related data
|
||||
EHANDLE m_hLadder;
|
||||
LadderMove_t m_LadderMove;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
194
sp/src/game/client/hl2/c_info_teleporter_countdown.cpp
Normal file
194
sp/src/game/client/hl2/c_info_teleporter_countdown.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
|
||||
#include "c_vguiscreen.h"
|
||||
#include <vgui/IVGui.h>
|
||||
#include <vgui_controls/Controls.h>
|
||||
#include <vgui_controls/Label.h>
|
||||
#include "clientmode_hlnormal.h"
|
||||
#include "tier1/utllinkedlist.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Amount of time before breen teleports away
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_InfoTeleporterCountdown : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_InfoTeleporterCountdown, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
public:
|
||||
C_InfoTeleporterCountdown();
|
||||
~C_InfoTeleporterCountdown();
|
||||
|
||||
virtual bool ShouldDraw() { return false; }
|
||||
|
||||
private:
|
||||
bool m_bCountdownStarted;
|
||||
bool m_bDisabled;
|
||||
float m_flStartTime;
|
||||
float m_flTimeRemaining;
|
||||
|
||||
friend class CTeleportCountdownScreen;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Global list of teleporters
|
||||
//-----------------------------------------------------------------------------
|
||||
CUtlFixedLinkedList<C_InfoTeleporterCountdown *> g_InfoTeleporterCountdownList;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Networking
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_InfoTeleporterCountdown, DT_InfoTeleporterCountdown, CInfoTeleporterCountdown )
|
||||
RecvPropInt( RECVINFO( m_bCountdownStarted ) ),
|
||||
RecvPropInt( RECVINFO( m_bDisabled ) ),
|
||||
RecvPropTime( RECVINFO( m_flStartTime ) ),
|
||||
RecvPropFloat( RECVINFO( m_flTimeRemaining ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_InfoTeleporterCountdown::C_InfoTeleporterCountdown()
|
||||
{
|
||||
g_InfoTeleporterCountdownList.AddToTail( this );
|
||||
}
|
||||
|
||||
C_InfoTeleporterCountdown::~C_InfoTeleporterCountdown()
|
||||
{
|
||||
g_InfoTeleporterCountdownList.FindAndRemove( this );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// In-game vgui panel which shows the teleporter countdown
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTeleportCountdownScreen : public CVGuiScreenPanel
|
||||
{
|
||||
DECLARE_CLASS( CTeleportCountdownScreen, CVGuiScreenPanel );
|
||||
|
||||
public:
|
||||
CTeleportCountdownScreen( vgui::Panel *parent, const char *panelName );
|
||||
|
||||
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
|
||||
virtual void OnTick();
|
||||
|
||||
private:
|
||||
vgui::Label *m_pTimeRemainingTitleLabel;
|
||||
vgui::Label *m_pTimeRemainingLabel;
|
||||
vgui::Label *m_pMalfunctionLabel;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Standard VGUI panel for objects
|
||||
//-----------------------------------------------------------------------------
|
||||
DECLARE_VGUI_SCREEN_FACTORY( CTeleportCountdownScreen, "teleport_countdown_screen" );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor:
|
||||
//-----------------------------------------------------------------------------
|
||||
CTeleportCountdownScreen::CTeleportCountdownScreen( vgui::Panel *parent, const char *panelName )
|
||||
: BaseClass( parent, panelName, g_hVGuiCombineScheme )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Initialization
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTeleportCountdownScreen::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
|
||||
{
|
||||
// Load all of the controls in
|
||||
if ( !BaseClass::Init(pKeyValues, pInitData) )
|
||||
return false;
|
||||
|
||||
// Make sure we get ticked...
|
||||
vgui::ivgui()->AddTickSignal( GetVPanel() );
|
||||
|
||||
// Grab ahold of certain well-known controls
|
||||
// NOTE: it is valid for these controls to not exist!
|
||||
m_pTimeRemainingTitleLabel = dynamic_cast<vgui::Label*>(FindChildByName( "TimeRemainingTitle" ));
|
||||
m_pTimeRemainingLabel = dynamic_cast<vgui::Label*>(FindChildByName( "TimeRemaining" ));
|
||||
m_pMalfunctionLabel = dynamic_cast<vgui::Label*>( FindChildByName( "MalfunctionLabel" ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Frame-based update
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTeleportCountdownScreen::OnTick()
|
||||
{
|
||||
BaseClass::OnTick();
|
||||
|
||||
// Find the active info teleporter countdown
|
||||
C_InfoTeleporterCountdown *pActiveCountdown = NULL;
|
||||
for ( int i = g_InfoTeleporterCountdownList.Head(); i != g_InfoTeleporterCountdownList.InvalidIndex();
|
||||
i = g_InfoTeleporterCountdownList.Next(i) )
|
||||
{
|
||||
if ( g_InfoTeleporterCountdownList[i]->m_bCountdownStarted )
|
||||
{
|
||||
pActiveCountdown = g_InfoTeleporterCountdownList[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !GetEntity() || !pActiveCountdown )
|
||||
{
|
||||
m_pTimeRemainingTitleLabel->SetVisible( false );
|
||||
m_pTimeRemainingLabel->SetVisible( false );
|
||||
m_pMalfunctionLabel->SetVisible( false );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Make the appropriate labels visible
|
||||
bool bMalfunction = pActiveCountdown->m_bDisabled;
|
||||
m_pTimeRemainingTitleLabel->SetVisible( !bMalfunction );
|
||||
m_pTimeRemainingLabel->SetVisible( !bMalfunction );
|
||||
|
||||
// This will make it flash
|
||||
m_pMalfunctionLabel->SetVisible( bMalfunction && (((int)(gpGlobals->curtime) & 0x1) == 0x1) );
|
||||
|
||||
// Update the time remaining
|
||||
if ( !bMalfunction )
|
||||
{
|
||||
char buf[32];
|
||||
if (m_pTimeRemainingLabel)
|
||||
{
|
||||
float dt = gpGlobals->curtime - pActiveCountdown->m_flStartTime;
|
||||
if ( dt < 0.0f )
|
||||
{
|
||||
dt = 0.0f;
|
||||
}
|
||||
|
||||
int nTimeRemaining = (int)(pActiveCountdown->m_flTimeRemaining - dt + 0.5f);
|
||||
if ( nTimeRemaining < 0 )
|
||||
{
|
||||
nTimeRemaining = 0;
|
||||
}
|
||||
|
||||
Q_snprintf( buf, sizeof( buf ), "%d", nTimeRemaining );
|
||||
m_pTimeRemainingLabel->SetText( buf );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
160
sp/src/game/client/hl2/c_npc_antlionguard.cpp
Normal file
160
sp/src/game/client/hl2/c_npc_antlionguard.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Client side antlion guard. Used to create dlight for the cave guard.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_ai_basenpc.h"
|
||||
#include "dlight.h"
|
||||
#include "iefx.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
#if HL2_EPISODIC
|
||||
// When enabled, add code to have the antlion bleed profusely as it is badly injured.
|
||||
#define ANTLIONGUARD_BLOOD_EFFECTS 2
|
||||
#endif
|
||||
|
||||
|
||||
class C_NPC_AntlionGuard : public C_AI_BaseNPC
|
||||
{
|
||||
public:
|
||||
C_NPC_AntlionGuard() {}
|
||||
|
||||
DECLARE_CLASS( C_NPC_AntlionGuard, C_AI_BaseNPC );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t type );
|
||||
virtual void ClientThink();
|
||||
|
||||
private:
|
||||
|
||||
bool m_bCavernBreed;
|
||||
bool m_bInCavern;
|
||||
dlight_t *m_dlight;
|
||||
|
||||
#if HL2_EPISODIC
|
||||
unsigned char m_iBleedingLevel; //< the version coming from the server
|
||||
unsigned char m_iPerformingBleedingLevel; //< the version we're currently performing (for comparison to one above)
|
||||
CNewParticleEffect *m_pBleedingFX;
|
||||
|
||||
/// update the hemorrhage particle effect
|
||||
virtual void UpdateBleedingPerformance( void );
|
||||
#endif
|
||||
|
||||
C_NPC_AntlionGuard( const C_NPC_AntlionGuard & );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save/restore
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC( C_NPC_AntlionGuard )
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Networking
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_NPC_AntlionGuard, DT_NPC_AntlionGuard, CNPC_AntlionGuard)
|
||||
RecvPropBool( RECVINFO( m_bCavernBreed ) ),
|
||||
RecvPropBool( RECVINFO( m_bInCavern ) ),
|
||||
|
||||
#if ANTLIONGUARD_BLOOD_EFFECTS
|
||||
RecvPropInt( RECVINFO( m_iBleedingLevel ) ),
|
||||
#endif
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_AntlionGuard::OnDataChanged( DataUpdateType_t type )
|
||||
{
|
||||
BaseClass::OnDataChanged( type );
|
||||
|
||||
if ( (type == DATA_UPDATE_CREATED) && m_bCavernBreed && m_bInCavern )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
|
||||
|
||||
#if HL2_EPISODIC
|
||||
if (m_iBleedingLevel != m_iPerformingBleedingLevel)
|
||||
{
|
||||
UpdateBleedingPerformance();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if HL2_EPISODIC
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_AntlionGuard::UpdateBleedingPerformance()
|
||||
{
|
||||
// get my particles
|
||||
CParticleProperty * pProp = ParticleProp();
|
||||
|
||||
// squelch the prior effect if it exists
|
||||
if (m_pBleedingFX)
|
||||
{
|
||||
pProp->StopEmission(m_pBleedingFX);
|
||||
m_pBleedingFX = NULL;
|
||||
}
|
||||
|
||||
// kick off a new effect
|
||||
switch (m_iBleedingLevel)
|
||||
{
|
||||
case 1: // light bleeding
|
||||
{
|
||||
m_pBleedingFX = pProp->Create( "blood_antlionguard_injured_light", PATTACH_ABSORIGIN_FOLLOW );
|
||||
AssertMsg1( m_pBleedingFX, "Particle system couldn't make %s", "blood_antlionguard_injured_light" );
|
||||
if ( m_pBleedingFX )
|
||||
{
|
||||
pProp->AddControlPoint( m_pBleedingFX, 1, this, PATTACH_ABSORIGIN_FOLLOW );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // severe bleeding
|
||||
{
|
||||
m_pBleedingFX = pProp->Create( "blood_antlionguard_injured_heavy", PATTACH_ABSORIGIN_FOLLOW );
|
||||
AssertMsg1( m_pBleedingFX, "Particle system couldn't make %s", "blood_antlionguard_injured_heavy" );
|
||||
if ( m_pBleedingFX )
|
||||
{
|
||||
pProp->AddControlPoint( m_pBleedingFX, 1, this, PATTACH_ABSORIGIN_FOLLOW );
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_iPerformingBleedingLevel = m_iBleedingLevel;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_AntlionGuard::ClientThink()
|
||||
{
|
||||
// update the dlight. (always done because clienthink only exists for cavernguard)
|
||||
if (!m_dlight)
|
||||
{
|
||||
m_dlight = effects->CL_AllocDlight( index );
|
||||
m_dlight->color.r = 220;
|
||||
m_dlight->color.g = 255;
|
||||
m_dlight->color.b = 80;
|
||||
m_dlight->radius = 180;
|
||||
m_dlight->minlight = 128.0 / 256.0f;
|
||||
m_dlight->flags = DLIGHT_NO_MODEL_ILLUMINATION;
|
||||
}
|
||||
|
||||
m_dlight->origin = GetAbsOrigin();
|
||||
// dl->die = gpGlobals->curtime + 0.1f;
|
||||
|
||||
BaseClass::ClientThink();
|
||||
}
|
||||
476
sp/src/game/client/hl2/c_npc_combinegunship.cpp
Normal file
476
sp/src/game/client/hl2/c_npc_combinegunship.cpp
Normal file
@@ -0,0 +1,476 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_basehelicopter.h"
|
||||
#include "fx_impact.h"
|
||||
#include "IEffects.h"
|
||||
#include "simple_keys.h"
|
||||
#include "fx_envelope.h"
|
||||
#include "fx_line.h"
|
||||
#include "iefx.h"
|
||||
#include "dlight.h"
|
||||
#include "c_sprite.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
#include <bitbuf.h>
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define GUNSHIP_MSG_BIG_SHOT 1
|
||||
#define GUNSHIP_MSG_STREAKS 2
|
||||
#define GUNSHIP_MSG_DEAD 3
|
||||
|
||||
#define GUNSHIPFX_BIG_SHOT_TIME 3.0f
|
||||
|
||||
CLIENTEFFECT_REGISTER_BEGIN( PrecacheGunshipFX )
|
||||
CLIENTEFFECT_MATERIAL( "sprites/bluelaser1" )
|
||||
CLIENTEFFECT_REGISTER_END()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Big belly shot FX
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class C_GunshipFX : public C_EnvelopeFX
|
||||
{
|
||||
public:
|
||||
typedef C_EnvelopeFX BaseClass;
|
||||
|
||||
C_GunshipFX();
|
||||
void Update( C_BaseEntity *pOwner, const Vector &targetPos );
|
||||
|
||||
// Returns the bounds relative to the origin (render bounds)
|
||||
virtual void GetRenderBounds( Vector& mins, Vector& maxs )
|
||||
{
|
||||
ClearBounds( mins, maxs );
|
||||
AddPointToBounds( m_worldPosition, mins, maxs );
|
||||
AddPointToBounds( m_targetPosition, mins, maxs );
|
||||
mins -= GetRenderOrigin();
|
||||
maxs -= GetRenderOrigin();
|
||||
}
|
||||
|
||||
virtual int DrawModel( int flags );
|
||||
|
||||
C_BaseEntity *m_pOwner;
|
||||
Vector m_targetPosition;
|
||||
Vector m_beamEndPosition;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_GunshipFX::C_GunshipFX( void )
|
||||
{
|
||||
m_pOwner = NULL;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
GUNSHIPFX_WARP_SCALE = 0,
|
||||
GUNSHIPFX_DARKNESS,
|
||||
GUNSHIPFX_FLARE_COLOR,
|
||||
GUNSHIPFX_FLARE_SIZE,
|
||||
|
||||
GUNSHIPFX_NARROW_BEAM_COLOR,
|
||||
GUNSHIPFX_NARROW_BEAM_SIZE,
|
||||
|
||||
GUNSHIPFX_WIDE_BEAM_COLOR,
|
||||
GUNSHIPFX_WIDE_BEAM_SIZE,
|
||||
|
||||
GUNSHIPFX_AFTERGLOW_COLOR,
|
||||
|
||||
GUNSHIPFX_WIDE_BEAM_LENGTH,
|
||||
|
||||
// must be last
|
||||
GUNSHIPFX_PARAMETERS,
|
||||
};
|
||||
|
||||
class CGunshipFXEnvelope
|
||||
{
|
||||
public:
|
||||
CGunshipFXEnvelope();
|
||||
|
||||
void AddKey( int parameterIndex, const CSimpleKeyInterp &key )
|
||||
{
|
||||
Assert( parameterIndex >= 0 && parameterIndex < GUNSHIPFX_PARAMETERS );
|
||||
|
||||
if ( parameterIndex >= 0 && parameterIndex < GUNSHIPFX_PARAMETERS )
|
||||
{
|
||||
m_parameters[parameterIndex].Insert( key );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CSimpleKeyList m_parameters[GUNSHIPFX_PARAMETERS];
|
||||
};
|
||||
|
||||
// NOTE: Beam widths are half-widths or radii, so this is a beam that represents a cylinder with 2" radius
|
||||
const float NARROW_BEAM_WIDTH = 32;
|
||||
const float WIDE_BEAM_WIDTH = 2;
|
||||
const float FLARE_SIZE = 128;
|
||||
const float DARK_SIZE = 16;
|
||||
const float AFTERGLOW_SIZE = 64;
|
||||
|
||||
CGunshipFXEnvelope::CGunshipFXEnvelope()
|
||||
{
|
||||
// Glow flare
|
||||
AddKey( GUNSHIPFX_FLARE_COLOR, CSimpleKeyInterp( 0.0, KEY_LINEAR, 0 ) );
|
||||
AddKey( GUNSHIPFX_FLARE_COLOR, CSimpleKeyInterp( 0.5, KEY_SPLINE, 1 ) );
|
||||
AddKey( GUNSHIPFX_FLARE_COLOR, CSimpleKeyInterp( 2.9, KEY_LINEAR, 1 ) );
|
||||
AddKey( GUNSHIPFX_FLARE_COLOR, CSimpleKeyInterp( 3.2, KEY_DECELERATE, 0 ) );
|
||||
|
||||
AddKey( GUNSHIPFX_FLARE_SIZE, CSimpleKeyInterp( 0.0, KEY_LINEAR, 0 ) );
|
||||
AddKey( GUNSHIPFX_FLARE_SIZE, CSimpleKeyInterp( 2.9, KEY_ACCELERATE, 1 ) );
|
||||
AddKey( GUNSHIPFX_FLARE_SIZE, CSimpleKeyInterp( 5.0, KEY_LINEAR, 1 ) );
|
||||
|
||||
// Ground beam
|
||||
AddKey( GUNSHIPFX_NARROW_BEAM_COLOR, CSimpleKeyInterp( 0.0, KEY_LINEAR, 0.0 ) );
|
||||
AddKey( GUNSHIPFX_NARROW_BEAM_COLOR, CSimpleKeyInterp( 2.5, KEY_SPLINE, 1.0 ) );
|
||||
AddKey( GUNSHIPFX_NARROW_BEAM_COLOR, CSimpleKeyInterp( 3.0, KEY_LINEAR, 1 ) );
|
||||
AddKey( GUNSHIPFX_NARROW_BEAM_COLOR, CSimpleKeyInterp( 3.2, KEY_ACCELERATE, 0 ) );
|
||||
|
||||
AddKey( GUNSHIPFX_NARROW_BEAM_SIZE, CSimpleKeyInterp( 0.0, KEY_LINEAR, 0 ) );
|
||||
AddKey( GUNSHIPFX_NARROW_BEAM_SIZE, CSimpleKeyInterp( 2.5, KEY_SPLINE, 0.25 ) );
|
||||
AddKey( GUNSHIPFX_NARROW_BEAM_SIZE, CSimpleKeyInterp( 2.8, KEY_ACCELERATE, 1 ) );
|
||||
AddKey( GUNSHIPFX_NARROW_BEAM_SIZE, CSimpleKeyInterp( 3.0, KEY_ACCELERATE, 4 ) );
|
||||
AddKey( GUNSHIPFX_NARROW_BEAM_SIZE, CSimpleKeyInterp( 3.2, KEY_DECELERATE, 0 ) );
|
||||
|
||||
// Glow color on the ship
|
||||
AddKey( GUNSHIPFX_AFTERGLOW_COLOR, CSimpleKeyInterp( 0.0, KEY_LINEAR, 0 ) );
|
||||
AddKey( GUNSHIPFX_AFTERGLOW_COLOR, CSimpleKeyInterp( 3.0, KEY_LINEAR, 1 ) );
|
||||
AddKey( GUNSHIPFX_AFTERGLOW_COLOR, CSimpleKeyInterp( 5.0, KEY_SPLINE, 0 ) );
|
||||
}
|
||||
|
||||
CGunshipFXEnvelope g_GunshipCannonEnvelope;
|
||||
|
||||
static void ScaleColor( color32 &out, const color32 &in, float scale )
|
||||
{
|
||||
out.r = (byte)(int)((float)in.r * scale);
|
||||
out.g = (byte)(int)((float)in.g * scale);
|
||||
out.b = (byte)(int)((float)in.b * scale);
|
||||
out.a = (byte)(int)((float)in.a * scale);
|
||||
}
|
||||
|
||||
static void DrawSpriteTangentSpace( const Vector &vecOrigin, float flWidth, float flHeight, color32 color )
|
||||
{
|
||||
unsigned char pColor[4] = { color.r, color.g, color.b, color.a };
|
||||
|
||||
// Generate half-widths
|
||||
flWidth *= 0.5f;
|
||||
flHeight *= 0.5f;
|
||||
|
||||
// Compute direction vectors for the sprite
|
||||
Vector fwd, right( 1, 0, 0 ), up( 0, 1, 0 );
|
||||
VectorSubtract( CurrentViewOrigin(), vecOrigin, fwd );
|
||||
float flDist = VectorNormalize( fwd );
|
||||
if (flDist >= 1e-3)
|
||||
{
|
||||
CrossProduct( CurrentViewUp(), fwd, right );
|
||||
flDist = VectorNormalize( right );
|
||||
if (flDist >= 1e-3)
|
||||
{
|
||||
CrossProduct( fwd, right, up );
|
||||
}
|
||||
else
|
||||
{
|
||||
// In this case, fwd == g_vecVUp, it's right above or
|
||||
// below us in screen space
|
||||
CrossProduct( fwd, CurrentViewRight(), up );
|
||||
VectorNormalize( up );
|
||||
CrossProduct( up, fwd, right );
|
||||
}
|
||||
}
|
||||
|
||||
Vector left = -right;
|
||||
Vector down = -up;
|
||||
Vector back = -fwd;
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
|
||||
CMeshBuilder meshBuilder;
|
||||
Vector point;
|
||||
IMesh* pMesh = pRenderContext->GetDynamicMesh( );
|
||||
|
||||
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
|
||||
|
||||
meshBuilder.Color4ubv (pColor);
|
||||
meshBuilder.TexCoord2f (0, 0, 1);
|
||||
VectorMA (vecOrigin, -flHeight, up, point);
|
||||
VectorMA (point, -flWidth, right, point);
|
||||
meshBuilder.TangentS3fv( left.Base() );
|
||||
meshBuilder.TangentT3fv( down.Base() );
|
||||
meshBuilder.Normal3fv( back.Base() );
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ubv (pColor);
|
||||
meshBuilder.TexCoord2f (0, 0, 0);
|
||||
VectorMA (vecOrigin, flHeight, up, point);
|
||||
VectorMA (point, -flWidth, right, point);
|
||||
meshBuilder.TangentS3fv( left.Base() );
|
||||
meshBuilder.TangentT3fv( down.Base() );
|
||||
meshBuilder.Normal3fv( back.Base() );
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ubv (pColor);
|
||||
meshBuilder.TexCoord2f (0, 1, 0);
|
||||
VectorMA (vecOrigin, flHeight, up, point);
|
||||
VectorMA (point, flWidth, right, point);
|
||||
meshBuilder.TangentS3fv( left.Base() );
|
||||
meshBuilder.TangentT3fv( down.Base() );
|
||||
meshBuilder.Normal3fv( back.Base() );
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ubv (pColor);
|
||||
meshBuilder.TexCoord2f (0, 1, 1);
|
||||
VectorMA (vecOrigin, -flHeight, up, point);
|
||||
VectorMA (point, flWidth, right, point);
|
||||
meshBuilder.TangentS3fv( left.Base() );
|
||||
meshBuilder.TangentT3fv( down.Base() );
|
||||
meshBuilder.Normal3fv( back.Base() );
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.End();
|
||||
pMesh->Draw();
|
||||
}
|
||||
|
||||
|
||||
void Gunship_DrawSprite( const Vector &vecOrigin, float size, const color32 &color, bool glow )
|
||||
{
|
||||
if ( glow )
|
||||
{
|
||||
pixelvis_queryparams_t params;
|
||||
params.Init( vecOrigin );
|
||||
if ( PixelVisibility_FractionVisible( params, NULL ) <= 0.0f )
|
||||
return;
|
||||
}
|
||||
|
||||
DrawSpriteTangentSpace( vecOrigin, size, size, color );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : int -
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_GunshipFX::DrawModel( int )
|
||||
{
|
||||
static color32 white = {255,255,255,255};
|
||||
Vector params[GUNSHIPFX_PARAMETERS];
|
||||
bool hasParam[GUNSHIPFX_PARAMETERS];
|
||||
|
||||
if ( !m_active )
|
||||
return 1;
|
||||
|
||||
C_BaseEntity *ent = cl_entitylist->GetEnt( m_entityIndex );
|
||||
if ( ent )
|
||||
{
|
||||
QAngle angles;
|
||||
ent->GetAttachment( m_attachment, m_worldPosition, angles );
|
||||
}
|
||||
|
||||
Vector test;
|
||||
m_t += gpGlobals->frametime;
|
||||
if ( m_tMax > 0 )
|
||||
{
|
||||
m_t = clamp( m_t, 0, m_tMax );
|
||||
m_beamEndPosition = m_worldPosition;
|
||||
}
|
||||
float t = m_t;
|
||||
|
||||
bool hasAny = false;
|
||||
memset( hasParam, 0, sizeof(hasParam) );
|
||||
for ( int i = 0; i < GUNSHIPFX_PARAMETERS; i++ )
|
||||
{
|
||||
hasParam[i] = g_GunshipCannonEnvelope.m_parameters[i].Interp( params[i], t );
|
||||
hasAny = hasAny || hasParam[i];
|
||||
}
|
||||
|
||||
// draw the narrow beam
|
||||
if ( hasParam[GUNSHIPFX_NARROW_BEAM_COLOR] && hasParam[GUNSHIPFX_NARROW_BEAM_SIZE] )
|
||||
{
|
||||
IMaterial *pMat = materials->FindMaterial( "sprites/bluelaser1", TEXTURE_GROUP_CLIENT_EFFECTS );
|
||||
float width = NARROW_BEAM_WIDTH * params[GUNSHIPFX_NARROW_BEAM_SIZE].x;
|
||||
color32 color;
|
||||
float bright = params[GUNSHIPFX_NARROW_BEAM_COLOR].x;
|
||||
ScaleColor( color, white, bright );
|
||||
|
||||
//Gunship_DrawLine( m_beamEndPosition, m_targetPosition, width, pMat, color );
|
||||
FX_DrawLine( m_beamEndPosition, m_targetPosition, width, pMat, color );
|
||||
}
|
||||
|
||||
// glowy blue flare sprite
|
||||
if ( hasParam[GUNSHIPFX_FLARE_COLOR] && hasParam[GUNSHIPFX_FLARE_SIZE] )
|
||||
{
|
||||
IMaterial *pMat = materials->FindMaterial( "effects/blueblackflash", TEXTURE_GROUP_CLIENT_EFFECTS );
|
||||
float size = FLARE_SIZE * params[GUNSHIPFX_FLARE_SIZE].x;
|
||||
color32 color;
|
||||
float bright = params[GUNSHIPFX_FLARE_COLOR].x;
|
||||
ScaleColor( color, white, bright );
|
||||
color.a = (int)(255 * params[GUNSHIPFX_DARKNESS].x);
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->Bind( pMat, (IClientRenderable*)this );
|
||||
Gunship_DrawSprite( m_worldPosition, size, color, true );
|
||||
}
|
||||
|
||||
if ( hasParam[GUNSHIPFX_AFTERGLOW_COLOR] )
|
||||
{
|
||||
// Muzzle effect
|
||||
dlight_t *dl = effects->CL_AllocDlight( m_entityIndex );
|
||||
dl->origin = m_worldPosition;
|
||||
dl->color.r = 40*params[GUNSHIPFX_AFTERGLOW_COLOR].x;
|
||||
dl->color.g = 60*params[GUNSHIPFX_AFTERGLOW_COLOR].x;
|
||||
dl->color.b = 255*params[GUNSHIPFX_AFTERGLOW_COLOR].x;
|
||||
dl->color.exponent = 5;
|
||||
dl->radius = 128.0f;
|
||||
dl->die = gpGlobals->curtime + 0.001;
|
||||
}
|
||||
|
||||
if ( m_t >= 4.0 && !hasAny )
|
||||
{
|
||||
EffectShutdown();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pOwner -
|
||||
// &targetPos -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_GunshipFX::Update( C_BaseEntity *pOwner, const Vector &targetPos )
|
||||
{
|
||||
BaseClass::Update();
|
||||
|
||||
m_pOwner = pOwner;
|
||||
|
||||
if ( m_active )
|
||||
{
|
||||
m_targetPosition = targetPos;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gunship
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class C_CombineGunship : public C_BaseHelicopter
|
||||
{
|
||||
DECLARE_CLASS( C_CombineGunship, C_BaseHelicopter );
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_CombineGunship( void ) {}
|
||||
|
||||
virtual ~C_CombineGunship( void )
|
||||
{
|
||||
m_cannonFX.EffectShutdown();
|
||||
}
|
||||
|
||||
C_GunshipFX m_cannonFX;
|
||||
Vector m_vecHitPos;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : length -
|
||||
// *data -
|
||||
// Output : void
|
||||
//-----------------------------------------------------------------------------
|
||||
void ReceiveMessage( int classID, bf_read &msg )
|
||||
{
|
||||
if ( classID != GetClientClass()->m_ClassID )
|
||||
{
|
||||
// message is for subclass
|
||||
BaseClass::ReceiveMessage( classID, msg );
|
||||
return;
|
||||
}
|
||||
|
||||
int messageType = msg.ReadByte();
|
||||
switch( messageType )
|
||||
{
|
||||
case GUNSHIP_MSG_STREAKS:
|
||||
{
|
||||
Vector pos;
|
||||
msg.ReadBitVec3Coord( pos );
|
||||
m_cannonFX.SetRenderOrigin( pos );
|
||||
m_cannonFX.EffectInit( entindex(), LookupAttachment( "BellyGun" ) );
|
||||
m_cannonFX.LimitTime( GUNSHIPFX_BIG_SHOT_TIME );
|
||||
}
|
||||
break;
|
||||
|
||||
case GUNSHIP_MSG_BIG_SHOT:
|
||||
{
|
||||
Vector tmp;
|
||||
msg.ReadBitVec3Coord( tmp );
|
||||
m_cannonFX.SetTime( GUNSHIPFX_BIG_SHOT_TIME );
|
||||
m_cannonFX.LimitTime( 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case GUNSHIP_MSG_DEAD:
|
||||
{
|
||||
m_cannonFX.EffectShutdown();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
m_cannonFX.Update( this, m_vecHitPos );
|
||||
}
|
||||
|
||||
virtual RenderGroup_t GetRenderGroup()
|
||||
{
|
||||
if ( hl2_episodic.GetBool() == true )
|
||||
{
|
||||
return RENDER_GROUP_TWOPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::GetRenderGroup();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
C_CombineGunship( const C_CombineGunship & ) {}
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_CombineGunship, DT_CombineGunship, CNPC_CombineGunship )
|
||||
RecvPropVector(RECVINFO(m_vecHitPos)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handle gunship impacts
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactGunshipCallback( const CEffectData &data )
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vecOrigin, vecStart, vecShotDir;
|
||||
int iMaterial, iDamageType, iHitbox;
|
||||
short nSurfaceProp;
|
||||
C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
|
||||
|
||||
if ( !pEntity )
|
||||
return;
|
||||
|
||||
// If we hit, perform our custom effects and play the sound
|
||||
if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr ) )
|
||||
{
|
||||
// Check for custom effects based on the Decal index
|
||||
PerformCustomEffects( vecOrigin, tr, vecShotDir, iMaterial, 3 );
|
||||
}
|
||||
|
||||
PlayImpactSound( pEntity, tr, vecOrigin, nSurfaceProp );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "ImpactGunship", ImpactGunshipCallback );
|
||||
|
||||
386
sp/src/game/client/hl2/c_npc_hydra.cpp
Normal file
386
sp/src/game/client/hl2/c_npc_hydra.cpp
Normal file
@@ -0,0 +1,386 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "bone_setup.h"
|
||||
#include "c_ai_basenpc.h"
|
||||
#include "engine/ivdebugoverlay.h"
|
||||
#include "tier0/vprof.h"
|
||||
#include "soundinfo.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_NPC_Hydra : public C_AI_BaseNPC
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_NPC_Hydra, C_AI_BaseNPC );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_INTERPOLATION();
|
||||
|
||||
C_NPC_Hydra();
|
||||
virtual ~C_NPC_Hydra();
|
||||
|
||||
// model specific
|
||||
virtual void OnLatchInterpolatedVariables( int flags );
|
||||
virtual bool SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime );
|
||||
virtual void StandardBlendingRules( Vector pos[], Quaternion q[], float currentTime, int boneMask );
|
||||
|
||||
void CalcBoneChain( Vector pos[], const Vector chain[] );
|
||||
void CalcBoneAngles( const Vector pos[], Quaternion q[] );
|
||||
|
||||
virtual bool GetSoundSpatialization( SpatializationInfo_t& info );
|
||||
|
||||
virtual void ResetLatched();
|
||||
|
||||
#define CHAIN_LINKS 32
|
||||
|
||||
bool m_bNewChain;
|
||||
int m_fLatchFlags;
|
||||
Vector m_vecChain[CHAIN_LINKS];
|
||||
|
||||
Vector m_vecHeadDir;
|
||||
CInterpolatedVar< Vector > m_iv_vecHeadDir;
|
||||
|
||||
//Vector m_vecInterpHeadDir;
|
||||
|
||||
float m_flRelaxedLength;
|
||||
|
||||
Vector *m_vecPos; // current animation
|
||||
CInterpolatedVar< Vector > *m_iv_vecPos;
|
||||
|
||||
int m_numHydraBones;
|
||||
float *m_boneLength;
|
||||
|
||||
float m_maxPossibleLength;
|
||||
|
||||
private:
|
||||
C_NPC_Hydra( const C_NPC_Hydra & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_NPC_Hydra, DT_NPC_Hydra, CNPC_Hydra)
|
||||
RecvPropVector ( RECVINFO( m_vecChain[0] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[1] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[2] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[3] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[4] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[5] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[6] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[7] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[8] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[9] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[10] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[11] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[12] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[13] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[14] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[15] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[16] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[17] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[18] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[19] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[20] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[21] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[22] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[23] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[24] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[25] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[26] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[27] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[28] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[29] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[30] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecChain[31] ) ),
|
||||
RecvPropVector ( RECVINFO( m_vecHeadDir ) ),
|
||||
RecvPropFloat ( RECVINFO( m_flRelaxedLength ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_NPC_Hydra::C_NPC_Hydra() : m_iv_vecHeadDir( "C_NPC_Hydra::m_iv_vecHeadDir" )
|
||||
{
|
||||
AddVar( &m_vecHeadDir, &m_iv_vecHeadDir, LATCH_ANIMATION_VAR );
|
||||
|
||||
m_numHydraBones = 0;
|
||||
m_boneLength = NULL;
|
||||
m_maxPossibleLength = 1;
|
||||
m_vecPos = NULL;
|
||||
m_iv_vecPos = NULL;
|
||||
}
|
||||
|
||||
|
||||
C_NPC_Hydra::~C_NPC_Hydra()
|
||||
{
|
||||
delete m_boneLength;
|
||||
delete m_vecPos;
|
||||
delete[] m_iv_vecPos;
|
||||
m_iv_vecPos = NULL;
|
||||
}
|
||||
|
||||
void C_NPC_Hydra::OnLatchInterpolatedVariables( int flags )
|
||||
{
|
||||
m_bNewChain = true;
|
||||
m_fLatchFlags = flags;
|
||||
|
||||
BaseClass::OnLatchInterpolatedVariables( flags );
|
||||
}
|
||||
|
||||
void C_NPC_Hydra::ResetLatched()
|
||||
{
|
||||
for (int i = 0; i < m_numHydraBones; i++)
|
||||
{
|
||||
m_iv_vecPos[i].Reset();
|
||||
}
|
||||
|
||||
BaseClass::ResetLatched();
|
||||
}
|
||||
|
||||
bool C_NPC_Hydra::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime )
|
||||
{
|
||||
return BaseClass::SetupBones( pBoneToWorldOut, nMaxBones, boneMask, currentTime );
|
||||
}
|
||||
|
||||
|
||||
void C_NPC_Hydra::StandardBlendingRules( Vector pos[], Quaternion q[], float currentTime, int boneMask )
|
||||
{
|
||||
VPROF( "C_NPC_Hydra::StandardBlendingRules" );
|
||||
|
||||
studiohdr_t *hdr = GetModelPtr();
|
||||
if ( !hdr )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
|
||||
// check for changing model memory requirements
|
||||
bool bNewlyInited = false;
|
||||
if (m_numHydraBones != hdr->numbones)
|
||||
{
|
||||
m_numHydraBones = hdr->numbones;
|
||||
|
||||
// build root animation
|
||||
float poseparam[MAXSTUDIOPOSEPARAM];
|
||||
for (i = 0; i < hdr->GetNumPoseParameters(); i++)
|
||||
{
|
||||
poseparam[i] = 0;
|
||||
}
|
||||
CalcPose( hdr, NULL, pos, q, 0.0f, 0.0f, poseparam, BONE_USED_BY_ANYTHING );
|
||||
|
||||
// allocate arrays
|
||||
if (m_boneLength)
|
||||
{
|
||||
delete[] m_boneLength;
|
||||
}
|
||||
m_boneLength = new float [m_numHydraBones];
|
||||
|
||||
if (m_vecPos)
|
||||
{
|
||||
delete[] m_vecPos;
|
||||
}
|
||||
m_vecPos = new Vector [m_numHydraBones];
|
||||
|
||||
if (m_iv_vecPos)
|
||||
{
|
||||
delete m_iv_vecPos;
|
||||
}
|
||||
m_iv_vecPos = new CInterpolatedVar< Vector >[m_numHydraBones];
|
||||
for ( i = 0; i < m_numHydraBones; i++ )
|
||||
{
|
||||
m_iv_vecPos[ i ].Setup( &m_vecPos[ i ], LATCH_SIMULATION_VAR | EXCLUDE_AUTO_LATCH | EXCLUDE_AUTO_INTERPOLATE );
|
||||
}
|
||||
|
||||
// calc models bone lengths
|
||||
m_maxPossibleLength = 0;
|
||||
for (i = 0; i < m_numHydraBones-1; i++)
|
||||
{
|
||||
m_boneLength[i] = (pos[i+1] - pos[i]).Length();
|
||||
m_maxPossibleLength += m_boneLength[i];
|
||||
}
|
||||
m_boneLength[i] = 0.0f;
|
||||
|
||||
bNewlyInited = true;
|
||||
}
|
||||
|
||||
// calc new bone setup if networked.
|
||||
if (m_bNewChain)
|
||||
{
|
||||
CalcBoneChain( m_vecPos, m_vecChain );
|
||||
for (i = 0; i < m_numHydraBones; i++)
|
||||
{
|
||||
// debugoverlay->AddLineOverlay( m_vecPos[i], m_vecPos[i<m_numHydraBones-1?i+1:m_numHydraBones-1], 0, 255, 0, false, 0.1 );
|
||||
m_vecPos[i] = m_vecPos[i] - GetAbsOrigin();
|
||||
|
||||
if ( m_fLatchFlags & LATCH_SIMULATION_VAR )
|
||||
{
|
||||
m_iv_vecPos[i].NoteChanged( currentTime, true );
|
||||
}
|
||||
}
|
||||
m_bNewChain = false;
|
||||
}
|
||||
|
||||
// if just allocated, initialize bones
|
||||
if (bNewlyInited)
|
||||
{
|
||||
|
||||
for (i = 0; i < m_numHydraBones; i++)
|
||||
{
|
||||
m_iv_vecPos[i].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < m_numHydraBones; i++)
|
||||
{
|
||||
m_iv_vecPos[i].Interpolate( currentTime );
|
||||
pos[ i ] = m_vecPos[ i ];
|
||||
}
|
||||
|
||||
// calculate bone angles
|
||||
CalcBoneAngles( pos, q );
|
||||
|
||||
// rotate the last bone of the hydra 90 degrees since it's oriented differently than the others
|
||||
Quaternion qTmp;
|
||||
AngleQuaternion( QAngle( 0, -90, 0) , qTmp );
|
||||
QuaternionMult( q[m_numHydraBones - 1], qTmp, q[m_numHydraBones - 1] );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Fits skeleton of hydra to the variable segment length "chain" array
|
||||
// Adjusts overall hydra so that "m_flRelaxedLength" of texture fits over
|
||||
// the actual length of the chain
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void C_NPC_Hydra::CalcBoneChain( Vector pos[], const Vector chain[] )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
// Find the dist chain link that's not zero length
|
||||
i = CHAIN_LINKS-1;
|
||||
while (i > 0)
|
||||
{
|
||||
if ((chain[i] - chain[i-1]).LengthSqr() > 0.0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
|
||||
// initialize the last bone to the last bone
|
||||
j = m_numHydraBones - 1;
|
||||
|
||||
// clamp length
|
||||
float totalLength = 0;
|
||||
for (int k = i; k > 0; k--)
|
||||
{
|
||||
// debugoverlay->AddLineOverlay( chain[k], chain[k-1], 255, 255, 255, false, 0 );
|
||||
totalLength += (chain[k] - chain[k-1]).Length();
|
||||
}
|
||||
totalLength = clamp( totalLength, 1.0, m_maxPossibleLength );
|
||||
float scale = m_flRelaxedLength / totalLength;
|
||||
|
||||
// starting from the head, fit the hydra skeleton onto the chain spline
|
||||
float dist = -16;
|
||||
while (j >= 0 && i > 0)
|
||||
{
|
||||
// debugoverlay->AddLineOverlay( chain[i], chain[i-1], 255, 255, 255, false, 0 );
|
||||
float dt = (chain[i] - chain[i-1]).Length() * scale;
|
||||
float dx = dt;
|
||||
while (j >= 0 && dist + dt >= m_boneLength[j])
|
||||
{
|
||||
float s = (dx - (dt - (m_boneLength[j] - dist))) / dx;
|
||||
|
||||
if (s < 0 || s > 1.)
|
||||
s = 0;
|
||||
// pos[j] = chain[i] * (1 - s) + chain[i-1] * s;
|
||||
Catmull_Rom_Spline( chain[(i<CHAIN_LINKS-1)?i+1:CHAIN_LINKS-1], chain[i], chain[(i>0)?i-1:0], chain[(i>1)?i-2:0], s, pos[j] );
|
||||
// debugoverlay->AddLineOverlay( pos[j], chain[i], 0, 255, 0, false, 0 );
|
||||
// debugoverlay->AddLineOverlay( pos[j], chain[i-1], 0, 255, 0, false, 0 );
|
||||
|
||||
dt = dt - (m_boneLength[j] - dist);
|
||||
j--;
|
||||
dist = 0;
|
||||
}
|
||||
dist += dt;
|
||||
i--;
|
||||
}
|
||||
|
||||
while (j >= 0)
|
||||
{
|
||||
pos[j] = chain[0];
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Minimize the amount of twist between bone segments
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void C_NPC_Hydra::CalcBoneAngles( const Vector pos[], Quaternion q[] )
|
||||
{
|
||||
int i;
|
||||
matrix3x4_t bonematrix;
|
||||
|
||||
for (i = m_numHydraBones - 1; i >= 0; i--)
|
||||
{
|
||||
Vector forward;
|
||||
Vector left2;
|
||||
|
||||
if (i != m_numHydraBones - 1)
|
||||
{
|
||||
QuaternionMatrix( q[i+1], bonematrix );
|
||||
MatrixGetColumn( bonematrix, 1, left2 );
|
||||
|
||||
forward = (pos[i+1] - pos[i]) /* + (pos[i] - pos[i-1])*/;
|
||||
float length = VectorNormalize( forward );
|
||||
if (length == 0.0)
|
||||
{
|
||||
q[i] = q[i+1];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forward = m_vecHeadDir;
|
||||
VectorNormalize( forward );
|
||||
|
||||
VectorMatrix( forward, bonematrix );
|
||||
MatrixGetColumn( bonematrix, 1, left2 );
|
||||
}
|
||||
|
||||
Vector up = CrossProduct( forward, left2 );
|
||||
VectorNormalize( up );
|
||||
|
||||
Vector left = CrossProduct( up, forward );
|
||||
|
||||
MatrixSetColumn( forward, 0, bonematrix );
|
||||
MatrixSetColumn( left, 1, bonematrix );
|
||||
MatrixSetColumn( up, 2, bonematrix );
|
||||
|
||||
// MatrixQuaternion( bonematrix, q[i] );
|
||||
QAngle angles;
|
||||
MatrixAngles( bonematrix, angles );
|
||||
AngleQuaternion( angles, q[i] );
|
||||
}
|
||||
}
|
||||
|
||||
bool C_NPC_Hydra::GetSoundSpatialization( SpatializationInfo_t& info )
|
||||
{
|
||||
bool bret = BaseClass::GetSoundSpatialization( info );
|
||||
// Default things it's audible, put it at a better spot?
|
||||
if ( bret )
|
||||
{
|
||||
// TODO: Note, this is where you could override the sound position and orientation and use
|
||||
// an attachment points position as the sound source
|
||||
// You might have to issue C_BaseAnimating::AllowBoneAccess( true, false ); to allow
|
||||
// bone setup during sound spatialization if you run into asserts...
|
||||
}
|
||||
|
||||
return bret;
|
||||
}
|
||||
|
||||
182
sp/src/game/client/hl2/c_npc_manhack.cpp
Normal file
182
sp/src/game/client/hl2/c_npc_manhack.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_ai_basenpc.h"
|
||||
#include "soundenvelope.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
class C_NPC_Manhack : public C_AI_BaseNPC
|
||||
{
|
||||
public:
|
||||
C_NPC_Manhack() {}
|
||||
|
||||
DECLARE_CLASS( C_NPC_Manhack, C_AI_BaseNPC );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
// Purpose: Start the manhack's engine sound.
|
||||
virtual void OnDataChanged( DataUpdateType_t type );
|
||||
virtual void UpdateOnRemove( void );
|
||||
virtual void OnRestore();
|
||||
|
||||
private:
|
||||
C_NPC_Manhack( const C_NPC_Manhack & );
|
||||
|
||||
// Purpose: Start + stop the manhack's engine sound.
|
||||
void SoundInit( void );
|
||||
void SoundShutdown( void );
|
||||
|
||||
CSoundPatch *m_pEngineSound1;
|
||||
CSoundPatch *m_pEngineSound2;
|
||||
CSoundPatch *m_pBladeSound;
|
||||
|
||||
int m_nEnginePitch1;
|
||||
int m_nEnginePitch2;
|
||||
float m_flEnginePitch1Time;
|
||||
float m_flEnginePitch2Time;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save/restore
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC( C_NPC_Manhack )
|
||||
|
||||
// DEFINE_SOUNDPATCH( m_pEngineSound1 ),
|
||||
// DEFINE_SOUNDPATCH( m_pEngineSound2 ),
|
||||
// DEFINE_SOUNDPATCH( m_pBladeSound ),
|
||||
|
||||
// DEFINE_FIELD( m_nEnginePitch1, FIELD_INTEGER ),
|
||||
// DEFINE_FIELD( m_nEnginePitch2, FIELD_INTEGER ),
|
||||
// DEFINE_FIELD( m_flEnginePitch1Time, FIELD_FLOAT ),
|
||||
// DEFINE_FIELD( m_flEnginePitch2Time, FIELD_FLOAT ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Networking
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_NPC_Manhack, DT_NPC_Manhack, CNPC_Manhack)
|
||||
RecvPropIntWithMinusOneFlag(RECVINFO(m_nEnginePitch1)),
|
||||
RecvPropFloat(RECVINFO(m_flEnginePitch1Time)),
|
||||
RecvPropIntWithMinusOneFlag(RECVINFO(m_nEnginePitch2)),
|
||||
RecvPropFloat(RECVINFO(m_flEnginePitch2Time)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start the manhack's engine sound.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Manhack::OnDataChanged( DataUpdateType_t type )
|
||||
{
|
||||
BaseClass::OnDataChanged( type );
|
||||
|
||||
if (( m_nEnginePitch1 < 0 ) || ( m_nEnginePitch2 < 0 ) )
|
||||
{
|
||||
SoundShutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
SoundInit();
|
||||
if ( m_pEngineSound1 && m_pEngineSound2 )
|
||||
{
|
||||
float dt = ( m_flEnginePitch1Time >= gpGlobals->curtime ) ? m_flEnginePitch1Time - gpGlobals->curtime : 0.0f;
|
||||
CSoundEnvelopeController::GetController().SoundChangePitch( m_pEngineSound1, m_nEnginePitch1, dt );
|
||||
dt = ( m_flEnginePitch2Time >= gpGlobals->curtime ) ? m_flEnginePitch2Time - gpGlobals->curtime : 0.0f;
|
||||
CSoundEnvelopeController::GetController().SoundChangePitch( m_pEngineSound2, m_nEnginePitch2, dt );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Restore
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Manhack::OnRestore()
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
SoundInit();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start the manhack's engine sound.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Manhack::UpdateOnRemove( void )
|
||||
{
|
||||
BaseClass::UpdateOnRemove();
|
||||
SoundShutdown();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start the manhack's engine sound.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Manhack::SoundInit( void )
|
||||
{
|
||||
if (( m_nEnginePitch1 < 0 ) || ( m_nEnginePitch2 < 0 ) )
|
||||
return;
|
||||
|
||||
// play an engine start sound!!
|
||||
CPASAttenuationFilter filter( this );
|
||||
|
||||
// Bring up the engine looping sound.
|
||||
if( !m_pEngineSound1 )
|
||||
{
|
||||
m_pEngineSound1 = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), "NPC_Manhack.EngineSound1" );
|
||||
CSoundEnvelopeController::GetController().Play( m_pEngineSound1, 0.0, m_nEnginePitch1 );
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pEngineSound1, 0.7, 2.0 );
|
||||
}
|
||||
|
||||
if( !m_pEngineSound2 )
|
||||
{
|
||||
m_pEngineSound2 = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), "NPC_Manhack.EngineSound2" );
|
||||
CSoundEnvelopeController::GetController().Play( m_pEngineSound2, 0.0, m_nEnginePitch2 );
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pEngineSound2, 0.7, 2.0 );
|
||||
}
|
||||
|
||||
if( !m_pBladeSound )
|
||||
{
|
||||
m_pBladeSound = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), "NPC_Manhack.BladeSound" );
|
||||
CSoundEnvelopeController::GetController().Play( m_pBladeSound, 0.0, m_nEnginePitch1 );
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pBladeSound, 0.7, 2.0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_NPC_Manhack::SoundShutdown(void)
|
||||
{
|
||||
// Kill the engine!
|
||||
if ( m_pEngineSound1 )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_pEngineSound1 );
|
||||
m_pEngineSound1 = NULL;
|
||||
}
|
||||
|
||||
// Kill the engine!
|
||||
if ( m_pEngineSound2 )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_pEngineSound2 );
|
||||
m_pEngineSound2 = NULL;
|
||||
}
|
||||
|
||||
// Kill the blade!
|
||||
if ( m_pBladeSound )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_pBladeSound );
|
||||
m_pBladeSound = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
174
sp/src/game/client/hl2/c_npc_rollermine.cpp
Normal file
174
sp/src/game/client/hl2/c_npc_rollermine.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_ai_basenpc.h"
|
||||
#include "iviewrender_beams.h"
|
||||
#include "beam_shared.h"
|
||||
#include "materialsystem/imaterial.h"
|
||||
#include "model_types.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
#include "beamdraw.h"
|
||||
|
||||
class C_RollerMine : public C_AI_BaseNPC
|
||||
{
|
||||
DECLARE_CLASS( C_RollerMine, C_AI_BaseNPC );
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_RollerMine( void ) {}
|
||||
|
||||
int DrawModel( int flags );
|
||||
|
||||
RenderGroup_t GetRenderGroup( void )
|
||||
{
|
||||
if ( m_bIsOpen )
|
||||
return RENDER_GROUP_TRANSLUCENT_ENTITY;
|
||||
else
|
||||
return RENDER_GROUP_OPAQUE_ENTITY;
|
||||
}
|
||||
|
||||
private:
|
||||
C_RollerMine( const C_RollerMine & ) {}
|
||||
|
||||
bool m_bIsOpen;
|
||||
float m_flActiveTime;
|
||||
bool m_bHackedByAlyx;
|
||||
bool m_bPowerDown;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_RollerMine, DT_RollerMine, CNPC_RollerMine )
|
||||
RecvPropInt( RECVINFO( m_bIsOpen ) ),
|
||||
RecvPropFloat( RECVINFO( m_flActiveTime ) ),
|
||||
RecvPropInt( RECVINFO( m_bHackedByAlyx ) ),
|
||||
RecvPropInt( RECVINFO( m_bPowerDown ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
#define NUM_ATTACHMENTS 11
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flags -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_RollerMine::DrawModel( int flags )
|
||||
{
|
||||
if ( m_bIsOpen && m_flActiveTime <= gpGlobals->curtime )
|
||||
{
|
||||
float scale = random->RandomFloat( 4.0f, 6.0f );
|
||||
|
||||
if ( gpGlobals->frametime != 0 )
|
||||
{
|
||||
// Inner beams
|
||||
BeamInfo_t beamInfo;
|
||||
|
||||
beamInfo.m_vecStart = GetAbsOrigin();
|
||||
Vector offset = RandomVector( -6*scale, 2*scale );
|
||||
|
||||
offset += Vector(2,2,2) * scale;
|
||||
beamInfo.m_vecEnd = GetAbsOrigin() + offset;
|
||||
|
||||
beamInfo.m_pStartEnt= cl_entitylist->GetEnt( BEAMENT_ENTITY( entindex() ) );
|
||||
beamInfo.m_pEndEnt = beamInfo.m_pStartEnt;
|
||||
beamInfo.m_nStartAttachment = random->RandomInt( 0, NUM_ATTACHMENTS );
|
||||
beamInfo.m_nEndAttachment = random->RandomInt( 0, NUM_ATTACHMENTS );
|
||||
|
||||
// Ensure we're not the same point
|
||||
if ( beamInfo.m_nStartAttachment == beamInfo.m_nEndAttachment )
|
||||
{
|
||||
int nextStep = ( random->RandomInt( 0, 1 ) ) ? 1 : -1;
|
||||
|
||||
beamInfo.m_nEndAttachment = ( beamInfo.m_nStartAttachment + nextStep ) % NUM_ATTACHMENTS;
|
||||
}
|
||||
|
||||
beamInfo.m_nType = TE_BEAMTESLA;
|
||||
beamInfo.m_pszModelName = "sprites/lgtning.vmt";
|
||||
beamInfo.m_flHaloScale = 0.0f;
|
||||
beamInfo.m_flLife = 0.1f;
|
||||
beamInfo.m_flWidth = random->RandomFloat( 2.0f, 4.0f );
|
||||
beamInfo.m_flEndWidth = random->RandomFloat( 0.0f, 1.0f );
|
||||
beamInfo.m_flFadeLength = 0.0f;
|
||||
beamInfo.m_flAmplitude = random->RandomFloat( 16, 32 );
|
||||
beamInfo.m_flBrightness = 255.0;
|
||||
beamInfo.m_flSpeed = 0.0;
|
||||
beamInfo.m_nStartFrame = 0.0;
|
||||
beamInfo.m_flFrameRate = 1.0f;
|
||||
|
||||
if ( m_bPowerDown )
|
||||
{
|
||||
beamInfo.m_flRed = 255.0f;;
|
||||
beamInfo.m_flGreen = 64.0f;
|
||||
beamInfo.m_flBlue = 64.0f;
|
||||
}
|
||||
else if ( m_bHackedByAlyx )
|
||||
{
|
||||
beamInfo.m_flRed = 240.0f;;
|
||||
beamInfo.m_flGreen = 200.0f;
|
||||
beamInfo.m_flBlue = 80.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
beamInfo.m_flRed = 255.0f;;
|
||||
beamInfo.m_flGreen = 255.0f;
|
||||
beamInfo.m_flBlue = 255.0f;
|
||||
}
|
||||
|
||||
beamInfo.m_nSegments = 4;
|
||||
beamInfo.m_bRenderable = true;
|
||||
beamInfo.m_nFlags = 0;
|
||||
|
||||
beams->CreateBeamEntPoint( beamInfo );
|
||||
|
||||
// Draw the halo
|
||||
float color[3];
|
||||
|
||||
if ( m_bHackedByAlyx )
|
||||
{
|
||||
color[0] = 0.25f;
|
||||
color[1] = 0.05f;
|
||||
color[2] = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
color[0] = color[1] = color[2] = 0.15f;
|
||||
}
|
||||
|
||||
IMaterial *pMaterial = materials->FindMaterial( "effects/rollerglow", NULL, false );
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->Bind( pMaterial );
|
||||
DrawHalo( pMaterial, GetAbsOrigin(), random->RandomFloat( 6.0f*scale, 6.5f*scale ), color );
|
||||
|
||||
if ( m_bPowerDown )
|
||||
{
|
||||
color[0] = random->RandomFloat( 0.80f, 1.00f );
|
||||
color[1] = random->RandomFloat( 0.10f, 0.25f );
|
||||
color[2] = 0.0f;
|
||||
}
|
||||
else if ( m_bHackedByAlyx )
|
||||
{
|
||||
color[0] = random->RandomFloat( 0.25f, 0.75f );
|
||||
color[1] = random->RandomFloat( 0.10f, 0.25f );
|
||||
color[2] = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
color[0] = color[1] = color[2] = random->RandomFloat( 0.25f, 0.5f );
|
||||
}
|
||||
|
||||
Vector attachOrigin;
|
||||
QAngle attachAngles;
|
||||
|
||||
GetAttachment( beamInfo.m_nEndAttachment, attachOrigin, attachAngles );
|
||||
DrawHalo( pMaterial, attachOrigin, random->RandomFloat( 1.0f*scale, 1.5f*scale ), color );
|
||||
|
||||
GetAttachment( beamInfo.m_nStartAttachment, attachOrigin, attachAngles );
|
||||
DrawHalo( pMaterial, attachOrigin, random->RandomFloat( 1.0f*scale, 1.5f*scale ), color );
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::DrawModel( flags );
|
||||
}
|
||||
279
sp/src/game/client/hl2/c_plasma_beam_node.cpp
Normal file
279
sp/src/game/client/hl2/c_plasma_beam_node.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "particles_simple.h"
|
||||
#include "c_tracer.h"
|
||||
#include "particle_collision.h"
|
||||
#include "view.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define PLASMASPARK_LIFETIME 0.5
|
||||
#define SPRAYS_PER_THINK 12
|
||||
|
||||
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectPlasmaBeam )
|
||||
CLIENTEFFECT_MATERIAL( "sprites/plasmaember" )
|
||||
CLIENTEFFECT_REGISTER_END()
|
||||
|
||||
class C_PlasmaBeamNode;
|
||||
|
||||
//##################################################################
|
||||
//
|
||||
// > CPlasmaSpray
|
||||
//
|
||||
//##################################################################
|
||||
class CPlasmaSpray : public CSimpleEmitter
|
||||
{
|
||||
public:
|
||||
CPlasmaSpray( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
|
||||
|
||||
static CSmartPtr<CPlasmaSpray> Create( const char *pDebugName );
|
||||
void Think( void );
|
||||
void UpdateVelocity( SimpleParticle *pParticle, float timeDelta );
|
||||
virtual void RenderParticles( CParticleRenderIterator *pIterator );
|
||||
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
|
||||
EHANDLE m_pOwner;
|
||||
CParticleCollision m_ParticleCollision;
|
||||
|
||||
private:
|
||||
CPlasmaSpray( const CPlasmaSpray & );
|
||||
};
|
||||
|
||||
//##################################################################
|
||||
//
|
||||
// PlasmaBeamNode - generates plasma spray
|
||||
//
|
||||
//##################################################################
|
||||
class C_PlasmaBeamNode : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_PlasmaBeamNode, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_PlasmaBeamNode();
|
||||
~C_PlasmaBeamNode(void);
|
||||
|
||||
public:
|
||||
void ClientThink(void);
|
||||
void AddEntity( void );
|
||||
void OnDataChanged(DataUpdateType_t updateType);
|
||||
bool ShouldDraw();
|
||||
bool m_bSprayOn;
|
||||
CSmartPtr<CPlasmaSpray> m_pFirePlasmaSpray;
|
||||
};
|
||||
|
||||
//##################################################################
|
||||
//
|
||||
// > CPlasmaSpray
|
||||
//
|
||||
//##################################################################
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pParticle -
|
||||
// timeDelta -
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
CSmartPtr<CPlasmaSpray> CPlasmaSpray::Create( const char *pDebugName )
|
||||
{
|
||||
CPlasmaSpray *pRet = new CPlasmaSpray( pDebugName );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : fTimeDelta -
|
||||
// Output : Vector
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPlasmaSpray::UpdateVelocity( SimpleParticle *pParticle, float timeDelta )
|
||||
{
|
||||
Vector vGravity = Vector(0,0,-1000);
|
||||
float flFrametime = gpGlobals->frametime;
|
||||
vGravity = flFrametime * vGravity;
|
||||
pParticle->m_vecVelocity += vGravity;
|
||||
}
|
||||
|
||||
|
||||
void CPlasmaSpray::SimulateParticles( CParticleSimulateIterator *pIterator )
|
||||
{
|
||||
float timeDelta = pIterator->GetTimeDelta();
|
||||
|
||||
SimpleParticle *pParticle = (SimpleParticle*)pIterator->GetFirst();
|
||||
while ( pParticle )
|
||||
{
|
||||
//Should this particle die?
|
||||
pParticle->m_flLifetime += timeDelta;
|
||||
|
||||
C_PlasmaBeamNode* pNode = (C_PlasmaBeamNode*)((C_BaseEntity*)m_pOwner);
|
||||
if ( pParticle->m_flLifetime >= pParticle->m_flDieTime )
|
||||
{
|
||||
pIterator->RemoveParticle( pParticle );
|
||||
}
|
||||
// If owner is gone or spray off remove me
|
||||
else if (pNode == NULL || !pNode->m_bSprayOn)
|
||||
{
|
||||
pIterator->RemoveParticle( pParticle );
|
||||
}
|
||||
|
||||
//Simulate the movement with collision
|
||||
trace_t trace;
|
||||
m_ParticleCollision.MoveParticle( pParticle->m_Pos, pParticle->m_vecVelocity, NULL, timeDelta, &trace );
|
||||
|
||||
pParticle = (SimpleParticle*)pIterator->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CPlasmaSpray::RenderParticles( CParticleRenderIterator *pIterator )
|
||||
{
|
||||
const SimpleParticle *pParticle = (const SimpleParticle *)pIterator->GetFirst();
|
||||
while ( pParticle )
|
||||
{
|
||||
float scale = random->RandomFloat( 0.02, 0.08 );
|
||||
|
||||
// NOTE: We need to do everything in screen space
|
||||
Vector delta;
|
||||
Vector start;
|
||||
TransformParticle(ParticleMgr()->GetModelView(), pParticle->m_Pos, start);
|
||||
float sortKey = start.z;
|
||||
|
||||
Vector3DMultiply( CurrentWorldToViewMatrix(), pParticle->m_vecVelocity, delta );
|
||||
|
||||
delta[0] *= scale;
|
||||
delta[1] *= scale;
|
||||
delta[2] *= scale;
|
||||
|
||||
// See c_tracer.* for this method
|
||||
Tracer_Draw( pIterator->GetParticleDraw(), start, delta, random->RandomInt( 2, 8 ), 0 );
|
||||
|
||||
pParticle = (const SimpleParticle *)pIterator->GetNext( sortKey );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//##################################################################
|
||||
//
|
||||
// PlasmaBeamNode - generates plasma spray
|
||||
//
|
||||
//##################################################################
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
C_PlasmaBeamNode::C_PlasmaBeamNode(void)
|
||||
{
|
||||
m_bSprayOn = false;
|
||||
m_pFirePlasmaSpray = CPlasmaSpray::Create( "C_PlasmaBeamNode" );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
C_PlasmaBeamNode::~C_PlasmaBeamNode(void)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PlasmaBeamNode::AddEntity( void )
|
||||
{
|
||||
m_pFirePlasmaSpray->SetSortOrigin( GetAbsOrigin() );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void C_PlasmaBeamNode::OnDataChanged(DataUpdateType_t updateType)
|
||||
{
|
||||
if (updateType == DATA_UPDATE_CREATED)
|
||||
{
|
||||
Vector vMoveDir = GetAbsVelocity();
|
||||
float flVel = VectorNormalize(vMoveDir);
|
||||
m_pFirePlasmaSpray->m_ParticleCollision.Setup( GetAbsOrigin(), &vMoveDir, 0.3,
|
||||
flVel-50, flVel+50, 800, 0.5 );
|
||||
SetNextClientThink(gpGlobals->curtime + 0.01);
|
||||
}
|
||||
C_BaseEntity::OnDataChanged(updateType);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
bool C_PlasmaBeamNode::ShouldDraw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void C_PlasmaBeamNode::ClientThink(void)
|
||||
{
|
||||
if (!m_bSprayOn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
trace_t trace;
|
||||
Vector vEndTrace = GetAbsOrigin() + (0.3*GetAbsVelocity());
|
||||
UTIL_TraceLine( GetAbsOrigin(), vEndTrace, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &trace );
|
||||
if ( trace.fraction != 1.0f || trace.startsolid)
|
||||
{
|
||||
m_bSprayOn = false;
|
||||
return;
|
||||
}
|
||||
|
||||
PMaterialHandle handle = m_pFirePlasmaSpray->GetPMaterial( "sprites/plasmaember" );
|
||||
for (int i=0;i<SPRAYS_PER_THINK;i++)
|
||||
{
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
//Make a new particle
|
||||
if ( random->RandomInt( 0, 2 ) == 0 )
|
||||
{
|
||||
float ranx = random->RandomFloat( -28.0f, 28.0f );
|
||||
float rany = random->RandomFloat( -28.0f, 28.0f );
|
||||
float ranz = random->RandomFloat( -28.0f, 28.0f );
|
||||
|
||||
Vector vNewPos = GetAbsOrigin();
|
||||
Vector vAdd = Vector(GetAbsAngles().x,GetAbsAngles().y,GetAbsAngles().z)*random->RandomFloat(-60,120);
|
||||
vNewPos += vAdd;
|
||||
|
||||
sParticle = (SimpleParticle *) m_pFirePlasmaSpray->AddParticle( sizeof(SimpleParticle), handle, vNewPos );
|
||||
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
sParticle->m_flDieTime = PLASMASPARK_LIFETIME;
|
||||
|
||||
sParticle->m_vecVelocity = GetAbsVelocity();
|
||||
sParticle->m_vecVelocity.x += ranx;
|
||||
sParticle->m_vecVelocity.y += rany;
|
||||
sParticle->m_vecVelocity.z += ranz;
|
||||
m_pFirePlasmaSpray->m_pOwner = this;
|
||||
}
|
||||
}
|
||||
|
||||
SetNextClientThink(gpGlobals->curtime + 0.05);
|
||||
}
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_PlasmaBeamNode, DT_PlasmaBeamNode, CPlasmaBeamNode )
|
||||
RecvPropVector (RECVINFO(m_vecVelocity), 0, RecvProxy_LocalVelocity),
|
||||
RecvPropInt (RECVINFO(m_bSprayOn)),
|
||||
END_RECV_TABLE()
|
||||
340
sp/src/game/client/hl2/c_prop_combine_ball.cpp
Normal file
340
sp/src/game/client/hl2/c_prop_combine_ball.cpp
Normal file
@@ -0,0 +1,340 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_prop_combine_ball.h"
|
||||
#include "materialsystem/imaterial.h"
|
||||
#include "model_types.h"
|
||||
#include "c_physicsprop.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#include "fx_quad.h"
|
||||
#include "fx.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
#include "view.h"
|
||||
#include "view_scene.h"
|
||||
#include "beamdraw.h"
|
||||
|
||||
// Precache our effects
|
||||
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectCombineBall )
|
||||
CLIENTEFFECT_MATERIAL( "effects/ar2_altfire1" )
|
||||
CLIENTEFFECT_MATERIAL( "effects/ar2_altfire1b" )
|
||||
CLIENTEFFECT_MATERIAL( "effects/combinemuzzle1_nocull" )
|
||||
CLIENTEFFECT_MATERIAL( "effects/combinemuzzle2_nocull" )
|
||||
CLIENTEFFECT_MATERIAL( "effects/combinemuzzle1" )
|
||||
CLIENTEFFECT_MATERIAL( "effects/ar2_altfire1" )
|
||||
CLIENTEFFECT_MATERIAL( "effects/ar2_altfire1b" )
|
||||
CLIENTEFFECT_REGISTER_END()
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_PropCombineBall, DT_PropCombineBall, CPropCombineBall )
|
||||
RecvPropBool( RECVINFO( m_bEmit ) ),
|
||||
RecvPropFloat( RECVINFO( m_flRadius ) ),
|
||||
RecvPropBool( RECVINFO( m_bHeld ) ),
|
||||
RecvPropBool( RECVINFO( m_bLaunched ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_PropCombineBall::C_PropCombineBall( void )
|
||||
{
|
||||
m_pFlickerMaterial = NULL;
|
||||
m_pBodyMaterial = NULL;
|
||||
m_pBlurMaterial = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCombineBall::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
m_vecLastOrigin = GetAbsOrigin();
|
||||
InitMaterials();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : RenderGroup_t
|
||||
//-----------------------------------------------------------------------------
|
||||
RenderGroup_t C_PropCombineBall::GetRenderGroup( void )
|
||||
{
|
||||
return RENDER_GROUP_TRANSLUCENT_ENTITY;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Cache the material handles
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool C_PropCombineBall::InitMaterials( void )
|
||||
{
|
||||
// Motion blur
|
||||
if ( m_pBlurMaterial == NULL )
|
||||
{
|
||||
m_pBlurMaterial = materials->FindMaterial( "effects/ar2_altfire1b", NULL, false );
|
||||
|
||||
if ( m_pBlurMaterial == NULL )
|
||||
return false;
|
||||
}
|
||||
|
||||
// Main body of the ball
|
||||
if ( m_pBodyMaterial == NULL )
|
||||
{
|
||||
m_pBodyMaterial = materials->FindMaterial( "effects/ar2_altfire1", NULL, false );
|
||||
|
||||
if ( m_pBodyMaterial == NULL )
|
||||
return false;
|
||||
}
|
||||
|
||||
// Flicker material
|
||||
if ( m_pFlickerMaterial == NULL )
|
||||
{
|
||||
m_pFlickerMaterial = materials->FindMaterial( "effects/combinemuzzle1", NULL, false );
|
||||
|
||||
if ( m_pFlickerMaterial == NULL )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCombineBall::DrawMotionBlur( void )
|
||||
{
|
||||
float color[3];
|
||||
|
||||
Vector vecDir = GetAbsOrigin() - m_vecLastOrigin;
|
||||
float speed = VectorNormalize( vecDir );
|
||||
|
||||
speed = clamp( speed, 0, 32 );
|
||||
|
||||
float stepSize = MIN( ( speed * 0.5f ), 4.0f );
|
||||
|
||||
Vector spawnPos = GetAbsOrigin();
|
||||
Vector spawnStep = -vecDir * stepSize;
|
||||
|
||||
float base = RemapValClamped( speed, 4, 32, 0.0f, 1.0f );
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->Bind( m_pBlurMaterial );
|
||||
|
||||
// Draw the motion blurred trail
|
||||
for ( int i = 0; i < 8; i++ )
|
||||
{
|
||||
spawnPos += spawnStep;
|
||||
|
||||
color[0] = color[1] = color[2] = base * ( 1.0f - ( (float) i / 12.0f ) );
|
||||
|
||||
DrawHalo( m_pBlurMaterial, spawnPos, m_flRadius, color );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCombineBall::DrawFlicker( void )
|
||||
{
|
||||
float rand1 = random->RandomFloat( 0.2f, 0.3f );
|
||||
float rand2 = random->RandomFloat( 1.5f, 2.5f );
|
||||
|
||||
if ( gpGlobals->frametime == 0.0f )
|
||||
{
|
||||
rand1 = 0.2f;
|
||||
rand2 = 1.5f;
|
||||
}
|
||||
|
||||
float color[3];
|
||||
color[0] = color[1] = color[2] = rand1;
|
||||
|
||||
// Draw the flickering glow
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->Bind( m_pFlickerMaterial );
|
||||
DrawHalo( m_pFlickerMaterial, GetAbsOrigin(), m_flRadius * rand2, color );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : pMaterial -
|
||||
// source -
|
||||
// color -
|
||||
//-----------------------------------------------------------------------------
|
||||
void DrawHaloOriented( const Vector& source, float scale, float const *color, float roll )
|
||||
{
|
||||
Vector point, screen;
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
IMesh* pMesh = pRenderContext->GetDynamicMesh();
|
||||
|
||||
CMeshBuilder meshBuilder;
|
||||
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
|
||||
|
||||
// Transform source into screen space
|
||||
ScreenTransform( source, screen );
|
||||
|
||||
Vector right, up;
|
||||
float sr, cr;
|
||||
|
||||
SinCos( roll, &sr, &cr );
|
||||
|
||||
for ( int i = 0; i < 3; i++ )
|
||||
{
|
||||
right[i] = CurrentViewRight()[i] * cr + CurrentViewUp()[i] * sr;
|
||||
up[i] = CurrentViewRight()[i] * -sr + CurrentViewUp()[i] * cr;
|
||||
}
|
||||
|
||||
meshBuilder.Color3fv (color);
|
||||
meshBuilder.TexCoord2f (0, 0, 1);
|
||||
VectorMA (source, -scale, up, point);
|
||||
VectorMA (point, -scale, right, point);
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color3fv (color);
|
||||
meshBuilder.TexCoord2f (0, 0, 0);
|
||||
VectorMA (source, scale, up, point);
|
||||
VectorMA (point, -scale, right, point);
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color3fv (color);
|
||||
meshBuilder.TexCoord2f (0, 1, 0);
|
||||
VectorMA (source, scale, up, point);
|
||||
VectorMA (point, scale, right, point);
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color3fv (color);
|
||||
meshBuilder.TexCoord2f (0, 1, 1);
|
||||
VectorMA (source, -scale, up, point);
|
||||
VectorMA (point, scale, right, point);
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.End();
|
||||
pMesh->Draw();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flags -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_PropCombineBall::DrawModel( int flags )
|
||||
{
|
||||
if ( !m_bEmit )
|
||||
return 0;
|
||||
|
||||
// Make sure our materials are cached
|
||||
if ( !InitMaterials() )
|
||||
{
|
||||
//NOTENOTE: This means that a material was not found for the combine ball, so it may not render!
|
||||
AssertOnce( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Draw the flickering overlay
|
||||
DrawFlicker();
|
||||
|
||||
// Draw the motion blur from movement
|
||||
if ( m_bHeld || m_bLaunched )
|
||||
{
|
||||
DrawMotionBlur();
|
||||
}
|
||||
|
||||
// Draw the model if we're being held
|
||||
if ( m_bHeld )
|
||||
{
|
||||
QAngle angles;
|
||||
VectorAngles( -CurrentViewForward(), angles );
|
||||
|
||||
// Always orient towards the camera!
|
||||
SetAbsAngles( angles );
|
||||
|
||||
BaseClass::DrawModel( flags );
|
||||
}
|
||||
else
|
||||
{
|
||||
float color[3];
|
||||
color[0] = color[1] = color[2] = 1.0f;
|
||||
|
||||
float sinOffs = 1.0f * sin( gpGlobals->curtime * 25 );
|
||||
|
||||
float roll = SpawnTime();
|
||||
|
||||
// Draw the main ball body
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->Bind( m_pBodyMaterial, (C_BaseEntity*) this );
|
||||
DrawHaloOriented( GetAbsOrigin(), m_flRadius + sinOffs, color, roll );
|
||||
}
|
||||
|
||||
m_vecLastOrigin = GetAbsOrigin();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &data -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CombineBallImpactCallback( const CEffectData &data )
|
||||
{
|
||||
// Quick flash
|
||||
FX_AddQuad( data.m_vOrigin,
|
||||
data.m_vNormal,
|
||||
data.m_flRadius * 10.0f,
|
||||
0,
|
||||
0.75f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.4f,
|
||||
random->RandomInt( 0, 360 ),
|
||||
0,
|
||||
Vector( 1.0f, 1.0f, 1.0f ),
|
||||
0.25f,
|
||||
"effects/combinemuzzle1_nocull",
|
||||
(FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) );
|
||||
|
||||
// Lingering burn
|
||||
FX_AddQuad( data.m_vOrigin,
|
||||
data.m_vNormal,
|
||||
data.m_flRadius * 2.0f,
|
||||
data.m_flRadius * 4.0f,
|
||||
0.75f,
|
||||
1.0f,
|
||||
0.0f,
|
||||
0.4f,
|
||||
random->RandomInt( 0, 360 ),
|
||||
0,
|
||||
Vector( 1.0f, 1.0f, 1.0f ),
|
||||
0.5f,
|
||||
"effects/combinemuzzle2_nocull",
|
||||
(FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) );
|
||||
|
||||
// Throw sparks
|
||||
FX_ElectricSpark( data.m_vOrigin, 2, 1, &data.m_vNormal );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "cball_bounce", CombineBallImpactCallback );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &data -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CombineBallExplosionCallback( const CEffectData &data )
|
||||
{
|
||||
Vector normal(0,0,1);
|
||||
|
||||
// Throw sparks
|
||||
FX_ElectricSpark( data.m_vOrigin, 4, 1, &normal );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "cball_explode", CombineBallExplosionCallback );
|
||||
45
sp/src/game/client/hl2/c_prop_combine_ball.h
Normal file
45
sp/src/game/client/hl2/c_prop_combine_ball.h
Normal file
@@ -0,0 +1,45 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef CPROPCOMBINEBALL_H_
|
||||
#define CPROPCOMBINEBALL_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
class C_PropCombineBall : public C_BaseAnimating
|
||||
{
|
||||
DECLARE_CLASS( C_PropCombineBall, C_BaseAnimating );
|
||||
DECLARE_CLIENTCLASS();
|
||||
public:
|
||||
|
||||
C_PropCombineBall( void );
|
||||
|
||||
virtual RenderGroup_t GetRenderGroup( void );
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual int DrawModel( int flags );
|
||||
|
||||
protected:
|
||||
|
||||
void DrawMotionBlur( void );
|
||||
void DrawFlicker( void );
|
||||
virtual bool InitMaterials( void );
|
||||
|
||||
Vector m_vecLastOrigin;
|
||||
bool m_bEmit;
|
||||
float m_flRadius;
|
||||
bool m_bHeld;
|
||||
bool m_bLaunched;
|
||||
|
||||
IMaterial *m_pFlickerMaterial;
|
||||
IMaterial *m_pBodyMaterial;
|
||||
IMaterial *m_pBlurMaterial;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
306
sp/src/game/client/hl2/c_rotorwash.cpp
Normal file
306
sp/src/game/client/hl2/c_rotorwash.cpp
Normal file
@@ -0,0 +1,306 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "particlemgr.h"
|
||||
#include "particle_prototype.h"
|
||||
#include "particle_util.h"
|
||||
#include "c_te_particlesystem.h"
|
||||
#include "fx.h"
|
||||
#include "fx_quad.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// ==============================================
|
||||
// Rotorwash particle emitter
|
||||
// ==============================================
|
||||
|
||||
#ifndef _XBOX
|
||||
|
||||
class WashEmitter : public CSimpleEmitter
|
||||
{
|
||||
public:
|
||||
|
||||
WashEmitter( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
|
||||
|
||||
static WashEmitter *Create( const char *pDebugName )
|
||||
{
|
||||
return new WashEmitter( pDebugName );
|
||||
}
|
||||
|
||||
void UpdateVelocity( SimpleParticle *pParticle, float timeDelta )
|
||||
{
|
||||
// Float up when lifetime is half gone.
|
||||
pParticle->m_vecVelocity[ 2 ] += 64 * timeDelta;
|
||||
|
||||
// FIXME: optimize this....
|
||||
pParticle->m_vecVelocity *= ExponentialDecay( 0.8, 0.05, timeDelta );
|
||||
}
|
||||
|
||||
virtual float UpdateRoll( SimpleParticle *pParticle, float timeDelta )
|
||||
{
|
||||
pParticle->m_flRoll += pParticle->m_flRollDelta * timeDelta;
|
||||
|
||||
pParticle->m_flRollDelta += pParticle->m_flRollDelta * ( timeDelta * -2.0f );
|
||||
|
||||
//Cap the minimum roll
|
||||
if ( fabs( pParticle->m_flRollDelta ) < 0.5f )
|
||||
{
|
||||
pParticle->m_flRollDelta = ( pParticle->m_flRollDelta > 0.0f ) ? 0.5f : -0.5f;
|
||||
}
|
||||
|
||||
return pParticle->m_flRoll;
|
||||
}
|
||||
|
||||
virtual float UpdateAlpha( const SimpleParticle *pParticle )
|
||||
{
|
||||
return ( ((float)pParticle->m_uchStartAlpha/255.0f) * sin( M_PI * (pParticle->m_flLifetime / pParticle->m_flDieTime) ) );
|
||||
}
|
||||
|
||||
private:
|
||||
WashEmitter( const WashEmitter & );
|
||||
};
|
||||
|
||||
#endif // !_XBOX
|
||||
|
||||
// ==============================================
|
||||
// Rotorwash entity
|
||||
// ==============================================
|
||||
|
||||
#define ROTORWASH_THINK_INTERVAL 0.1f
|
||||
|
||||
class C_RotorWashEmitter : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
|
||||
DECLARE_CLASS( C_RotorWashEmitter, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_RotorWashEmitter( void );
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual void ClientThink( void );
|
||||
|
||||
protected:
|
||||
|
||||
float m_flAltitude;
|
||||
|
||||
PMaterialHandle m_hWaterMaterial[2];
|
||||
|
||||
#ifndef _XBOX
|
||||
void InitSpawner( void );
|
||||
CSmartPtr<WashEmitter> m_pSimple;
|
||||
#endif // !XBOX
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_RotorWashEmitter, DT_RotorWashEmitter, CRotorWashEmitter)
|
||||
RecvPropFloat(RECVINFO(m_flAltitude)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_RotorWashEmitter::C_RotorWashEmitter( void )
|
||||
{
|
||||
#ifndef _XBOX
|
||||
m_pSimple = NULL;
|
||||
m_hWaterMaterial[0] = NULL;
|
||||
m_hWaterMaterial[1] = NULL;
|
||||
#endif // !_XBOX
|
||||
}
|
||||
|
||||
#ifndef _XBOX
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_RotorWashEmitter::InitSpawner( void )
|
||||
{
|
||||
if ( m_pSimple.IsValid() )
|
||||
return;
|
||||
|
||||
m_pSimple = WashEmitter::Create( "wash" );
|
||||
m_pSimple->SetNearClip( 128, 256 );
|
||||
}
|
||||
#endif // !XBOX
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_RotorWashEmitter::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
SetNextClientThink( gpGlobals->curtime + ROTORWASH_THINK_INTERVAL );
|
||||
|
||||
#ifndef _XBOX
|
||||
InitSpawner();
|
||||
#endif // !XBOX
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_RotorWashEmitter::ClientThink( void )
|
||||
{
|
||||
SetNextClientThink( gpGlobals->curtime + ROTORWASH_THINK_INTERVAL );
|
||||
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin()+(Vector(0, 0, -1024)), (MASK_SOLID_BRUSHONLY|CONTENTS_WATER|CONTENTS_SLIME), NULL, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( /*!m_bIgnoreSolid && */(tr.fraction == 1.0f || tr.startsolid || tr.allsolid) )
|
||||
return;
|
||||
|
||||
// If we hit the skybox, don't do it either
|
||||
if ( tr.surface.flags & SURF_SKY )
|
||||
return;
|
||||
|
||||
float heightScale = RemapValClamped( tr.fraction * 1024, 512, 1024, 1.0f, 0.0f );
|
||||
|
||||
Vector vecDustColor;
|
||||
|
||||
if ( tr.contents & CONTENTS_WATER )
|
||||
{
|
||||
vecDustColor.x = 0.8f;
|
||||
vecDustColor.y = 0.8f;
|
||||
vecDustColor.z = 0.75f;
|
||||
}
|
||||
else if ( tr.contents & CONTENTS_SLIME )
|
||||
{
|
||||
vecDustColor.x = 0.6f;
|
||||
vecDustColor.y = 0.5f;
|
||||
vecDustColor.z = 0.15f;
|
||||
}
|
||||
else
|
||||
{
|
||||
vecDustColor.x = 0.35f;
|
||||
vecDustColor.y = 0.3f;
|
||||
vecDustColor.z = 0.25f;
|
||||
}
|
||||
|
||||
#ifndef _XBOX
|
||||
|
||||
InitSpawner();
|
||||
|
||||
if ( m_pSimple.IsValid() == false )
|
||||
return;
|
||||
|
||||
m_pSimple->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
PMaterialHandle *hMaterial;
|
||||
|
||||
// Cache and set our material based on the surface we're over (ie. water)
|
||||
if ( tr.contents & (CONTENTS_WATER|CONTENTS_SLIME) )
|
||||
{
|
||||
if ( m_hWaterMaterial[0] == NULL )
|
||||
{
|
||||
m_hWaterMaterial[0] = m_pSimple->GetPMaterial("effects/splash1");
|
||||
m_hWaterMaterial[1] = m_pSimple->GetPMaterial("effects/splash2");
|
||||
}
|
||||
hMaterial = m_hWaterMaterial;
|
||||
}
|
||||
else
|
||||
{
|
||||
hMaterial = g_Mat_DustPuff;
|
||||
}
|
||||
|
||||
#endif // !XBOX
|
||||
|
||||
// If we're above water, make ripples
|
||||
if ( tr.contents & (CONTENTS_WATER|CONTENTS_SLIME) )
|
||||
{
|
||||
float flScale = random->RandomFloat( 7.5f, 8.5f );
|
||||
|
||||
Vector color = Vector( 0.8f, 0.8f, 0.75f );
|
||||
Vector startPos = tr.endpos + Vector(0,0,8);
|
||||
Vector endPos = tr.endpos + Vector(0,0,-64);
|
||||
|
||||
if ( tr.fraction < 1.0f )
|
||||
{
|
||||
//Add a ripple quad to the surface
|
||||
FX_AddQuad( tr.endpos + ( tr.plane.normal * 0.5f ),
|
||||
tr.plane.normal,
|
||||
64.0f * flScale,
|
||||
128.0f * flScale,
|
||||
0.8f,
|
||||
0.75f * heightScale,
|
||||
0.0f,
|
||||
0.75f,
|
||||
random->RandomFloat( 0, 360 ),
|
||||
random->RandomFloat( -2.0f, 2.0f ),
|
||||
vecDustColor,
|
||||
0.2f,
|
||||
"effects/splashwake3",
|
||||
(FXQUAD_BIAS_SCALE|FXQUAD_BIAS_ALPHA) );
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _XBOX
|
||||
int numRingSprites = 32;
|
||||
float yaw = random->RandomFloat( 0, 2*M_PI ); // Randomly placed on the unit circle
|
||||
float yawIncr = (2*M_PI) / numRingSprites;
|
||||
Vector vecForward;
|
||||
Vector offset;
|
||||
SimpleParticle *pParticle;
|
||||
|
||||
// Draw the rings
|
||||
for ( int i = 0; i < numRingSprites; i++ )
|
||||
{
|
||||
// Get our x,y on the unit circle
|
||||
SinCos( yaw, &vecForward.y, &vecForward.x );
|
||||
|
||||
// Increment ahead
|
||||
yaw += yawIncr;
|
||||
|
||||
// @NOTE toml (3-28-07): broke out following expression because vc2005 optimizer was screwing up in presence of SinCos inline assembly. Would also
|
||||
// go away if offset were referenced below as in the AddLineOverlay()
|
||||
//offset = ( RandomVector( -4.0f, 4.0f ) + tr.endpos ) + ( vecForward * 128.0f );
|
||||
|
||||
offset = vecForward * 128.0f;
|
||||
offset += tr.endpos + RandomVector( -4.0f, 4.0f );
|
||||
|
||||
|
||||
pParticle = (SimpleParticle *) m_pSimple->AddParticle( sizeof(SimpleParticle), hMaterial[random->RandomInt(0,1)], offset );
|
||||
|
||||
if ( pParticle != NULL )
|
||||
{
|
||||
pParticle->m_flLifetime = 0.0f;
|
||||
pParticle->m_flDieTime = random->RandomFloat( 0.25f, 1.0f );
|
||||
|
||||
pParticle->m_vecVelocity = vecForward * random->RandomFloat( 1000, 1500 );
|
||||
|
||||
#if __EXPLOSION_DEBUG
|
||||
debugoverlay->AddLineOverlay( m_vecOrigin, m_vecOrigin + pParticle->m_vecVelocity, 255, 0, 0, false, 3 );
|
||||
#endif
|
||||
|
||||
if ( tr.contents & CONTENTS_SLIME )
|
||||
{
|
||||
vecDustColor.x = random->RandomFloat( 0.4f, 0.6f );
|
||||
vecDustColor.y = random->RandomFloat( 0.3f, 0.5f );
|
||||
vecDustColor.z = random->RandomFloat( 0.1f, 0.2f );
|
||||
}
|
||||
|
||||
pParticle->m_uchColor[0] = vecDustColor.x * 255.0f;
|
||||
pParticle->m_uchColor[1] = vecDustColor.y * 255.0f;
|
||||
pParticle->m_uchColor[2] = vecDustColor.z * 255.0f;
|
||||
|
||||
pParticle->m_uchStartSize = random->RandomInt( 16, 64 );
|
||||
pParticle->m_uchEndSize = pParticle->m_uchStartSize * 4;
|
||||
|
||||
pParticle->m_uchStartAlpha = random->RandomFloat( 16, 32 ) * heightScale;
|
||||
pParticle->m_uchEndAlpha = 0;
|
||||
|
||||
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
pParticle->m_flRollDelta = random->RandomFloat( -16.0f, 16.0f );
|
||||
}
|
||||
}
|
||||
#endif // !XBOX
|
||||
}
|
||||
502
sp/src/game/client/hl2/c_script_intro.cpp
Normal file
502
sp/src/game/client/hl2/c_script_intro.cpp
Normal file
@@ -0,0 +1,502 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "shareddefs.h"
|
||||
#include "materialsystem/imesh.h"
|
||||
#include "view.h"
|
||||
#include "iviewrender.h"
|
||||
#include "view_shared.h"
|
||||
#include "viewrender.h"
|
||||
#ifdef MAPBASE
|
||||
#include "c_point_camera.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern IntroData_t *g_pIntroData;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_ScriptIntro : public C_BaseEntity
|
||||
{
|
||||
DECLARE_CLASS( C_ScriptIntro, C_BaseEntity );
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ScriptIntro( void );
|
||||
~C_ScriptIntro( void );
|
||||
void PostDataUpdate( DataUpdateType_t updateType );
|
||||
void ClientThink( void );
|
||||
void CalculateFOV( void );
|
||||
void CalculateAlpha( void );
|
||||
|
||||
public:
|
||||
int m_iNextFOV;
|
||||
int m_iFOV;
|
||||
int m_iPrevFOV;
|
||||
int m_iStartFOV;
|
||||
float m_flNextFOVBlendTime;
|
||||
float m_flFOVBlendStartTime;
|
||||
bool m_bAlternateFOV;
|
||||
|
||||
// Our intro data block
|
||||
IntroData_t m_IntroData;
|
||||
|
||||
private:
|
||||
Vector m_vecCameraView;
|
||||
QAngle m_vecCameraViewAngles;
|
||||
int m_iBlendMode;
|
||||
int m_iNextBlendMode;
|
||||
float m_flNextBlendTime;
|
||||
float m_flBlendStartTime;
|
||||
bool m_bActive;
|
||||
EHANDLE m_hCameraEntity;
|
||||
#ifdef MAPBASE
|
||||
bool m_bDrawSky;
|
||||
bool m_bDrawSky2;
|
||||
bool m_bUseEyePosition;
|
||||
#endif
|
||||
|
||||
// Fades
|
||||
float m_flFadeColor[3]; // Server's desired fade color
|
||||
float m_flFadeAlpha; // Server's desired fade alpha
|
||||
float m_flPrevServerFadeAlpha; // Previous server's desired fade alpha
|
||||
float m_flFadeDuration; // Time it should take to reach the server's new fade alpha
|
||||
float m_flFadeTimeStartedAt; // Time at which we last recieved a new desired fade alpha
|
||||
float m_flFadeAlphaStartedAt; // Alpha at which we last received a new desired fade alpha
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ScriptIntro, DT_ScriptIntro, CScriptIntro )
|
||||
RecvPropVector( RECVINFO( m_vecCameraView ) ),
|
||||
RecvPropVector( RECVINFO( m_vecCameraViewAngles ) ),
|
||||
RecvPropInt( RECVINFO( m_iBlendMode ) ),
|
||||
RecvPropInt( RECVINFO( m_iNextBlendMode ) ),
|
||||
RecvPropFloat( RECVINFO( m_flNextBlendTime ) ),
|
||||
RecvPropFloat( RECVINFO( m_flBlendStartTime ) ),
|
||||
RecvPropBool( RECVINFO( m_bActive ) ),
|
||||
#ifdef MAPBASE
|
||||
RecvPropBool( RECVINFO( m_bDrawSky ) ),
|
||||
RecvPropBool( RECVINFO( m_bDrawSky2 ) ),
|
||||
RecvPropBool( RECVINFO( m_bUseEyePosition ) ),
|
||||
#endif
|
||||
|
||||
// Fov & fov blends
|
||||
RecvPropInt( RECVINFO( m_iFOV ) ),
|
||||
RecvPropInt( RECVINFO( m_iNextFOV ) ),
|
||||
RecvPropInt( RECVINFO( m_iStartFOV ) ),
|
||||
RecvPropFloat( RECVINFO( m_flNextFOVBlendTime ) ),
|
||||
RecvPropFloat( RECVINFO( m_flFOVBlendStartTime ) ),
|
||||
RecvPropBool( RECVINFO( m_bAlternateFOV ) ),
|
||||
|
||||
// Fades
|
||||
RecvPropFloat( RECVINFO( m_flFadeAlpha ) ),
|
||||
RecvPropArray( RecvPropFloat( RECVINFO( m_flFadeColor[0] ) ), m_flFadeColor ),
|
||||
RecvPropFloat( RECVINFO( m_flFadeDuration ) ),
|
||||
RecvPropEHandle(RECVINFO(m_hCameraEntity)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_ScriptIntro::C_ScriptIntro( void )
|
||||
{
|
||||
m_bActive = false;
|
||||
m_vecCameraView = vec3_origin;
|
||||
m_vecCameraViewAngles = vec3_angle;
|
||||
m_iBlendMode = 0;
|
||||
m_iNextBlendMode = 0;
|
||||
m_flNextBlendTime = 0;
|
||||
m_flBlendStartTime = 0;
|
||||
m_IntroData.m_playerViewFOV = 0;
|
||||
m_flFadeAlpha = 0;
|
||||
m_flPrevServerFadeAlpha = 0;
|
||||
m_flFadeDuration = 0;
|
||||
m_flFadeTimeStartedAt = 0;
|
||||
m_flFadeAlphaStartedAt = 0;
|
||||
m_hCameraEntity = NULL;
|
||||
m_iPrevFOV = 0;
|
||||
m_iStartFOV = 0;
|
||||
|
||||
g_pIntroData = NULL;
|
||||
|
||||
// Setup fade colors
|
||||
m_IntroData.m_flCurrentFadeColor[0] = m_flFadeColor[0];
|
||||
m_IntroData.m_flCurrentFadeColor[1] = m_flFadeColor[1];
|
||||
m_IntroData.m_flCurrentFadeColor[2] = m_flFadeColor[2];
|
||||
m_IntroData.m_flCurrentFadeColor[3] = m_flFadeAlpha;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_ScriptIntro::~C_ScriptIntro( void )
|
||||
{
|
||||
g_pIntroData = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ScriptIntro::PostDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::PostDataUpdate( updateType );
|
||||
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
|
||||
// Fill out the intro data
|
||||
m_IntroData.m_vecCameraView = m_vecCameraView;
|
||||
m_IntroData.m_vecCameraViewAngles = m_vecCameraViewAngles;
|
||||
m_IntroData.m_Passes.SetCount( 0 );
|
||||
|
||||
#ifdef MAPBASE
|
||||
m_IntroData.m_bDrawSky = m_bDrawSky;
|
||||
#endif
|
||||
|
||||
// Find/Create our first pass
|
||||
IntroDataBlendPass_t *pass1;
|
||||
if ( m_IntroData.m_Passes.Count() == 0 )
|
||||
{
|
||||
pass1 = &m_IntroData.m_Passes[m_IntroData.m_Passes.AddToTail()];
|
||||
}
|
||||
else
|
||||
{
|
||||
pass1 = &m_IntroData.m_Passes[0];
|
||||
}
|
||||
Assert(pass1);
|
||||
pass1->m_BlendMode = m_iBlendMode;
|
||||
pass1->m_Alpha = 1.0f;
|
||||
|
||||
if ( m_vecCameraView == vec3_origin )
|
||||
{
|
||||
m_IntroData.m_bDrawPrimary = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IntroData.m_bDrawPrimary = true;
|
||||
#ifdef MAPBASE
|
||||
m_IntroData.m_bDrawSky2 = m_bDrawSky2;
|
||||
|
||||
// If it's a point_camera and it's ortho, send it to the intro data
|
||||
// Change this code if the purpose of m_hCameraEntity in intro data ever goes beyond ortho
|
||||
if ( m_hCameraEntity && Q_strncmp(m_hCameraEntity->GetClassname(), "point_camera", 12) == 0 )
|
||||
{
|
||||
C_PointCamera *pCamera = dynamic_cast<C_PointCamera*>(m_hCameraEntity.Get());
|
||||
if (pCamera && pCamera->IsOrtho())
|
||||
{
|
||||
m_IntroData.m_hCameraEntity = m_hCameraEntity;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// If we're currently blending to a new mode, set the second pass
|
||||
if ( m_flNextBlendTime > gpGlobals->curtime )
|
||||
{
|
||||
IntroDataBlendPass_t *pass2;
|
||||
if ( m_IntroData.m_Passes.Count() < 2 )
|
||||
{
|
||||
pass2 = &m_IntroData.m_Passes[m_IntroData.m_Passes.AddToTail()];
|
||||
|
||||
//Msg("STARTED BLEND: Mode %d to %d.\n", m_IntroData.m_Passes[0].m_BlendMode, m_iNextBlendMode );
|
||||
}
|
||||
else
|
||||
{
|
||||
pass2 = &m_IntroData.m_Passes[1];
|
||||
|
||||
Assert( pass2->m_BlendMode == m_iNextBlendMode );
|
||||
}
|
||||
Assert(pass2);
|
||||
pass2->m_BlendMode = m_iNextBlendMode;
|
||||
pass2->m_Alpha = 0.0f;
|
||||
}
|
||||
else if ( m_IntroData.m_Passes.Count() == 2 )
|
||||
{
|
||||
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
|
||||
if ( !player )
|
||||
return;
|
||||
|
||||
//Msg("FINISHED BLEND.\n");
|
||||
m_IntroData.m_Passes.Remove(1);
|
||||
}
|
||||
|
||||
// Set the introdata our data chunk
|
||||
if ( m_bActive )
|
||||
{
|
||||
g_pIntroData = &m_IntroData;
|
||||
}
|
||||
else if ( g_pIntroData == &m_IntroData )
|
||||
{
|
||||
g_pIntroData = NULL;
|
||||
}
|
||||
|
||||
// Update the fade color
|
||||
m_IntroData.m_flCurrentFadeColor[0] = m_flFadeColor[0];
|
||||
m_IntroData.m_flCurrentFadeColor[1] = m_flFadeColor[1];
|
||||
m_IntroData.m_flCurrentFadeColor[2] = m_flFadeColor[2];
|
||||
|
||||
// Started fading?
|
||||
if ( m_flFadeAlpha != m_flPrevServerFadeAlpha )
|
||||
{
|
||||
m_flFadeTimeStartedAt = gpGlobals->curtime;
|
||||
m_flFadeAlphaStartedAt = m_IntroData.m_flCurrentFadeColor[3];
|
||||
m_flPrevServerFadeAlpha = m_flFadeAlpha;
|
||||
|
||||
if ( !m_flFadeDuration )
|
||||
{
|
||||
m_flFadeDuration = 0.01;
|
||||
}
|
||||
|
||||
//Msg("STARTING NEW FADE: alpha %.2f, duration %.2f.\n", m_flFadeAlpha, m_flFadeDuration );
|
||||
}
|
||||
|
||||
if ( m_iPrevFOV != m_iFOV )
|
||||
{
|
||||
m_IntroData.m_playerViewFOV = m_iFOV;
|
||||
m_iPrevFOV = m_iFOV;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ScriptIntro::ClientThink( void )
|
||||
{
|
||||
Assert( m_IntroData.m_Passes.Count() <= 2 );
|
||||
|
||||
if ( m_hCameraEntity )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if ( m_bUseEyePosition )
|
||||
{
|
||||
m_hCameraEntity->GetEyePosition( m_IntroData.m_vecCameraView, m_IntroData.m_vecCameraViewAngles );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IntroData.m_vecCameraView = m_hCameraEntity->GetAbsOrigin();
|
||||
m_IntroData.m_vecCameraViewAngles = m_hCameraEntity->GetAbsAngles();
|
||||
}
|
||||
#else
|
||||
m_IntroData.m_vecCameraView = m_hCameraEntity->GetAbsOrigin();
|
||||
m_IntroData.m_vecCameraViewAngles = m_hCameraEntity->GetAbsAngles();
|
||||
#endif
|
||||
}
|
||||
|
||||
CalculateFOV();
|
||||
CalculateAlpha();
|
||||
|
||||
// Calculate the blend levels of each pass
|
||||
float flPerc = 1.0;
|
||||
if ( (m_flNextBlendTime - m_flBlendStartTime) != 0 )
|
||||
{
|
||||
flPerc = clamp( (gpGlobals->curtime - m_flBlendStartTime) / (m_flNextBlendTime - m_flBlendStartTime), 0, 1 );
|
||||
}
|
||||
|
||||
// Detect when we're finished blending
|
||||
if ( flPerc >= 1.0 )
|
||||
{
|
||||
if ( m_IntroData.m_Passes.Count() == 2 )
|
||||
{
|
||||
// We're done blending
|
||||
m_IntroData.m_Passes[0].m_BlendMode = m_IntroData.m_Passes[1].m_BlendMode;
|
||||
m_IntroData.m_Passes[0].m_Alpha = 1.0;
|
||||
m_IntroData.m_Passes.Remove(1);
|
||||
|
||||
//Msg("FINISHED BLEND.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IntroData.m_Passes[0].m_Alpha = 1.0f;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
if ( m_flNextBlendTime >= gpGlobals->curtime )
|
||||
{
|
||||
Msg("INTRO BLENDING: Blending from mode %d to %d.\n", m_IntroData.m_Passes[0].m_BlendMode, m_IntroData.m_Passes[1].m_BlendMode );
|
||||
Msg(" curtime %.2f StartedAt %.2f FinishAt: %.2f\n", gpGlobals->curtime, m_flBlendStartTime, m_flNextBlendTime );
|
||||
Msg(" Perc: %.2f\n", flPerc );
|
||||
}
|
||||
*/
|
||||
|
||||
if ( m_IntroData.m_Passes.Count() == 2 )
|
||||
{
|
||||
m_IntroData.m_Passes[0].m_Alpha = 1.0 - flPerc;
|
||||
m_IntroData.m_Passes[1].m_Alpha = flPerc;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IntroData.m_Passes[0].m_Alpha = 1.0 - flPerc;
|
||||
}
|
||||
}
|
||||
|
||||
extern float ScriptInfo_CalculateFOV( float flFOVBlendStartTime, float flNextFOVBlendTime, int nFOV, int nNextFOV, bool bSplineRamp );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ScriptIntro::CalculateFOV( void )
|
||||
{
|
||||
// We're past our blending time so we're at our target
|
||||
if ( m_flNextFOVBlendTime >= gpGlobals->curtime )
|
||||
{
|
||||
// Calculate where we're at
|
||||
m_IntroData.m_playerViewFOV = ScriptInfo_CalculateFOV( m_flFOVBlendStartTime, m_flNextFOVBlendTime, m_iStartFOV, m_iNextFOV, m_bAlternateFOV );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ScriptIntro::CalculateAlpha( void )
|
||||
{
|
||||
// Fill out the fade alpha
|
||||
float flNewAlpha = RemapValClamped( gpGlobals->curtime, m_flFadeTimeStartedAt, m_flFadeTimeStartedAt + m_flFadeDuration, m_flFadeAlphaStartedAt, m_flFadeAlpha );
|
||||
/*
|
||||
if ( m_IntroData.m_flCurrentFadeColor[3] != flNewAlpha )
|
||||
{
|
||||
Msg("INTRO FADING: curtime %.2f StartedAt %.2f Duration: %.2f\n", gpGlobals->curtime, m_flFadeTimeStartedAt, m_flFadeDuration );
|
||||
Msg(" TimePassed %.2f Alpha: %.2f\n", RemapValClamped( gpGlobals->curtime, m_flFadeTimeStartedAt, m_flFadeTimeStartedAt + m_flFadeDuration, 0.0, 1.0 ), m_IntroData.m_flCurrentFadeColor[3] );
|
||||
}
|
||||
*/
|
||||
|
||||
m_IntroData.m_flCurrentFadeColor[3] = flNewAlpha;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_PlayerViewProxy : public C_BaseEntity
|
||||
{
|
||||
DECLARE_CLASS( C_PlayerViewProxy, C_BaseEntity );
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
Vector EyePosition( void ); // position of eyes
|
||||
const QAngle &EyeAngles( void ); // Direction of eyes in world space
|
||||
void GetEyePosition( Vector &vecOrigin, QAngle &angAngles );
|
||||
const QAngle &LocalEyeAngles( void ); // Direction of eyes
|
||||
Vector EarPosition( void ); // position of ears
|
||||
|
||||
#ifdef MAPBASE_MP
|
||||
C_BasePlayer *GetPlayer() { return m_bEnabled ? (m_hPlayer.Get() ? m_hPlayer.Get() : C_BasePlayer::GetLocalPlayer()) : NULL; }
|
||||
#else
|
||||
C_BasePlayer *GetPlayer() { return m_bEnabled ? C_BasePlayer::GetLocalPlayer() : NULL; }
|
||||
#endif
|
||||
|
||||
public:
|
||||
#ifdef MAPBASE_MP
|
||||
CHandle<C_BasePlayer> m_hPlayer;
|
||||
#endif
|
||||
|
||||
bool m_bEnabled;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_PlayerViewProxy, DT_PlayerViewProxy, CPlayerViewProxy )
|
||||
#ifdef MAPBASE_MP
|
||||
RecvPropEHandle( RECVINFO( m_hPlayer ) ),
|
||||
#endif
|
||||
RecvPropBool( RECVINFO( m_bEnabled ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
Vector C_PlayerViewProxy::EyePosition( void )
|
||||
{
|
||||
C_BasePlayer *pPlayer = GetPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
//Vector vecPlayerOffset = m_hPlayer.Get()->EyePosition() - m_hPlayer.Get()->GetAbsOrigin();
|
||||
//return GetAbsOrigin() + vecPlayerOffset;
|
||||
|
||||
Vector vecOrigin;
|
||||
QAngle angAngles;
|
||||
float fldummy;
|
||||
pPlayer->CalcView( vecOrigin, angAngles, fldummy, fldummy, fldummy );
|
||||
|
||||
return GetAbsOrigin() + (vecOrigin - pPlayer->GetAbsOrigin());
|
||||
}
|
||||
else
|
||||
return BaseClass::EyePosition();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const QAngle &C_PlayerViewProxy::EyeAngles( void )
|
||||
{
|
||||
C_BasePlayer *pPlayer = GetPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
Vector vecOrigin;
|
||||
static QAngle angAngles;
|
||||
float fldummy;
|
||||
pPlayer->CalcView( vecOrigin, angAngles, fldummy, fldummy, fldummy );
|
||||
|
||||
angAngles = GetAbsAngles() + (angAngles - pPlayer->GetAbsAngles());
|
||||
return angAngles;
|
||||
|
||||
//return m_hPlayer.Get()->EyeAngles();
|
||||
}
|
||||
else
|
||||
return BaseClass::EyeAngles();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PlayerViewProxy::GetEyePosition( Vector &vecOrigin, QAngle &angAngles )
|
||||
{
|
||||
C_BasePlayer *pPlayer = GetPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
float fldummy;
|
||||
pPlayer->CalcView( vecOrigin, angAngles, fldummy, fldummy, fldummy );
|
||||
|
||||
vecOrigin = GetAbsOrigin() + (vecOrigin - pPlayer->GetAbsOrigin());
|
||||
angAngles = GetAbsAngles() + (angAngles - pPlayer->GetAbsAngles());
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseClass::GetEyePosition( vecOrigin, angAngles );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const QAngle &C_PlayerViewProxy::LocalEyeAngles( void )
|
||||
{
|
||||
C_BasePlayer *pPlayer = GetPlayer();
|
||||
if (pPlayer) {
|
||||
static QAngle angAngles;
|
||||
angAngles = GetAbsAngles() + (pPlayer->LocalEyeAngles() - pPlayer->GetAbsAngles());
|
||||
return angAngles;
|
||||
}
|
||||
else
|
||||
return BaseClass::LocalEyeAngles();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
Vector C_PlayerViewProxy::EarPosition( void )
|
||||
{
|
||||
C_BasePlayer *pPlayer = GetPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
Vector vecPlayerOffset = pPlayer->GetAbsOrigin() - pPlayer->EarPosition();
|
||||
return GetAbsOrigin() + vecPlayerOffset;
|
||||
}
|
||||
else
|
||||
return BaseClass::EarPosition();
|
||||
}
|
||||
#endif
|
||||
|
||||
1048
sp/src/game/client/hl2/c_strider.cpp
Normal file
1048
sp/src/game/client/hl2/c_strider.cpp
Normal file
File diff suppressed because it is too large
Load Diff
110
sp/src/game/client/hl2/c_te_concussiveexplosion.cpp
Normal file
110
sp/src/game/client/hl2/c_te_concussiveexplosion.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
#include "cbase.h"
|
||||
#include "c_te_particlesystem.h"
|
||||
#include "fx.h"
|
||||
#include "ragdollexplosionenumerator.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "toolframework_client.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Concussive explosion entity
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_TEConcussiveExplosion : public C_TEParticleSystem
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_TEConcussiveExplosion, C_TEParticleSystem );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual void PostDataUpdate( DataUpdateType_t updateType );
|
||||
|
||||
void AffectRagdolls( void );
|
||||
|
||||
Vector m_vecNormal;
|
||||
float m_flScale;
|
||||
int m_nRadius;
|
||||
int m_nMagnitude;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Networking
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CLIENTCLASS_EVENT_DT( C_TEConcussiveExplosion, DT_TEConcussiveExplosion, CTEConcussiveExplosion )
|
||||
RecvPropVector( RECVINFO(m_vecNormal)),
|
||||
RecvPropFloat( RECVINFO(m_flScale)),
|
||||
RecvPropInt( RECVINFO(m_nRadius)),
|
||||
RecvPropInt( RECVINFO(m_nMagnitude)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_TEConcussiveExplosion::AffectRagdolls( void )
|
||||
{
|
||||
if ( ( m_nRadius == 0 ) || ( m_nMagnitude == 0 ) )
|
||||
return;
|
||||
|
||||
CRagdollExplosionEnumerator ragdollEnum( m_vecOrigin, m_nRadius, m_nMagnitude );
|
||||
partition->EnumerateElementsInSphere( PARTITION_CLIENT_RESPONSIVE_EDICTS, m_vecOrigin, m_nRadius, false, &ragdollEnum );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Recording
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void RecordConcussiveExplosion( const Vector& start, const Vector &vecDirection )
|
||||
{
|
||||
if ( !ToolsEnabled() )
|
||||
return;
|
||||
|
||||
if ( clienttools->IsInRecordingMode() )
|
||||
{
|
||||
KeyValues *msg = new KeyValues( "TempEntity" );
|
||||
|
||||
msg->SetInt( "te", TE_CONCUSSIVE_EXPLOSION );
|
||||
msg->SetString( "name", "TE_ConcussiveExplosion" );
|
||||
msg->SetFloat( "time", gpGlobals->curtime );
|
||||
msg->SetFloat( "originx", start.x );
|
||||
msg->SetFloat( "originy", start.y );
|
||||
msg->SetFloat( "originz", start.z );
|
||||
msg->SetFloat( "directionx", vecDirection.x );
|
||||
msg->SetFloat( "directiony", vecDirection.y );
|
||||
msg->SetFloat( "directionz", vecDirection.z );
|
||||
|
||||
ToolFramework_PostToolMessage( HTOOLHANDLE_INVALID, msg );
|
||||
msg->deleteThis();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_TEConcussiveExplosion::PostDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
AffectRagdolls();
|
||||
|
||||
FX_ConcussiveExplosion( m_vecOrigin, m_vecNormal );
|
||||
RecordConcussiveExplosion( m_vecOrigin, m_vecNormal );
|
||||
}
|
||||
|
||||
void TE_ConcussiveExplosion( IRecipientFilter& filter, float delay, KeyValues *pKeyValues )
|
||||
{
|
||||
Vector vecOrigin, vecDirection;
|
||||
vecOrigin.x = pKeyValues->GetFloat( "originx" );
|
||||
vecOrigin.y = pKeyValues->GetFloat( "originy" );
|
||||
vecOrigin.z = pKeyValues->GetFloat( "originz" );
|
||||
vecDirection.x = pKeyValues->GetFloat( "directionx" );
|
||||
vecDirection.y = pKeyValues->GetFloat( "directiony" );
|
||||
vecDirection.z = pKeyValues->GetFloat( "directionz" );
|
||||
FX_ConcussiveExplosion( vecOrigin, vecDirection );
|
||||
}
|
||||
414
sp/src/game/client/hl2/c_te_flare.cpp
Normal file
414
sp/src/game/client/hl2/c_te_flare.cpp
Normal file
@@ -0,0 +1,414 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Flare effects
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
#include "particles_simple.h"
|
||||
#include "iefx.h"
|
||||
#include "dlight.h"
|
||||
#include "view.h"
|
||||
#include "fx.h"
|
||||
#include "clientsideeffects.h"
|
||||
#include "c_pixel_visibility.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//Precahce the effects
|
||||
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectFlares )
|
||||
CLIENTEFFECT_MATERIAL( "effects/redflare" )
|
||||
CLIENTEFFECT_MATERIAL( "effects/yellowflare" )
|
||||
CLIENTEFFECT_MATERIAL( "effects/yellowflare_noz" )
|
||||
CLIENTEFFECT_REGISTER_END()
|
||||
|
||||
class C_Flare : public C_BaseCombatCharacter, CSimpleEmitter
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_Flare, C_BaseCombatCharacter );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_Flare();
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
void Update( float timeDelta );
|
||||
void NotifyDestroyParticle( Particle* pParticle );
|
||||
void NotifyShouldTransmit( ShouldTransmitState_t state );
|
||||
void RestoreResources( void );
|
||||
|
||||
float m_flTimeBurnOut;
|
||||
float m_flScale;
|
||||
bool m_bLight;
|
||||
bool m_bSmoke;
|
||||
bool m_bPropFlare;
|
||||
pixelvis_handle_t m_queryHandle;
|
||||
|
||||
|
||||
private:
|
||||
C_Flare( const C_Flare & );
|
||||
TimedEvent m_teSmokeSpawn;
|
||||
|
||||
int m_iAttachment;
|
||||
|
||||
SimpleParticle *m_pParticle[2];
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_Flare, DT_Flare, CFlare )
|
||||
RecvPropFloat( RECVINFO( m_flTimeBurnOut ) ),
|
||||
RecvPropFloat( RECVINFO( m_flScale ) ),
|
||||
RecvPropInt( RECVINFO( m_bLight ) ),
|
||||
RecvPropInt( RECVINFO( m_bSmoke ) ),
|
||||
RecvPropInt( RECVINFO( m_bPropFlare ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_Flare::C_Flare() : CSimpleEmitter( "C_Flare" )
|
||||
{
|
||||
m_pParticle[0] = NULL;
|
||||
m_pParticle[1] = NULL;
|
||||
m_flTimeBurnOut = 0.0f;
|
||||
|
||||
m_bLight = true;
|
||||
m_bSmoke = true;
|
||||
m_bPropFlare = false;
|
||||
|
||||
SetDynamicallyAllocated( false );
|
||||
m_queryHandle = 0;
|
||||
|
||||
m_iAttachment = -1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : state -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_Flare::NotifyShouldTransmit( ShouldTransmitState_t state )
|
||||
{
|
||||
if ( state == SHOULDTRANSMIT_END )
|
||||
{
|
||||
AddEffects( EF_NODRAW );
|
||||
}
|
||||
else if ( state == SHOULDTRANSMIT_START )
|
||||
{
|
||||
RemoveEffects( EF_NODRAW );
|
||||
}
|
||||
|
||||
BaseClass::NotifyShouldTransmit( state );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : bool -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_Flare::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
SetSortOrigin( GetAbsOrigin() );
|
||||
if ( m_bSmoke )
|
||||
{
|
||||
m_teSmokeSpawn.Init( 8 );
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_Flare::RestoreResources( void )
|
||||
{
|
||||
if ( m_pParticle[0] == NULL )
|
||||
{
|
||||
m_pParticle[0] = (SimpleParticle *) AddParticle( sizeof( SimpleParticle ), GetPMaterial( "effects/redflare" ), GetAbsOrigin() );
|
||||
|
||||
if ( m_pParticle[0] != NULL )
|
||||
{
|
||||
m_pParticle[0]->m_uchColor[0] = m_pParticle[0]->m_uchColor[1] = m_pParticle[0]->m_uchColor[2] = 0;
|
||||
m_pParticle[0]->m_flRoll = random->RandomInt( 0, 360 );
|
||||
m_pParticle[0]->m_flRollDelta = random->RandomFloat( 1.0f, 4.0f );
|
||||
m_pParticle[0]->m_flLifetime = 0.0f;
|
||||
m_pParticle[0]->m_flDieTime = 10.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_pParticle[1] == NULL )
|
||||
{
|
||||
m_pParticle[1] = (SimpleParticle *) AddParticle( sizeof( SimpleParticle ), GetPMaterial( "effects/yellowflare_noz" ), GetAbsOrigin() );
|
||||
|
||||
if ( m_pParticle[1] != NULL )
|
||||
{
|
||||
m_pParticle[1]->m_uchColor[0] = m_pParticle[1]->m_uchColor[1] = m_pParticle[1]->m_uchColor[2] = 0;
|
||||
m_pParticle[1]->m_flRoll = random->RandomInt( 0, 360 );
|
||||
m_pParticle[1]->m_flRollDelta = random->RandomFloat( 1.0f, 4.0f );
|
||||
m_pParticle[1]->m_flLifetime = 0.0f;
|
||||
m_pParticle[1]->m_flDieTime = 10.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : pParticle -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_Flare::NotifyDestroyParticle( Particle* pParticle )
|
||||
{
|
||||
if ( pParticle == m_pParticle[0] )
|
||||
{
|
||||
m_pParticle[0] = NULL;
|
||||
}
|
||||
|
||||
if ( pParticle == m_pParticle[1] )
|
||||
{
|
||||
m_pParticle[1] = NULL;
|
||||
}
|
||||
|
||||
CSimpleEmitter::NotifyDestroyParticle( pParticle );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : timeDelta -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_Flare::Update( float timeDelta )
|
||||
{
|
||||
if ( !IsVisible() )
|
||||
return;
|
||||
|
||||
CSimpleEmitter::Update( timeDelta );
|
||||
|
||||
//Make sure our stored resources are up to date
|
||||
RestoreResources();
|
||||
|
||||
//Don't do this if the console is down
|
||||
if ( timeDelta <= 0.0f )
|
||||
return;
|
||||
|
||||
//Check for LOS
|
||||
pixelvis_queryparams_t params;
|
||||
params.Init(GetAbsOrigin());
|
||||
params.proxySize = 8.0f; // Inches
|
||||
|
||||
float visible = PixelVisibility_FractionVisible( params, &m_queryHandle );
|
||||
|
||||
float fColor;
|
||||
#ifdef HL2_CLIENT_DLL
|
||||
float baseScale = m_flScale;
|
||||
#else
|
||||
// NOTE!!! This is bigger by a factor of 1.2 to deal with fixing a bug from HL2. See dlight_t.h
|
||||
float baseScale = m_flScale * 1.2f;
|
||||
#endif
|
||||
|
||||
//Account for fading out
|
||||
if ( ( m_flTimeBurnOut != -1.0f ) && ( ( m_flTimeBurnOut - gpGlobals->curtime ) <= 10.0f ) )
|
||||
{
|
||||
baseScale *= ( ( m_flTimeBurnOut - gpGlobals->curtime ) / 10.0f );
|
||||
}
|
||||
|
||||
bool bVisible = (baseScale < 0.01f || visible == 0.0f) ? false : true;
|
||||
//Clamp the scale if vanished
|
||||
if ( !bVisible )
|
||||
{
|
||||
if ( m_pParticle[0] != NULL )
|
||||
{
|
||||
m_pParticle[0]->m_flDieTime = gpGlobals->curtime;
|
||||
m_pParticle[0]->m_uchStartSize = m_pParticle[0]->m_uchEndSize = 0;
|
||||
m_pParticle[0]->m_uchColor[0] = 0;
|
||||
m_pParticle[0]->m_uchColor[1] = 0;
|
||||
m_pParticle[0]->m_uchColor[2] = 0;
|
||||
}
|
||||
|
||||
if ( m_pParticle[1] != NULL )
|
||||
{
|
||||
m_pParticle[1]->m_flDieTime = gpGlobals->curtime;
|
||||
m_pParticle[1]->m_uchStartSize = m_pParticle[1]->m_uchEndSize = 0;
|
||||
m_pParticle[1]->m_uchColor[0] = 0;
|
||||
m_pParticle[1]->m_uchColor[1] = 0;
|
||||
m_pParticle[1]->m_uchColor[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( baseScale < 0.01f )
|
||||
return;
|
||||
//
|
||||
// Dynamic light
|
||||
//
|
||||
|
||||
if ( m_bLight )
|
||||
{
|
||||
dlight_t *dl= effects->CL_AllocDlight( index );
|
||||
|
||||
|
||||
|
||||
if ( m_bPropFlare == false )
|
||||
{
|
||||
dl->origin = GetAbsOrigin();
|
||||
dl->color.r = 255;
|
||||
dl->die = gpGlobals->curtime + 0.1f;
|
||||
|
||||
dl->radius = baseScale * random->RandomFloat( 110.0f, 128.0f );
|
||||
dl->color.g = dl->color.b = random->RandomInt( 32, 64 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_iAttachment == -1 )
|
||||
{
|
||||
m_iAttachment = LookupAttachment( "fuse" );
|
||||
}
|
||||
|
||||
if ( m_iAttachment != -1 )
|
||||
{
|
||||
Vector effect_origin;
|
||||
QAngle effect_angles;
|
||||
|
||||
GetAttachment( m_iAttachment, effect_origin, effect_angles );
|
||||
|
||||
//Raise the light a little bit away from the flare so it lights it up better.
|
||||
dl->origin = effect_origin + Vector( 0, 0, 4 );
|
||||
dl->color.r = 255;
|
||||
dl->die = gpGlobals->curtime + 0.1f;
|
||||
|
||||
dl->radius = baseScale * random->RandomFloat( 245.0f, 256.0f );
|
||||
dl->color.g = dl->color.b = random->RandomInt( 95, 128 );
|
||||
|
||||
dlight_t *el= effects->CL_AllocElight( index );
|
||||
|
||||
el->origin = effect_origin;
|
||||
el->color.r = 255;
|
||||
el->color.g = dl->color.b = random->RandomInt( 95, 128 );
|
||||
el->radius = baseScale * random->RandomFloat( 260.0f, 290.0f );
|
||||
el->die = gpGlobals->curtime + 0.1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Smoke
|
||||
//
|
||||
|
||||
float dt = timeDelta;
|
||||
|
||||
if ( m_bSmoke )
|
||||
{
|
||||
while ( m_teSmokeSpawn.NextEvent( dt ) )
|
||||
{
|
||||
Vector smokeOrg = GetAbsOrigin();
|
||||
|
||||
Vector flareScreenDir = ( smokeOrg - MainViewOrigin() );
|
||||
VectorNormalize( flareScreenDir );
|
||||
|
||||
smokeOrg = smokeOrg + ( flareScreenDir * 2.0f );
|
||||
smokeOrg[2] += baseScale * 4.0f;
|
||||
|
||||
SimpleParticle *sParticle = (SimpleParticle *) AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[1], smokeOrg );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
sParticle->m_flDieTime = 1.0f;
|
||||
|
||||
sParticle->m_vecVelocity = Vector( random->RandomFloat( -16.0f, 16.0f ), random->RandomFloat( -16.0f, 16.0f ), random->RandomFloat( 8.0f, 16.0f ) + 32.0f );
|
||||
|
||||
if ( m_bPropFlare )
|
||||
{
|
||||
sParticle->m_uchColor[0] = 255;
|
||||
sParticle->m_uchColor[1] = 100;
|
||||
sParticle->m_uchColor[2] = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
sParticle->m_uchColor[0] = 255;
|
||||
sParticle->m_uchColor[1] = 48;
|
||||
sParticle->m_uchColor[2] = 48;
|
||||
}
|
||||
|
||||
sParticle->m_uchStartAlpha = random->RandomInt( 64, 90 );
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
sParticle->m_uchStartSize = random->RandomInt( 2, 4 );
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 8.0f;
|
||||
sParticle->m_flRoll = random->RandomInt( 0, 2*M_PI );
|
||||
sParticle->m_flRollDelta = random->RandomFloat( -(M_PI/6.0f), M_PI/6.0f );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bVisible )
|
||||
return;
|
||||
|
||||
//
|
||||
// Outer glow
|
||||
//
|
||||
|
||||
Vector offset;
|
||||
|
||||
//Cause the base of the effect to shake
|
||||
offset.Random( -0.5f * baseScale, 0.5f * baseScale );
|
||||
offset += GetAbsOrigin();
|
||||
|
||||
if ( m_pParticle[0] != NULL )
|
||||
{
|
||||
m_pParticle[0]->m_Pos = offset;
|
||||
m_pParticle[0]->m_flLifetime = 0.0f;
|
||||
m_pParticle[0]->m_flDieTime = 2.0f;
|
||||
|
||||
m_pParticle[0]->m_vecVelocity.Init();
|
||||
|
||||
fColor = random->RandomInt( 100.0f, 128.0f ) * visible;
|
||||
|
||||
m_pParticle[0]->m_uchColor[0] = fColor;
|
||||
m_pParticle[0]->m_uchColor[1] = fColor;
|
||||
m_pParticle[0]->m_uchColor[2] = fColor;
|
||||
m_pParticle[0]->m_uchStartAlpha = fColor;
|
||||
m_pParticle[0]->m_uchEndAlpha = fColor;
|
||||
m_pParticle[0]->m_uchStartSize = baseScale * (float) random->RandomInt( 32, 48 );
|
||||
m_pParticle[0]->m_uchEndSize = m_pParticle[0]->m_uchStartSize;
|
||||
m_pParticle[0]->m_flRollDelta = 0.0f;
|
||||
|
||||
if ( random->RandomInt( 0, 4 ) == 3 )
|
||||
{
|
||||
m_pParticle[0]->m_flRoll += random->RandomInt( 2, 8 );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Inner core
|
||||
//
|
||||
|
||||
//Cause the base of the effect to shake
|
||||
offset.Random( -1.0f * baseScale, 1.0f * baseScale );
|
||||
offset += GetAbsOrigin();
|
||||
|
||||
if ( m_pParticle[1] != NULL )
|
||||
{
|
||||
m_pParticle[1]->m_Pos = offset;
|
||||
m_pParticle[1]->m_flLifetime = 0.0f;
|
||||
m_pParticle[1]->m_flDieTime = 2.0f;
|
||||
|
||||
m_pParticle[1]->m_vecVelocity.Init();
|
||||
|
||||
fColor = 255 * visible;
|
||||
|
||||
m_pParticle[1]->m_uchColor[0] = fColor;
|
||||
m_pParticle[1]->m_uchColor[1] = fColor;
|
||||
m_pParticle[1]->m_uchColor[2] = fColor;
|
||||
m_pParticle[1]->m_uchStartAlpha = fColor;
|
||||
m_pParticle[1]->m_uchEndAlpha = fColor;
|
||||
m_pParticle[1]->m_uchStartSize = baseScale * (float) random->RandomInt( 2, 4 );
|
||||
m_pParticle[1]->m_uchEndSize = m_pParticle[0]->m_uchStartSize;
|
||||
m_pParticle[1]->m_flRoll = random->RandomInt( 0, 360 );
|
||||
}
|
||||
}
|
||||
170
sp/src/game/client/hl2/c_thumper_dust.cpp
Normal file
170
sp/src/game/client/hl2/c_thumper_dust.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "particlemgr.h"
|
||||
#include "particle_prototype.h"
|
||||
#include "particle_util.h"
|
||||
#include "c_te_particlesystem.h"
|
||||
#include "fx.h"
|
||||
#include "fx_quad.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#include "view.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define THUMPER_DUST_LIFETIME 2.0f
|
||||
#define THUMPER_MAX_PARTICLES 24
|
||||
|
||||
|
||||
extern IPhysicsSurfaceProps *physprops;
|
||||
|
||||
|
||||
class ThumperDustEmitter : public CSimpleEmitter
|
||||
{
|
||||
public:
|
||||
|
||||
ThumperDustEmitter( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
|
||||
|
||||
static ThumperDustEmitter *Create( const char *pDebugName )
|
||||
{
|
||||
return new ThumperDustEmitter( pDebugName );
|
||||
}
|
||||
|
||||
void UpdateVelocity( SimpleParticle *pParticle, float timeDelta )
|
||||
{
|
||||
// Float up when lifetime is half gone.
|
||||
pParticle->m_vecVelocity[2] -= ( 8.0f * timeDelta );
|
||||
|
||||
|
||||
// FIXME: optimize this....
|
||||
pParticle->m_vecVelocity *= ExponentialDecay( 0.9, 0.03, timeDelta );
|
||||
}
|
||||
|
||||
virtual float UpdateRoll( SimpleParticle *pParticle, float timeDelta )
|
||||
{
|
||||
pParticle->m_flRoll += pParticle->m_flRollDelta * timeDelta;
|
||||
|
||||
pParticle->m_flRollDelta += pParticle->m_flRollDelta * ( timeDelta * -4.0f );
|
||||
|
||||
//Cap the minimum roll
|
||||
if ( fabs( pParticle->m_flRollDelta ) < 0.25f )
|
||||
{
|
||||
pParticle->m_flRollDelta = ( pParticle->m_flRollDelta > 0.0f ) ? 0.25f : -0.25f;
|
||||
}
|
||||
|
||||
return pParticle->m_flRoll;
|
||||
}
|
||||
|
||||
virtual float UpdateAlpha( const SimpleParticle *pParticle )
|
||||
{
|
||||
return (pParticle->m_uchStartAlpha/255.0f) + ( (float)(pParticle->m_uchEndAlpha/255.0f) - (float)(pParticle->m_uchStartAlpha/255.0f) ) * (pParticle->m_flLifetime / pParticle->m_flDieTime);
|
||||
}
|
||||
|
||||
private:
|
||||
ThumperDustEmitter( const ThumperDustEmitter & );
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : bNewEntity - whether or not to start a new entity
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FX_ThumperDust( const CEffectData &data )
|
||||
{
|
||||
Vector vecDustColor;
|
||||
vecDustColor.x = 0.85f;
|
||||
vecDustColor.y = 0.75f;
|
||||
vecDustColor.z = 0.52f;
|
||||
|
||||
CSmartPtr<ThumperDustEmitter> pSimple = ThumperDustEmitter::Create( "thumperdust" );
|
||||
|
||||
C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity );
|
||||
if ( pEnt )
|
||||
{
|
||||
Vector vWorldMins, vWorldMaxs;
|
||||
float scale = pEnt->CollisionProp()->BoundingRadius();
|
||||
vWorldMins[0] = data.m_vOrigin[0] - scale;
|
||||
vWorldMins[1] = data.m_vOrigin[1] - scale;
|
||||
vWorldMins[2] = data.m_vOrigin[2] - scale;
|
||||
vWorldMaxs[0] = data.m_vOrigin[0] + scale;
|
||||
vWorldMaxs[1] = data.m_vOrigin[1] + scale;
|
||||
vWorldMaxs[2] = data.m_vOrigin[2] + scale;
|
||||
pSimple->GetBinding().SetBBox( vWorldMins, vWorldMaxs, true );
|
||||
}
|
||||
|
||||
pSimple->SetSortOrigin( data.m_vOrigin );
|
||||
pSimple->SetNearClip( 32, 64 );
|
||||
|
||||
SimpleParticle *pParticle = NULL;
|
||||
|
||||
Vector offset;
|
||||
|
||||
//int numPuffs = IsXbox() ? THUMPER_MAX_PARTICLES/2 : THUMPER_MAX_PARTICLES;
|
||||
int numPuffs = THUMPER_MAX_PARTICLES;
|
||||
|
||||
float flYaw = 0;
|
||||
float flIncr = (2*M_PI) / (float) numPuffs; // Radians
|
||||
Vector forward;
|
||||
Vector vecColor;
|
||||
int i = 0;
|
||||
|
||||
float flScale = MIN( data.m_flScale, 255 );
|
||||
|
||||
// Setup the color for these particles
|
||||
engine->ComputeLighting( data.m_vOrigin, NULL, true, vecColor );
|
||||
VectorLerp( vecColor, vecDustColor, 0.5, vecColor );
|
||||
vecColor *= 255;
|
||||
|
||||
for ( i = 0; i < numPuffs; i++ )
|
||||
{
|
||||
flYaw += flIncr;
|
||||
SinCos( flYaw, &forward.y, &forward.x );
|
||||
forward.z = 0.0f;
|
||||
|
||||
offset = ( RandomVector( -4.0f, 4.0f ) + data.m_vOrigin ) + ( forward * 128.0f );
|
||||
|
||||
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[random->RandomInt(0,1)], offset );
|
||||
if ( pParticle != NULL )
|
||||
{
|
||||
pParticle->m_flLifetime = 0.0f;
|
||||
pParticle->m_flDieTime = 1.5f;
|
||||
|
||||
Vector dir = (offset - data.m_vOrigin);
|
||||
float length = dir.Length();
|
||||
VectorNormalize( dir );
|
||||
|
||||
pParticle->m_vecVelocity = dir * ( length * 2.0f );
|
||||
pParticle->m_vecVelocity[2] = data.m_flScale / 3;
|
||||
|
||||
pParticle->m_uchColor[0] = vecColor[0];
|
||||
pParticle->m_uchColor[1] = vecColor[1];
|
||||
pParticle->m_uchColor[2] = vecColor[2];
|
||||
|
||||
pParticle->m_uchStartAlpha = random->RandomInt( 64, 96 );
|
||||
pParticle->m_uchEndAlpha = 0;
|
||||
|
||||
pParticle->m_uchStartSize = flScale * 0.25f;
|
||||
pParticle->m_uchEndSize = flScale * 0.5f;
|
||||
|
||||
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
pParticle->m_flRollDelta = random->RandomFloat( -6.0f, 6.0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &data -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ThumperDustCallback( const CEffectData &data )
|
||||
{
|
||||
FX_ThumperDust( data );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "ThumperDust", ThumperDustCallback );
|
||||
931
sp/src/game/client/hl2/c_vehicle_airboat.cpp
Normal file
931
sp/src/game/client/hl2/c_vehicle_airboat.cpp
Normal file
@@ -0,0 +1,931 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Client side implementation of the airboat.
|
||||
//
|
||||
// - Dampens motion of driver's view to reduce nausea.
|
||||
// - Autocenters driver's view after a period of inactivity.
|
||||
// - Controls headlights.
|
||||
// - Controls curve parameters for pitch/roll blending.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_prop_vehicle.h"
|
||||
#include "datacache/imdlcache.h"
|
||||
#include "flashlighteffect.h"
|
||||
#include "movevars_shared.h"
|
||||
#include "ammodef.h"
|
||||
#include "SpriteTrail.h"
|
||||
#include "beamdraw.h"
|
||||
#include "enginesprite.h"
|
||||
#include "fx_quad.h"
|
||||
#include "fx.h"
|
||||
#include "fx_water.h"
|
||||
#include "engine/ivdebugoverlay.h"
|
||||
#include "view.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
#include "c_basehlplayer.h"
|
||||
#include "vgui_controls/Controls.h"
|
||||
#include "vgui/ISurface.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
ConVar r_AirboatViewBlendTo( "r_AirboatViewBlendTo", "1", FCVAR_CHEAT );
|
||||
ConVar r_AirboatViewBlendToScale( "r_AirboatViewBlendToScale", "0.03", FCVAR_CHEAT );
|
||||
ConVar r_AirboatViewBlendToTime( "r_AirboatViewBlendToTime", "1.5", FCVAR_CHEAT );
|
||||
|
||||
ConVar cl_draw_airboat_wake( "cl_draw_airboat_wake", "1", FCVAR_CHEAT );
|
||||
|
||||
// Curve parameters for pitch/roll blending.
|
||||
// NOTE: Must restart (or create a new airboat) after changing these cvars!
|
||||
ConVar r_AirboatRollCurveZero( "r_AirboatRollCurveZero", "90.0", FCVAR_CHEAT ); // Roll less than this is clamped to zero.
|
||||
ConVar r_AirboatRollCurveLinear( "r_AirboatRollCurveLinear", "120.0", FCVAR_CHEAT ); // Roll greater than this is mapped directly.
|
||||
// Spline in between.
|
||||
|
||||
ConVar r_AirboatPitchCurveZero( "r_AirboatPitchCurveZero", "25.0", FCVAR_CHEAT ); // Pitch less than this is clamped to zero.
|
||||
ConVar r_AirboatPitchCurveLinear( "r_AirboatPitchCurveLinear", "60.0", FCVAR_CHEAT ); // Pitch greater than this is mapped directly.
|
||||
// Spline in between.
|
||||
|
||||
ConVar airboat_joy_response_move( "airboat_joy_response_move", "1" ); // Quadratic steering response
|
||||
|
||||
|
||||
#define AIRBOAT_DELTA_LENGTH_MAX 12.0f // 1 foot
|
||||
#define AIRBOAT_FRAMETIME_MIN 1e-6
|
||||
|
||||
#define HEADLIGHT_DISTANCE 1000
|
||||
|
||||
#define MAX_WAKE_POINTS 16
|
||||
#define WAKE_POINT_MASK (MAX_WAKE_POINTS-1)
|
||||
|
||||
#define WAKE_LIFETIME 0.5f
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Client-side Airboat Class
|
||||
//
|
||||
class C_PropAirboat : public C_PropVehicleDriveable
|
||||
{
|
||||
DECLARE_CLASS( C_PropAirboat, C_PropVehicleDriveable );
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_INTERPOLATION();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
C_PropAirboat();
|
||||
~C_PropAirboat();
|
||||
|
||||
public:
|
||||
|
||||
// C_BaseEntity
|
||||
virtual void Simulate();
|
||||
|
||||
// IClientVehicle
|
||||
virtual void UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd );
|
||||
virtual void OnEnteredVehicle( C_BasePlayer *pPlayer );
|
||||
virtual int GetPrimaryAmmoType() const;
|
||||
virtual int GetPrimaryAmmoClip() const;
|
||||
virtual bool PrimaryAmmoUsesClips() const;
|
||||
virtual int GetPrimaryAmmoCount() const;
|
||||
virtual int GetJoystickResponseCurve() const;
|
||||
|
||||
int DrawModel( int flags );
|
||||
|
||||
// Draws crosshair in the forward direction of the boat
|
||||
void DrawHudElements( );
|
||||
|
||||
private:
|
||||
|
||||
void DrawPropWake( Vector origin, float speed );
|
||||
void DrawPontoonSplash( Vector position, Vector direction, float speed );
|
||||
void DrawPontoonWake( Vector startPos, Vector wakeDir, float wakeLength, float speed);
|
||||
|
||||
void DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles );
|
||||
void DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime );
|
||||
void DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime );
|
||||
void ComputePDControllerCoefficients( float *pCoefficientsOut, float flFrequency, float flDampening, float flDeltaTime );
|
||||
|
||||
void UpdateHeadlight( void );
|
||||
void UpdateWake( void );
|
||||
int DrawWake( void );
|
||||
void DrawSegment( const BeamSeg_t &beamSeg, const Vector &vNormal );
|
||||
|
||||
TrailPoint_t *GetTrailPoint( int n )
|
||||
{
|
||||
int nIndex = (n + m_nFirstStep) & WAKE_POINT_MASK;
|
||||
return &m_vecSteps[nIndex];
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Vector m_vecLastEyePos;
|
||||
Vector m_vecLastEyeTarget;
|
||||
Vector m_vecEyeSpeed;
|
||||
Vector m_vecTargetSpeed;
|
||||
|
||||
float m_flViewAngleDeltaTime;
|
||||
|
||||
bool m_bHeadlightIsOn;
|
||||
int m_nAmmoCount;
|
||||
CHeadlightEffect *m_pHeadlight;
|
||||
|
||||
int m_nExactWaterLevel;
|
||||
|
||||
TrailPoint_t m_vecSteps[MAX_WAKE_POINTS];
|
||||
int m_nFirstStep;
|
||||
int m_nStepCount;
|
||||
float m_flUpdateTime;
|
||||
|
||||
TimedEvent m_SplashTime;
|
||||
CMeshBuilder m_Mesh;
|
||||
|
||||
Vector m_vecPhysVelocity;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_PropAirboat, DT_PropAirboat, CPropAirboat )
|
||||
RecvPropBool( RECVINFO( m_bHeadlightIsOn ) ),
|
||||
RecvPropInt( RECVINFO( m_nAmmoCount ) ),
|
||||
RecvPropInt( RECVINFO( m_nExactWaterLevel ) ),
|
||||
RecvPropInt( RECVINFO( m_nWaterLevel ) ),
|
||||
RecvPropVector( RECVINFO( m_vecPhysVelocity ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
BEGIN_DATADESC( C_PropAirboat )
|
||||
DEFINE_FIELD( m_vecLastEyePos, FIELD_POSITION_VECTOR ),
|
||||
DEFINE_FIELD( m_vecLastEyeTarget, FIELD_POSITION_VECTOR ),
|
||||
DEFINE_FIELD( m_vecEyeSpeed, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_vecTargetSpeed, FIELD_VECTOR ),
|
||||
//DEFINE_FIELD( m_flViewAngleDeltaTime, FIELD_FLOAT ),
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_PropAirboat::C_PropAirboat()
|
||||
{
|
||||
m_vecEyeSpeed.Init();
|
||||
m_flViewAngleDeltaTime = 0.0f;
|
||||
m_pHeadlight = NULL;
|
||||
|
||||
m_ViewSmoothingData.flPitchCurveZero = r_AirboatPitchCurveZero.GetFloat();
|
||||
m_ViewSmoothingData.flPitchCurveLinear = r_AirboatPitchCurveLinear.GetFloat();
|
||||
m_ViewSmoothingData.flRollCurveZero = r_AirboatRollCurveZero.GetFloat();
|
||||
m_ViewSmoothingData.flRollCurveLinear = r_AirboatRollCurveLinear.GetFloat();
|
||||
|
||||
m_ViewSmoothingData.rollLockData.flLockInterval = 1.5;
|
||||
m_ViewSmoothingData.rollLockData.flUnlockBlendInterval = 1.0;
|
||||
|
||||
m_ViewSmoothingData.pitchLockData.flLockInterval = 1.5;
|
||||
m_ViewSmoothingData.pitchLockData.flUnlockBlendInterval = 1.0;
|
||||
|
||||
m_nFirstStep = 0;
|
||||
m_nStepCount = 0;
|
||||
m_SplashTime.Init( 60 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Deconstructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_PropAirboat::~C_PropAirboat()
|
||||
{
|
||||
if (m_pHeadlight)
|
||||
{
|
||||
delete m_pHeadlight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Draws the ammo for the airboat
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_PropAirboat::GetPrimaryAmmoType() const
|
||||
{
|
||||
if ( m_nAmmoCount < 0 )
|
||||
return -1;
|
||||
|
||||
int nAmmoType = GetAmmoDef()->Index( "AirboatGun" );
|
||||
return nAmmoType;
|
||||
}
|
||||
|
||||
int C_PropAirboat::GetPrimaryAmmoCount() const
|
||||
{
|
||||
return m_nAmmoCount;
|
||||
}
|
||||
|
||||
bool C_PropAirboat::PrimaryAmmoUsesClips() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int C_PropAirboat::GetPrimaryAmmoClip() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The airboat prefers a more peppy response curve for joystick control.
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_PropAirboat::GetJoystickResponseCurve() const
|
||||
{
|
||||
return airboat_joy_response_move.GetInt();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Draws crosshair in the forward direction of the boat
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::DrawHudElements( )
|
||||
{
|
||||
BaseClass::DrawHudElements();
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
CHudTexture *pIcon = gHUD.GetIcon( IsX360() ? "crosshair_default" : "plushair" );
|
||||
if ( pIcon != NULL )
|
||||
{
|
||||
float x, y;
|
||||
Vector screen;
|
||||
|
||||
int vx, vy, vw, vh;
|
||||
vgui::surface()->GetFullscreenViewport( vx, vy, vw, vh );
|
||||
float screenWidth = vw;
|
||||
float screenHeight = vh;
|
||||
|
||||
x = screenWidth/2;
|
||||
y = screenHeight/2;
|
||||
|
||||
int eyeAttachmentIndex = LookupAttachment( "vehicle_driver_eyes" );
|
||||
Vector vehicleEyeOrigin;
|
||||
QAngle vehicleEyeAngles;
|
||||
GetAttachment( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles );
|
||||
|
||||
// Only worry about yaw.
|
||||
vehicleEyeAngles.x = vehicleEyeAngles.z = 0.0f;
|
||||
|
||||
Vector vecForward;
|
||||
AngleVectors( vehicleEyeAngles, &vecForward );
|
||||
VectorMA( vehicleEyeOrigin, 100.0f, vecForward, vehicleEyeOrigin );
|
||||
|
||||
ScreenTransform( vehicleEyeOrigin, screen );
|
||||
x += 0.5 * screen[0] * screenWidth + 0.5;
|
||||
y -= 0.5 * screen[1] * screenHeight + 0.5;
|
||||
|
||||
x -= pIcon->Width() / 2;
|
||||
y -= pIcon->Height() / 2;
|
||||
|
||||
pIcon->DrawSelf( x, y, gHUD.m_clrNormal );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Blend view angles.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd )
|
||||
{
|
||||
if ( r_AirboatViewBlendTo.GetInt() )
|
||||
{
|
||||
//
|
||||
// Autocenter the view after a period of no mouse movement while throttling.
|
||||
//
|
||||
bool bResetViewAngleTime = false;
|
||||
|
||||
if ( ( pCmd->mousedx != 0 || pCmd->mousedy != 0 ) || ( fabsf( m_flThrottle ) < 0.01f ) )
|
||||
{
|
||||
if ( IsX360() )
|
||||
{
|
||||
// Only reset this if there isn't an autoaim target!
|
||||
C_BaseHLPlayer *pLocalHLPlayer = (C_BaseHLPlayer *)pLocalPlayer;
|
||||
if ( pLocalHLPlayer )
|
||||
{
|
||||
// Get the autoaim target.
|
||||
CBaseEntity *pTarget = pLocalHLPlayer->m_HL2Local.m_hAutoAimTarget.Get();
|
||||
|
||||
if( !pTarget )
|
||||
{
|
||||
bResetViewAngleTime = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bResetViewAngleTime = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( bResetViewAngleTime )
|
||||
{
|
||||
m_flViewAngleDeltaTime = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flViewAngleDeltaTime += gpGlobals->frametime;
|
||||
}
|
||||
|
||||
if ( m_flViewAngleDeltaTime > r_AirboatViewBlendToTime.GetFloat() )
|
||||
{
|
||||
// Blend the view angles.
|
||||
int eyeAttachmentIndex = LookupAttachment( "vehicle_driver_eyes" );
|
||||
Vector vehicleEyeOrigin;
|
||||
QAngle vehicleEyeAngles;
|
||||
GetAttachmentLocal( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles );
|
||||
|
||||
QAngle outAngles;
|
||||
InterpolateAngles( pCmd->viewangles, vehicleEyeAngles, outAngles, r_AirboatViewBlendToScale.GetFloat() );
|
||||
pCmd->viewangles = outAngles;
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::UpdateViewAngles( pLocalPlayer, pCmd );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles )
|
||||
{
|
||||
// Get the frametime. (Check to see if enough time has passed to warrent dampening).
|
||||
float flFrameTime = gpGlobals->frametime;
|
||||
if ( flFrameTime < AIRBOAT_FRAMETIME_MIN )
|
||||
{
|
||||
vecVehicleEyePos = m_vecLastEyePos;
|
||||
DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, 0.0f );
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep static the sideways motion.
|
||||
|
||||
// Dampen forward/backward motion.
|
||||
DampenForwardMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime );
|
||||
|
||||
// Blend up/down motion.
|
||||
DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Use the controller as follows:
|
||||
// speed += ( pCoefficientsOut[0] * ( targetPos - currentPos ) + pCoefficientsOut[1] * ( targetSpeed - currentSpeed ) ) * flDeltaTime;
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::ComputePDControllerCoefficients( float *pCoefficientsOut,
|
||||
float flFrequency, float flDampening,
|
||||
float flDeltaTime )
|
||||
{
|
||||
float flKs = 9.0f * flFrequency * flFrequency;
|
||||
float flKd = 4.5f * flFrequency * flDampening;
|
||||
|
||||
float flScale = 1.0f / ( 1.0f + flKd * flDeltaTime + flKs * flDeltaTime * flDeltaTime );
|
||||
|
||||
pCoefficientsOut[0] = flKs * flScale;
|
||||
pCoefficientsOut[1] = ( flKd + flKs * flDeltaTime ) * flScale;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime )
|
||||
{
|
||||
// vecVehicleEyePos = real eye position this frame
|
||||
|
||||
// m_vecLastEyePos = eye position last frame
|
||||
// m_vecEyeSpeed = eye speed last frame
|
||||
// vecPredEyePos = predicted eye position this frame (assuming no acceleration - it will get that from the pd controller).
|
||||
// vecPredEyeSpeed = predicted eye speed
|
||||
Vector vecPredEyePos = m_vecLastEyePos + m_vecEyeSpeed * flFrameTime;
|
||||
Vector vecPredEyeSpeed = m_vecEyeSpeed;
|
||||
|
||||
// m_vecLastEyeTarget = real eye position last frame (used for speed calculation).
|
||||
// Calculate the approximate speed based on the current vehicle eye position and the eye position last frame.
|
||||
Vector vecVehicleEyeSpeed = ( vecVehicleEyePos - m_vecLastEyeTarget ) / flFrameTime;
|
||||
m_vecLastEyeTarget = vecVehicleEyePos;
|
||||
if (vecVehicleEyeSpeed.Length() == 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the delta between the predicted eye position and speed and the current eye position and speed.
|
||||
Vector vecDeltaSpeed = vecVehicleEyeSpeed - vecPredEyeSpeed;
|
||||
Vector vecDeltaPos = vecVehicleEyePos - vecPredEyePos;
|
||||
|
||||
// Forward vector.
|
||||
Vector vecForward;
|
||||
AngleVectors( vecVehicleEyeAngles, &vecForward );
|
||||
|
||||
float flDeltaLength = vecDeltaPos.Length();
|
||||
if ( flDeltaLength > AIRBOAT_DELTA_LENGTH_MAX )
|
||||
{
|
||||
// Clamp.
|
||||
float flDelta = flDeltaLength - AIRBOAT_DELTA_LENGTH_MAX;
|
||||
if ( flDelta > 40.0f )
|
||||
{
|
||||
// This part is a bit of a hack to get rid of large deltas (at level load, etc.).
|
||||
m_vecLastEyePos = vecVehicleEyePos;
|
||||
m_vecEyeSpeed = vecVehicleEyeSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Position clamp.
|
||||
float flRatio = AIRBOAT_DELTA_LENGTH_MAX / flDeltaLength;
|
||||
vecDeltaPos *= flRatio;
|
||||
Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) );
|
||||
vecVehicleEyePos -= vecForwardOffset;
|
||||
m_vecLastEyePos = vecVehicleEyePos;
|
||||
|
||||
// Speed clamp.
|
||||
vecDeltaSpeed *= flRatio;
|
||||
float flCoefficients[2];
|
||||
ComputePDControllerCoefficients( flCoefficients, r_AirboatViewDampenFreq.GetFloat(), r_AirboatViewDampenDamp.GetFloat(), flFrameTime );
|
||||
m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate an updated (dampening) speed for use in next frames position prediction.
|
||||
float flCoefficients[2];
|
||||
ComputePDControllerCoefficients( flCoefficients, r_AirboatViewDampenFreq.GetFloat(), r_AirboatViewDampenDamp.GetFloat(), flFrameTime );
|
||||
m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime );
|
||||
|
||||
// Save off data for next frame.
|
||||
m_vecLastEyePos = vecPredEyePos;
|
||||
|
||||
// Move eye forward/backward.
|
||||
Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) );
|
||||
vecVehicleEyePos -= vecForwardOffset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime )
|
||||
{
|
||||
// Get up vector.
|
||||
Vector vecUp;
|
||||
AngleVectors( vecVehicleEyeAngles, NULL, NULL, &vecUp );
|
||||
vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z );
|
||||
vecVehicleEyePos.z += r_AirboatViewZHeight.GetFloat() * vecUp.z;
|
||||
|
||||
// NOTE: Should probably use some damped equation here.
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::OnEnteredVehicle( C_BasePlayer *pPlayer )
|
||||
{
|
||||
int eyeAttachmentIndex = LookupAttachment( "vehicle_driver_eyes" );
|
||||
Vector vehicleEyeOrigin;
|
||||
QAngle vehicleEyeAngles;
|
||||
GetAttachment( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles );
|
||||
|
||||
m_vecLastEyeTarget = vehicleEyeOrigin;
|
||||
m_vecLastEyePos = vehicleEyeOrigin;
|
||||
m_vecEyeSpeed = vec3_origin;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::Simulate()
|
||||
{
|
||||
UpdateHeadlight();
|
||||
UpdateWake();
|
||||
|
||||
BaseClass::Simulate();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Creates, destroys, and updates the headlight effect as needed.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::UpdateHeadlight()
|
||||
{
|
||||
if (m_bHeadlightIsOn)
|
||||
{
|
||||
if (!m_pHeadlight)
|
||||
{
|
||||
// Turned on the headlight; create it.
|
||||
m_pHeadlight = new CHeadlightEffect();
|
||||
|
||||
if (!m_pHeadlight)
|
||||
return;
|
||||
|
||||
m_pHeadlight->TurnOn();
|
||||
}
|
||||
|
||||
// The headlight is emitted from an attachment point so that it can move
|
||||
// as we turn the handlebars.
|
||||
int nHeadlightIndex = LookupAttachment( "vehicle_headlight" );
|
||||
|
||||
Vector vecLightPos;
|
||||
QAngle angLightDir;
|
||||
GetAttachment(nHeadlightIndex, vecLightPos, angLightDir);
|
||||
|
||||
Vector vecLightDir, vecLightRight, vecLightUp;
|
||||
AngleVectors( angLightDir, &vecLightDir, &vecLightRight, &vecLightUp );
|
||||
|
||||
// Update the light with the new position and direction.
|
||||
m_pHeadlight->UpdateLight( vecLightPos, vecLightDir, vecLightRight, vecLightUp, HEADLIGHT_DISTANCE );
|
||||
}
|
||||
else if (m_pHeadlight)
|
||||
{
|
||||
// Turned off the headlight; delete it.
|
||||
delete m_pHeadlight;
|
||||
m_pHeadlight = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::UpdateWake( void )
|
||||
{
|
||||
if ( gpGlobals->frametime <= 0.0f )
|
||||
return;
|
||||
|
||||
// Can't update too quickly
|
||||
if ( m_flUpdateTime > gpGlobals->curtime )
|
||||
return;
|
||||
|
||||
Vector screenPos = GetRenderOrigin();
|
||||
screenPos.z = m_nExactWaterLevel;
|
||||
|
||||
TrailPoint_t *pLast = m_nStepCount ? GetTrailPoint( m_nStepCount-1 ) : NULL;
|
||||
if ( ( pLast == NULL ) || ( pLast->m_vecScreenPos.DistToSqr( screenPos ) > 4.0f ) )
|
||||
{
|
||||
// If we're over our limit, steal the last point and put it up front
|
||||
if ( m_nStepCount >= MAX_WAKE_POINTS )
|
||||
{
|
||||
--m_nStepCount;
|
||||
++m_nFirstStep;
|
||||
}
|
||||
|
||||
// Save off its screen position, not its world position
|
||||
TrailPoint_t *pNewPoint = GetTrailPoint( m_nStepCount );
|
||||
pNewPoint->m_vecScreenPos = screenPos + Vector( 0, 0, 2 );
|
||||
pNewPoint->m_flDieTime = gpGlobals->curtime + WAKE_LIFETIME;
|
||||
pNewPoint->m_flWidthVariance = random->RandomFloat( -16, 16 );
|
||||
|
||||
if ( pLast )
|
||||
{
|
||||
pNewPoint->m_flTexCoord = pLast->m_flTexCoord + pLast->m_vecScreenPos.DistTo( screenPos );
|
||||
pNewPoint->m_flTexCoord = fmod( pNewPoint->m_flTexCoord, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
pNewPoint->m_flTexCoord = 0.0f;
|
||||
}
|
||||
|
||||
++m_nStepCount;
|
||||
}
|
||||
|
||||
// Don't update again for a bit
|
||||
m_flUpdateTime = gpGlobals->curtime + ( 0.5f / (float) MAX_WAKE_POINTS );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &beamSeg -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::DrawSegment( const BeamSeg_t &beamSeg, const Vector &vNormal )
|
||||
{
|
||||
// Build the endpoints.
|
||||
Vector vPoint1, vPoint2;
|
||||
VectorMA( beamSeg.m_vPos, beamSeg.m_flWidth*0.5f, vNormal, vPoint1 );
|
||||
VectorMA( beamSeg.m_vPos, -beamSeg.m_flWidth*0.5f, vNormal, vPoint2 );
|
||||
|
||||
// Specify the points.
|
||||
m_Mesh.Position3fv( vPoint1.Base() );
|
||||
m_Mesh.Color4f( VectorExpand( beamSeg.m_vColor ), beamSeg.m_flAlpha );
|
||||
m_Mesh.TexCoord2f( 0, 0, beamSeg.m_flTexCoord );
|
||||
m_Mesh.TexCoord2f( 1, 0, beamSeg.m_flTexCoord );
|
||||
m_Mesh.AdvanceVertex();
|
||||
|
||||
m_Mesh.Position3fv( vPoint2.Base() );
|
||||
m_Mesh.Color4f( VectorExpand( beamSeg.m_vColor ), beamSeg.m_flAlpha );
|
||||
m_Mesh.TexCoord2f( 0, 1, beamSeg.m_flTexCoord );
|
||||
m_Mesh.TexCoord2f( 1, 1, beamSeg.m_flTexCoord );
|
||||
m_Mesh.AdvanceVertex();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : position -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::DrawPontoonSplash( Vector origin, Vector direction, float speed )
|
||||
{
|
||||
Vector offset;
|
||||
|
||||
CSmartPtr<CSplashParticle> pSimple = CSplashParticle::Create( "splish" );
|
||||
pSimple->SetSortOrigin( origin );
|
||||
|
||||
SimpleParticle *pParticle;
|
||||
|
||||
Vector color = Vector( 0.8f, 0.8f, 0.75f );
|
||||
float colorRamp;
|
||||
|
||||
float flScale = RemapVal( speed, 64, 256, 0.75f, 1.0f );
|
||||
|
||||
PMaterialHandle hMaterial;
|
||||
|
||||
float tempDelta = gpGlobals->frametime;
|
||||
|
||||
while( m_SplashTime.NextEvent( tempDelta ) )
|
||||
{
|
||||
if ( random->RandomInt( 0, 1 ) )
|
||||
{
|
||||
hMaterial = ParticleMgr()->GetPMaterial( "effects/splash1" );
|
||||
}
|
||||
else
|
||||
{
|
||||
hMaterial = ParticleMgr()->GetPMaterial( "effects/splash2" );
|
||||
}
|
||||
|
||||
offset = RandomVector( -8.0f * flScale, 8.0f * flScale );
|
||||
offset[2] = 0.0f;
|
||||
offset += origin;
|
||||
|
||||
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), hMaterial, offset );
|
||||
|
||||
if ( pParticle == NULL )
|
||||
continue;
|
||||
|
||||
pParticle->m_flLifetime = 0.0f;
|
||||
pParticle->m_flDieTime = 0.25f;
|
||||
|
||||
pParticle->m_vecVelocity.Random( -0.4f, 0.4f );
|
||||
pParticle->m_vecVelocity += (direction*5.0f+Vector(0,0,1));
|
||||
|
||||
VectorNormalize( pParticle->m_vecVelocity );
|
||||
|
||||
pParticle->m_vecVelocity *= speed + random->RandomFloat( -128.0f, 128.0f );
|
||||
|
||||
colorRamp = random->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 = random->RandomFloat( 8, 16 ) * flScale;
|
||||
pParticle->m_uchEndSize = pParticle->m_uchStartSize * 2;
|
||||
|
||||
pParticle->m_uchStartAlpha = 255;
|
||||
pParticle->m_uchEndAlpha = 0;
|
||||
|
||||
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
pParticle->m_flRollDelta = random->RandomFloat( -4.0f, 4.0f );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : Vector startPos -
|
||||
// wakeDir -
|
||||
// wakeLength -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropAirboat::DrawPontoonWake( Vector startPos, Vector wakeDir, float wakeLength, float speed )
|
||||
{
|
||||
#define WAKE_STEPS 6
|
||||
|
||||
Vector wakeStep = wakeDir * ( wakeLength / (float) WAKE_STEPS );
|
||||
Vector origin;
|
||||
float scale;
|
||||
|
||||
IMaterial *pMaterial = materials->FindMaterial( "effects/splashwake1", NULL, false );
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
IMesh* pMesh = pRenderContext->GetDynamicMesh( 0, 0, 0, pMaterial );
|
||||
|
||||
CMeshBuilder meshBuilder;
|
||||
meshBuilder.Begin( pMesh, MATERIAL_QUADS, WAKE_STEPS );
|
||||
|
||||
for ( int i = 0; i < WAKE_STEPS; i++ )
|
||||
{
|
||||
origin = startPos + ( wakeStep * i );
|
||||
origin[0] += random->RandomFloat( -4.0f, 4.0f );
|
||||
origin[1] += random->RandomFloat( -4.0f, 4.0f );
|
||||
origin[2] = m_nExactWaterLevel + 2.0f;
|
||||
|
||||
float scaleRange = RemapVal( i, 0, WAKE_STEPS-1, 32, 64 );
|
||||
scale = scaleRange + ( 8.0f * sin( gpGlobals->curtime * 5 * i ) );
|
||||
|
||||
float alpha = RemapValClamped( speed, 128, 600, 0.05f, 0.25f );
|
||||
float color[4] = { 1.0f, 1.0f, 1.0f, alpha };
|
||||
|
||||
// Needs to be time based so it'll freeze when the game is frozen
|
||||
float yaw = random->RandomFloat( 0, 360 );
|
||||
|
||||
Vector rRight = ( Vector(1,0,0) * cos( DEG2RAD( yaw ) ) ) - ( Vector(0,1,0) * sin( DEG2RAD( yaw ) ) );
|
||||
Vector rUp = ( Vector(1,0,0) * cos( DEG2RAD( yaw+90.0f ) ) ) - ( Vector(0,1,0) * sin( DEG2RAD( yaw+90.0f ) ) );
|
||||
|
||||
Vector point;
|
||||
meshBuilder.Color4fv (color);
|
||||
meshBuilder.TexCoord2f (0, 0, 1);
|
||||
VectorMA (origin, -scale, rRight, point);
|
||||
VectorMA (point, -scale, rUp, point);
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4fv (color);
|
||||
meshBuilder.TexCoord2f (0, 0, 0);
|
||||
VectorMA (origin, scale, rRight, point);
|
||||
VectorMA (point, -scale, rUp, point);
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4fv (color);
|
||||
meshBuilder.TexCoord2f (0, 1, 0);
|
||||
VectorMA (origin, scale, rRight, point);
|
||||
VectorMA (point, scale, rUp, point);
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4fv (color);
|
||||
meshBuilder.TexCoord2f (0, 1, 1);
|
||||
VectorMA (origin, -scale, rRight, point);
|
||||
VectorMA (point, scale, rUp, point);
|
||||
meshBuilder.Position3fv (point.Base());
|
||||
meshBuilder.AdvanceVertex();
|
||||
}
|
||||
|
||||
meshBuilder.End();
|
||||
pMesh->Draw();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_PropAirboat::DrawWake( void )
|
||||
{
|
||||
if ( cl_draw_airboat_wake.GetBool() == false )
|
||||
return 0;
|
||||
|
||||
// Make sure we're in water...
|
||||
if ( GetWaterLevel() == 0 )
|
||||
return 0;
|
||||
|
||||
//FIXME: For now, we don't draw slime this way
|
||||
if ( GetWaterLevel() == 2 )
|
||||
return 0;
|
||||
|
||||
bool bDriven = ( GetPassenger( VEHICLE_ROLE_DRIVER ) != NULL );
|
||||
|
||||
Vector vehicleDir = m_vecPhysVelocity;
|
||||
float vehicleSpeed = VectorNormalize( vehicleDir );
|
||||
|
||||
Vector vecPontoonFrontLeft;
|
||||
Vector vecPontoonFrontRight;
|
||||
Vector vecPontoonRearLeft;
|
||||
Vector vecPontoonRearRight;
|
||||
Vector vecSplashPoint;
|
||||
|
||||
QAngle fooAngles;
|
||||
|
||||
//FIXME: This lookup should be cached off
|
||||
// Get all attachments
|
||||
GetAttachment( LookupAttachment( "raytrace_fl" ), vecPontoonFrontLeft, fooAngles );
|
||||
GetAttachment( LookupAttachment( "raytrace_fr" ), vecPontoonFrontRight, fooAngles );
|
||||
GetAttachment( LookupAttachment( "raytrace_rl" ), vecPontoonRearLeft, fooAngles );
|
||||
GetAttachment( LookupAttachment( "raytrace_rr" ), vecPontoonRearRight, fooAngles );
|
||||
GetAttachment( LookupAttachment( "splash_pt" ), vecSplashPoint, fooAngles );
|
||||
|
||||
// Find the direction of the pontoons
|
||||
Vector vecLeftWakeDir = ( vecPontoonRearLeft - vecPontoonFrontLeft );
|
||||
Vector vecRightWakeDir = ( vecPontoonRearRight - vecPontoonFrontRight );
|
||||
|
||||
// Find the pontoon's size
|
||||
float flWakeLeftLength = VectorNormalize( vecLeftWakeDir );
|
||||
float flWakeRightLength = VectorNormalize( vecRightWakeDir );
|
||||
|
||||
vecPontoonFrontLeft.z = m_nExactWaterLevel;
|
||||
vecPontoonFrontRight.z = m_nExactWaterLevel;
|
||||
|
||||
if ( bDriven && vehicleSpeed > 128.0f )
|
||||
{
|
||||
DrawPontoonWake( vecPontoonFrontLeft, vecLeftWakeDir, flWakeLeftLength, vehicleSpeed );
|
||||
DrawPontoonWake( vecPontoonFrontRight, vecRightWakeDir, flWakeRightLength, vehicleSpeed );
|
||||
|
||||
Vector vecSplashDir;
|
||||
Vector vForward;
|
||||
GetVectors( &vForward, NULL, NULL );
|
||||
|
||||
if ( m_vecPhysVelocity.x < -64.0f )
|
||||
{
|
||||
vecSplashDir = vecLeftWakeDir - vForward;
|
||||
VectorNormalize( vecSplashDir );
|
||||
|
||||
// Don't do this if we're going backwards
|
||||
if ( m_vecPhysVelocity.y > 0.0f )
|
||||
{
|
||||
DrawPontoonSplash( vecPontoonFrontLeft + ( vecLeftWakeDir * 1.0f ), vecSplashDir, m_vecPhysVelocity.y );
|
||||
}
|
||||
}
|
||||
else if ( m_vecPhysVelocity.x > 64.0f )
|
||||
{
|
||||
vecSplashDir = vecRightWakeDir + vForward;
|
||||
VectorNormalize( vecSplashDir );
|
||||
|
||||
// Don't do this if we're going backwards
|
||||
if ( m_vecPhysVelocity.y > 0.0f )
|
||||
{
|
||||
DrawPontoonSplash( vecPontoonFrontRight + ( vecRightWakeDir * 1.0f ), vecSplashDir, m_vecPhysVelocity.y );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Must have at least one point
|
||||
if ( m_nStepCount <= 1 )
|
||||
return 1;
|
||||
|
||||
IMaterial *pMaterial = materials->FindMaterial( "effects/splashwake4", 0);
|
||||
|
||||
//Bind the material
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
|
||||
|
||||
m_Mesh.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, (m_nStepCount-1) * 2 );
|
||||
|
||||
TrailPoint_t *pLast = GetTrailPoint( m_nStepCount - 1 );
|
||||
|
||||
TrailPoint_t currentPoint;
|
||||
currentPoint.m_flDieTime = gpGlobals->curtime + 0.5f;
|
||||
currentPoint.m_vecScreenPos = GetAbsOrigin();
|
||||
currentPoint.m_vecScreenPos[2] = m_nExactWaterLevel + 16;
|
||||
currentPoint.m_flTexCoord = pLast->m_flTexCoord + currentPoint.m_vecScreenPos.DistTo(pLast->m_vecScreenPos);
|
||||
currentPoint.m_flTexCoord = fmod( currentPoint.m_flTexCoord, 1 );
|
||||
currentPoint.m_flWidthVariance = 0.0f;
|
||||
|
||||
TrailPoint_t *pPrevPoint = NULL;
|
||||
|
||||
Vector segDir, normal;
|
||||
|
||||
for ( int i = 0; i <= m_nStepCount; ++i )
|
||||
{
|
||||
// This makes it so that we're always drawing to the current location
|
||||
TrailPoint_t *pPoint = (i != m_nStepCount) ? GetTrailPoint(i) : ¤tPoint;
|
||||
|
||||
float flLifePerc = RemapValClamped( ( pPoint->m_flDieTime - gpGlobals->curtime ), 0, WAKE_LIFETIME, 0.0f, 1.0f );
|
||||
|
||||
BeamSeg_t curSeg;
|
||||
curSeg.m_vColor.x = curSeg.m_vColor.y = curSeg.m_vColor.z = 1.0f;
|
||||
|
||||
float flAlphaFade = flLifePerc;
|
||||
float alpha = RemapValClamped( fabs( m_vecPhysVelocity.y ), 128, 600, 0.0f, 1.0f );
|
||||
|
||||
curSeg.m_flAlpha = 0.25f;
|
||||
curSeg.m_flAlpha *= flAlphaFade * alpha;
|
||||
|
||||
curSeg.m_vPos = pPoint->m_vecScreenPos;
|
||||
|
||||
float widthBase = SimpleSplineRemapVal( fabs( m_vecPhysVelocity.y ), 128, 600, 32, 48 );
|
||||
|
||||
curSeg.m_flWidth = Lerp( flLifePerc, widthBase*6, widthBase );
|
||||
curSeg.m_flWidth += pPoint->m_flWidthVariance;
|
||||
|
||||
if ( curSeg.m_flWidth < 0.0f )
|
||||
{
|
||||
curSeg.m_flWidth = 0.0f;
|
||||
}
|
||||
|
||||
curSeg.m_flTexCoord = pPoint->m_flTexCoord;
|
||||
|
||||
if ( pPrevPoint != NULL )
|
||||
{
|
||||
segDir = ( pPrevPoint->m_vecScreenPos - pPoint->m_vecScreenPos );
|
||||
VectorNormalize( segDir );
|
||||
|
||||
normal = CrossProduct( segDir, Vector( 0, 0, -1 ) );
|
||||
|
||||
DrawSegment( curSeg, normal );
|
||||
}
|
||||
|
||||
pPrevPoint = pPoint;
|
||||
}
|
||||
|
||||
m_Mesh.End();
|
||||
pMesh->Draw();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flags -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_PropAirboat::DrawModel( int flags )
|
||||
{
|
||||
if ( BaseClass::DrawModel( flags ) == false )
|
||||
return 0;
|
||||
|
||||
if ( !m_bReadyToDraw )
|
||||
return 0;
|
||||
|
||||
return DrawWake();
|
||||
}
|
||||
187
sp/src/game/client/hl2/c_vehicle_cannon.cpp
Normal file
187
sp/src/game/client/hl2/c_vehicle_cannon.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "hud.h"
|
||||
#include <vgui_controls/Controls.h>
|
||||
#include <Color.h>
|
||||
#include "c_vehicle_crane.h"
|
||||
#include "view.h"
|
||||
#include "vehicle_viewblend_shared.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
int ScreenTransform( const Vector& point, Vector& screen );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_PropCannon : public C_BaseAnimating, public IClientVehicle
|
||||
{
|
||||
|
||||
DECLARE_CLASS( C_PropCannon, C_BaseAnimating );
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
C_PropCannon();
|
||||
|
||||
void PreDataUpdate( DataUpdateType_t updateType );
|
||||
|
||||
public:
|
||||
|
||||
// IClientVehicle overrides.
|
||||
virtual void GetVehicleViewPosition( int nRole, Vector *pOrigin, QAngle *pAngles, float *pFOV = NULL );
|
||||
virtual void GetVehicleFOV( float &flFOV ) { flFOV = 0.0f; }
|
||||
virtual void DrawHudElements();
|
||||
virtual bool IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) { return false; }
|
||||
virtual void UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd ) {}
|
||||
virtual C_BaseCombatCharacter *GetPassenger( int nRole );
|
||||
virtual int GetPassengerRole( C_BaseCombatCharacter *pPassenger );
|
||||
virtual void GetVehicleClipPlanes( float &flZNear, float &flZFar ) const;
|
||||
virtual int GetPrimaryAmmoType() const { return -1; }
|
||||
virtual int GetPrimaryAmmoCount() const { return -1; }
|
||||
virtual int GetPrimaryAmmoClip() const { return -1; }
|
||||
virtual bool PrimaryAmmoUsesClips() const { return false; }
|
||||
virtual int GetJoystickResponseCurve() const { return 0; }
|
||||
|
||||
public:
|
||||
|
||||
// C_BaseEntity overrides.
|
||||
virtual IClientVehicle* GetClientVehicle() { return this; }
|
||||
virtual C_BaseEntity *GetVehicleEnt() { return this; }
|
||||
virtual void SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) {}
|
||||
virtual void ProcessMovement( C_BasePlayer *pPlayer, CMoveData *pMoveData ) {}
|
||||
virtual void FinishMove( C_BasePlayer *player, CUserCmd *ucmd, CMoveData *move ) {}
|
||||
virtual bool IsPredicted() const { return false; }
|
||||
virtual void ItemPostFrame( C_BasePlayer *pPlayer ) {}
|
||||
virtual bool IsSelfAnimating() { return false; };
|
||||
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
|
||||
|
||||
private:
|
||||
|
||||
CHandle<C_BasePlayer> m_hPlayer;
|
||||
CHandle<C_BasePlayer> m_hPrevPlayer;
|
||||
|
||||
bool m_bEnterAnimOn;
|
||||
bool m_bExitAnimOn;
|
||||
Vector m_vecEyeExitEndpoint;
|
||||
|
||||
Vector m_vecOldShadowDir;
|
||||
|
||||
ViewSmoothingData_t m_ViewSmoothingData;
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_PropCannon, DT_PropCannon, CPropCannon)
|
||||
RecvPropEHandle( RECVINFO(m_hPlayer) ),
|
||||
RecvPropBool( RECVINFO( m_bEnterAnimOn ) ),
|
||||
RecvPropBool( RECVINFO( m_bExitAnimOn ) ),
|
||||
RecvPropVector( RECVINFO( m_vecEyeExitEndpoint ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
BEGIN_DATADESC( C_PropCannon )
|
||||
DEFINE_EMBEDDED( m_ViewSmoothingData ),
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
#define ROLL_CURVE_ZERO 5 // roll less than this is clamped to zero
|
||||
#define ROLL_CURVE_LINEAR 45 // roll greater than this is copied out
|
||||
|
||||
#define PITCH_CURVE_ZERO 10 // pitch less than this is clamped to zero
|
||||
#define PITCH_CURVE_LINEAR 45 // pitch greater than this is copied out
|
||||
// spline in between
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_PropCannon::C_PropCannon( void )
|
||||
{
|
||||
memset( &m_ViewSmoothingData, 0, sizeof( m_ViewSmoothingData ) );
|
||||
m_ViewSmoothingData.pVehicle = this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCannon::PreDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::PreDataUpdate( updateType );
|
||||
|
||||
m_hPrevPlayer = m_hPlayer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_BaseCombatCharacter *C_PropCannon::GetPassenger( int nRole )
|
||||
{
|
||||
if ( nRole == VEHICLE_ROLE_DRIVER )
|
||||
return m_hPlayer.Get();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the role of the passenger
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_PropCannon::GetPassengerRole( C_BaseCombatCharacter *pPassenger )
|
||||
{
|
||||
if ( m_hPlayer.Get() == pPassenger )
|
||||
return VEHICLE_ROLE_DRIVER;
|
||||
|
||||
return VEHICLE_ROLE_NONE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Modify the player view/camera while in a vehicle
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCannon::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*=NULL*/ )
|
||||
{
|
||||
SharedVehicleViewSmoothing( m_hPlayer,
|
||||
pAbsOrigin, pAbsAngles,
|
||||
m_bEnterAnimOn, m_bExitAnimOn,
|
||||
m_vecEyeExitEndpoint,
|
||||
&m_ViewSmoothingData,
|
||||
pFOV );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Futzes with the clip planes
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCannon::GetVehicleClipPlanes( float &flZNear, float &flZFar ) const
|
||||
{
|
||||
// FIXME: Need something a better long-term, this fixes the buggy.
|
||||
flZNear = 6;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Renders hud elements
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCannon::DrawHudElements( )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : theMins -
|
||||
// theMaxs -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCannon::GetRenderBounds( Vector &theMins, Vector &theMaxs )
|
||||
{
|
||||
// This is kind of hacky:( Add 660.0 to the y coordinate of the bounding box to
|
||||
// allow for the full extension of the crane arm.
|
||||
BaseClass::GetRenderBounds( theMins, theMaxs );
|
||||
theMaxs.y += 660.0f;
|
||||
}
|
||||
|
||||
151
sp/src/game/client/hl2/c_vehicle_crane.cpp
Normal file
151
sp/src/game/client/hl2/c_vehicle_crane.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "hud.h"
|
||||
#include <vgui_controls/Controls.h>
|
||||
#include <Color.h>
|
||||
#include "c_vehicle_crane.h"
|
||||
#include "view.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
int ScreenTransform( const Vector& point, Vector& screen );
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_PropCrane, DT_PropCrane, CPropCrane)
|
||||
RecvPropEHandle( RECVINFO(m_hPlayer) ),
|
||||
RecvPropBool( RECVINFO(m_bMagnetOn) ),
|
||||
RecvPropBool( RECVINFO( m_bEnterAnimOn ) ),
|
||||
RecvPropBool( RECVINFO( m_bExitAnimOn ) ),
|
||||
RecvPropVector( RECVINFO( m_vecEyeExitEndpoint ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
BEGIN_DATADESC( C_PropCrane )
|
||||
DEFINE_EMBEDDED( m_ViewSmoothingData ),
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
#define ROLL_CURVE_ZERO 5 // roll less than this is clamped to zero
|
||||
#define ROLL_CURVE_LINEAR 45 // roll greater than this is copied out
|
||||
|
||||
#define PITCH_CURVE_ZERO 10 // pitch less than this is clamped to zero
|
||||
#define PITCH_CURVE_LINEAR 45 // pitch greater than this is copied out
|
||||
// spline in between
|
||||
|
||||
#define CRANE_FOV 75
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_PropCrane::C_PropCrane( void )
|
||||
{
|
||||
memset( &m_ViewSmoothingData, 0, sizeof( m_ViewSmoothingData ) );
|
||||
m_ViewSmoothingData.pVehicle = this;
|
||||
m_ViewSmoothingData.flFOV = CRANE_FOV;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCrane::PreDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::PreDataUpdate( updateType );
|
||||
|
||||
m_hPrevPlayer = m_hPlayer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCrane::PostDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::PostDataUpdate( updateType );
|
||||
|
||||
// Store off the old shadow direction
|
||||
if ( m_hPlayer && !m_hPrevPlayer )
|
||||
{
|
||||
m_vecOldShadowDir = g_pClientShadowMgr->GetShadowDirection();
|
||||
//Vector vecDown = m_vecOldShadowDir - Vector(0,0,0.5);
|
||||
//VectorNormalize( vecDown );
|
||||
Vector vecDown = Vector(0,0,-1);
|
||||
g_pClientShadowMgr->SetShadowDirection( vecDown );
|
||||
}
|
||||
else if ( !m_hPlayer && m_hPrevPlayer )
|
||||
{
|
||||
g_pClientShadowMgr->SetShadowDirection( m_vecOldShadowDir );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_BaseCombatCharacter *C_PropCrane::GetPassenger( int nRole )
|
||||
{
|
||||
if ( nRole == VEHICLE_ROLE_DRIVER )
|
||||
return m_hPlayer.Get();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the role of the passenger
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_PropCrane::GetPassengerRole( C_BaseCombatCharacter *pPassenger )
|
||||
{
|
||||
if ( m_hPlayer.Get() == pPassenger )
|
||||
return VEHICLE_ROLE_DRIVER;
|
||||
|
||||
return VEHICLE_ROLE_NONE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Modify the player view/camera while in a vehicle
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCrane::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*=NULL*/ )
|
||||
{
|
||||
SharedVehicleViewSmoothing( m_hPlayer,
|
||||
pAbsOrigin, pAbsAngles,
|
||||
m_bEnterAnimOn, m_bExitAnimOn,
|
||||
m_vecEyeExitEndpoint,
|
||||
&m_ViewSmoothingData,
|
||||
pFOV );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Futzes with the clip planes
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCrane::GetVehicleClipPlanes( float &flZNear, float &flZFar ) const
|
||||
{
|
||||
// FIXME: Need something a better long-term, this fixes the buggy.
|
||||
flZNear = 6;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Renders hud elements
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCrane::DrawHudElements( )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : theMins -
|
||||
// theMaxs -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropCrane::GetRenderBounds( Vector &theMins, Vector &theMaxs )
|
||||
{
|
||||
// This is kind of hacky:( Add 660.0 to the y coordinate of the bounding box to
|
||||
// allow for the full extension of the crane arm.
|
||||
BaseClass::GetRenderBounds( theMins, theMaxs );
|
||||
theMaxs.y += 660.0f;
|
||||
}
|
||||
|
||||
80
sp/src/game/client/hl2/c_vehicle_crane.h
Normal file
80
sp/src/game/client/hl2/c_vehicle_crane.h
Normal file
@@ -0,0 +1,80 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "iclientvehicle.h"
|
||||
#include "vehicle_viewblend_shared.h"
|
||||
|
||||
#ifndef C_VEHICLE_CRANE_H
|
||||
#define C_VEHICLE_CRANE_H
|
||||
#pragma once
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_PropCrane : public C_BaseAnimating, public IClientVehicle
|
||||
{
|
||||
|
||||
DECLARE_CLASS( C_PropCrane, C_BaseAnimating );
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
C_PropCrane();
|
||||
|
||||
void PreDataUpdate( DataUpdateType_t updateType );
|
||||
void PostDataUpdate( DataUpdateType_t updateType );
|
||||
|
||||
bool IsMagnetOn( void ) { return m_bMagnetOn; }
|
||||
|
||||
public:
|
||||
|
||||
// IClientVehicle overrides.
|
||||
virtual void GetVehicleViewPosition( int nRole, Vector *pOrigin, QAngle *pAngles, float *pFOV =NULL );
|
||||
virtual void GetVehicleFOV( float &flFOV ) { flFOV = 0.0f; }
|
||||
virtual void DrawHudElements();
|
||||
virtual bool IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) { return false; }
|
||||
virtual void UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd ) {}
|
||||
virtual C_BaseCombatCharacter* GetPassenger( int nRole );
|
||||
virtual int GetPassengerRole( C_BaseCombatCharacter *pPassenger );
|
||||
virtual void GetVehicleClipPlanes( float &flZNear, float &flZFar ) const;
|
||||
virtual int GetPrimaryAmmoType() const { return -1; }
|
||||
virtual int GetPrimaryAmmoCount() const { return -1; }
|
||||
virtual int GetPrimaryAmmoClip() const { return -1; }
|
||||
virtual bool PrimaryAmmoUsesClips() const { return false; }
|
||||
virtual int GetJoystickResponseCurve() const { return 0; }
|
||||
|
||||
public:
|
||||
|
||||
// C_BaseEntity overrides.
|
||||
virtual IClientVehicle* GetClientVehicle() { return this; }
|
||||
virtual C_BaseEntity *GetVehicleEnt() { return this; }
|
||||
virtual void SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) {}
|
||||
virtual void ProcessMovement( C_BasePlayer *pPlayer, CMoveData *pMoveData ) {}
|
||||
virtual void FinishMove( C_BasePlayer *player, CUserCmd *ucmd, CMoveData *move ) {}
|
||||
virtual bool IsPredicted() const { return false; }
|
||||
virtual void ItemPostFrame( C_BasePlayer *pPlayer ) {}
|
||||
virtual bool IsSelfAnimating() { return false; };
|
||||
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
|
||||
|
||||
private:
|
||||
|
||||
CHandle<C_BasePlayer> m_hPlayer;
|
||||
CHandle<C_BasePlayer> m_hPrevPlayer;
|
||||
|
||||
bool m_bEnterAnimOn;
|
||||
bool m_bExitAnimOn;
|
||||
Vector m_vecEyeExitEndpoint;
|
||||
|
||||
bool m_bMagnetOn;
|
||||
|
||||
Vector m_vecOldShadowDir;
|
||||
|
||||
ViewSmoothingData_t m_ViewSmoothingData;
|
||||
};
|
||||
|
||||
#endif // C_VEHICLE_CRANE_H
|
||||
237
sp/src/game/client/hl2/c_vehicle_prisoner_pod.cpp
Normal file
237
sp/src/game/client/hl2/c_vehicle_prisoner_pod.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "hud.h"
|
||||
#include "c_physicsprop.h"
|
||||
#include "iclientvehicle.h"
|
||||
#include <vgui_controls/Controls.h>
|
||||
#include <Color.h>
|
||||
#include "vehicle_viewblend_shared.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern float RemapAngleRange( float startInterval, float endInterval, float value );
|
||||
|
||||
|
||||
#define ROLL_CURVE_ZERO 5 // roll less than this is clamped to zero
|
||||
#define ROLL_CURVE_LINEAR 45 // roll greater than this is copied out
|
||||
|
||||
#define PITCH_CURVE_ZERO 10 // pitch less than this is clamped to zero
|
||||
#define PITCH_CURVE_LINEAR 45 // pitch greater than this is copied out
|
||||
// spline in between
|
||||
|
||||
#define POD_VIEW_FOV 90
|
||||
#define POD_VIEW_YAW_MIN -60
|
||||
#define POD_VIEW_YAW_MAX 60
|
||||
#define POD_VIEW_PITCH_MIN -90
|
||||
#define POD_VIEW_PITCH_MAX 38 // Don't let players look down and see that the pod is empty
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_PropVehiclePrisonerPod : public C_PhysicsProp, public IClientVehicle
|
||||
{
|
||||
DECLARE_CLASS( C_PropVehiclePrisonerPod, C_PhysicsProp );
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
C_PropVehiclePrisonerPod();
|
||||
|
||||
void PreDataUpdate( DataUpdateType_t updateType );
|
||||
void PostDataUpdate( DataUpdateType_t updateType );
|
||||
|
||||
public:
|
||||
|
||||
// IClientVehicle overrides.
|
||||
virtual void GetVehicleViewPosition( int nRole, Vector *pOrigin, QAngle *pAngles, float *pFOV = NULL );
|
||||
virtual void GetVehicleFOV( float &flFOV )
|
||||
{
|
||||
flFOV = m_flFOV;
|
||||
}
|
||||
virtual void DrawHudElements();
|
||||
virtual bool IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) { return false; }
|
||||
virtual void UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd );
|
||||
virtual C_BaseCombatCharacter* GetPassenger( int nRole );
|
||||
virtual int GetPassengerRole( C_BaseCombatCharacter *pEnt );
|
||||
virtual void GetVehicleClipPlanes( float &flZNear, float &flZFar ) const;
|
||||
virtual int GetPrimaryAmmoType() const { return -1; }
|
||||
virtual int GetPrimaryAmmoCount() const { return -1; }
|
||||
virtual int GetPrimaryAmmoClip() const { return -1; }
|
||||
virtual bool PrimaryAmmoUsesClips() const { return false; }
|
||||
virtual int GetJoystickResponseCurve() const { return 0; }
|
||||
|
||||
public:
|
||||
|
||||
// C_BaseEntity overrides.
|
||||
virtual IClientVehicle* GetClientVehicle() { return this; }
|
||||
virtual C_BaseEntity *GetVehicleEnt() { return this; }
|
||||
virtual void SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) {}
|
||||
virtual void ProcessMovement( C_BasePlayer *pPlayer, CMoveData *pMoveData ) {}
|
||||
virtual void FinishMove( C_BasePlayer *player, CUserCmd *ucmd, CMoveData *move ) {}
|
||||
virtual bool IsPredicted() const { return false; }
|
||||
virtual void ItemPostFrame( C_BasePlayer *pPlayer ) {}
|
||||
virtual bool IsSelfAnimating() { return false; };
|
||||
|
||||
private:
|
||||
|
||||
CHandle<C_BasePlayer> m_hPlayer;
|
||||
CHandle<C_BasePlayer> m_hPrevPlayer;
|
||||
|
||||
bool m_bEnterAnimOn;
|
||||
bool m_bExitAnimOn;
|
||||
Vector m_vecEyeExitEndpoint;
|
||||
float m_flFOV; // The current FOV (changes during entry/exit anims).
|
||||
|
||||
ViewSmoothingData_t m_ViewSmoothingData;
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_PropVehiclePrisonerPod, DT_PropVehiclePrisonerPod, CPropVehiclePrisonerPod)
|
||||
RecvPropEHandle( RECVINFO(m_hPlayer) ),
|
||||
RecvPropBool( RECVINFO( m_bEnterAnimOn ) ),
|
||||
RecvPropBool( RECVINFO( m_bExitAnimOn ) ),
|
||||
RecvPropVector( RECVINFO( m_vecEyeExitEndpoint ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
BEGIN_DATADESC( C_PropVehiclePrisonerPod )
|
||||
DEFINE_EMBEDDED( m_ViewSmoothingData ),
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_PropVehiclePrisonerPod::C_PropVehiclePrisonerPod( void )
|
||||
{
|
||||
memset( &m_ViewSmoothingData, 0, sizeof( m_ViewSmoothingData ) );
|
||||
|
||||
m_ViewSmoothingData.pVehicle = this;
|
||||
m_ViewSmoothingData.bClampEyeAngles = true;
|
||||
m_ViewSmoothingData.flPitchCurveZero = PITCH_CURVE_ZERO;
|
||||
m_ViewSmoothingData.flPitchCurveLinear = PITCH_CURVE_LINEAR;
|
||||
m_ViewSmoothingData.flRollCurveZero = ROLL_CURVE_ZERO;
|
||||
m_ViewSmoothingData.flRollCurveLinear = ROLL_CURVE_LINEAR;
|
||||
m_ViewSmoothingData.flFOV = POD_VIEW_FOV;
|
||||
|
||||
m_flFOV = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropVehiclePrisonerPod::PreDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::PreDataUpdate( updateType );
|
||||
|
||||
m_hPrevPlayer = m_hPlayer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropVehiclePrisonerPod::PostDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::PostDataUpdate( updateType );
|
||||
|
||||
if ( !m_hPlayer && m_hPrevPlayer )
|
||||
{
|
||||
// They have just exited the vehicle.
|
||||
// Sometimes we never reach the end of our exit anim, such as if the
|
||||
// animation doesn't have fadeout 0 specified in the QC, so we fail to
|
||||
// catch it in VehicleViewSmoothing. Catch it here instead.
|
||||
m_ViewSmoothingData.bWasRunningAnim = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_BaseCombatCharacter *C_PropVehiclePrisonerPod::GetPassenger( int nRole )
|
||||
{
|
||||
if ( nRole == VEHICLE_ROLE_DRIVER )
|
||||
return m_hPlayer.Get();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the role of the passenger
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_PropVehiclePrisonerPod::GetPassengerRole( C_BaseCombatCharacter *pPassenger )
|
||||
{
|
||||
if ( m_hPlayer.Get() == pPassenger )
|
||||
return VEHICLE_ROLE_DRIVER;
|
||||
|
||||
return VEHICLE_ROLE_NONE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Modify the player view/camera while in a vehicle
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropVehiclePrisonerPod::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*=NULL*/ )
|
||||
{
|
||||
SharedVehicleViewSmoothing( m_hPlayer,
|
||||
pAbsOrigin, pAbsAngles,
|
||||
m_bEnterAnimOn, m_bExitAnimOn,
|
||||
m_vecEyeExitEndpoint,
|
||||
&m_ViewSmoothingData,
|
||||
pFOV );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : pLocalPlayer -
|
||||
// pCmd -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropVehiclePrisonerPod::UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd )
|
||||
{
|
||||
int eyeAttachmentIndex = LookupAttachment( "vehicle_driver_eyes" );
|
||||
Vector vehicleEyeOrigin;
|
||||
QAngle vehicleEyeAngles;
|
||||
GetAttachmentLocal( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles );
|
||||
|
||||
// Limit the yaw.
|
||||
float flAngleDiff = AngleDiff( pCmd->viewangles.y, vehicleEyeAngles.y );
|
||||
flAngleDiff = clamp( flAngleDiff, POD_VIEW_YAW_MIN, POD_VIEW_YAW_MAX );
|
||||
pCmd->viewangles.y = vehicleEyeAngles.y + flAngleDiff;
|
||||
|
||||
// Limit the pitch -- don't let them look down into the empty pod!
|
||||
flAngleDiff = AngleDiff( pCmd->viewangles.x, vehicleEyeAngles.x );
|
||||
flAngleDiff = clamp( flAngleDiff, POD_VIEW_PITCH_MIN, POD_VIEW_PITCH_MAX );
|
||||
pCmd->viewangles.x = vehicleEyeAngles.x + flAngleDiff;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Futzes with the clip planes
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropVehiclePrisonerPod::GetVehicleClipPlanes( float &flZNear, float &flZFar ) const
|
||||
{
|
||||
// Pod doesn't need to adjust the clip planes.
|
||||
//flZNear = 6;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Renders hud elements
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_PropVehiclePrisonerPod::DrawHudElements( )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
121
sp/src/game/client/hl2/c_waterbullet.cpp
Normal file
121
sp/src/game/client/hl2/c_waterbullet.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "particles_simple.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
class C_WaterBullet : public C_BaseAnimating
|
||||
{
|
||||
public:
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_CLASS( C_WaterBullet, C_BaseAnimating );
|
||||
|
||||
C_WaterBullet( void ) {};
|
||||
~C_WaterBullet( void ) {};
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
m_pEmitter = CSimpleEmitter::Create( "FX_Bubble" );
|
||||
m_pEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
|
||||
m_vecLastOrigin = GetAbsOrigin();
|
||||
}
|
||||
}
|
||||
|
||||
#define BUBBLES_PER_INCH 0.2
|
||||
|
||||
void AddEntity( void )
|
||||
{
|
||||
Vector direction = GetAbsOrigin() - m_vecLastOrigin;
|
||||
float flDist = VectorNormalize( direction );
|
||||
|
||||
int numBubbles = (int) ( flDist * BUBBLES_PER_INCH );
|
||||
|
||||
if ( numBubbles < 1 )
|
||||
numBubbles = 1;
|
||||
|
||||
// Make bubbles
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
Vector offset;
|
||||
|
||||
for ( int i = 0; i < numBubbles; i++ )
|
||||
{
|
||||
offset = m_vecLastOrigin + ( direction * ( flDist / numBubbles ) * i ) + RandomVector( -2.5f, 2.5f );
|
||||
|
||||
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/bubble" ), offset );
|
||||
|
||||
if ( sParticle )
|
||||
{
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
sParticle->m_flDieTime = random->RandomFloat( 0.75f, 1.25f );
|
||||
|
||||
sParticle->m_flRoll = 0;
|
||||
sParticle->m_flRollDelta = 0;
|
||||
|
||||
unsigned char color = random->RandomInt( 128, 255 );
|
||||
|
||||
sParticle->m_uchColor[0] = color;
|
||||
sParticle->m_uchColor[1] = color;
|
||||
sParticle->m_uchColor[2] = color;
|
||||
sParticle->m_uchStartAlpha = 255;
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
sParticle->m_uchStartSize = random->RandomInt( 1, 2 );
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize;
|
||||
|
||||
sParticle->m_vecVelocity = ( direction * 64.0f ) + Vector( 0, 0, 32 );
|
||||
}
|
||||
|
||||
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/splash2" ), offset );
|
||||
|
||||
if ( sParticle )
|
||||
{
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
sParticle->m_flDieTime = 0.2f;
|
||||
|
||||
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = random->RandomInt( -4, 4 );;
|
||||
|
||||
unsigned char color = random->RandomInt( 200, 255 );
|
||||
|
||||
sParticle->m_uchColor[0] = color;
|
||||
sParticle->m_uchColor[1] = color;
|
||||
sParticle->m_uchColor[2] = color;
|
||||
sParticle->m_uchStartAlpha = 128;
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
sParticle->m_uchStartSize = 2;
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 4;
|
||||
|
||||
sParticle->m_vecVelocity = ( direction * 64.0f ) + Vector( 0, 0, 32 );
|
||||
}
|
||||
}
|
||||
|
||||
// Save our last position
|
||||
m_vecLastOrigin = GetAbsOrigin();
|
||||
|
||||
BaseClass::AddEntity();
|
||||
}
|
||||
|
||||
bool ShouldDraw( void ) { return true; }
|
||||
|
||||
private:
|
||||
C_WaterBullet( const C_WaterBullet & );
|
||||
|
||||
CSmartPtr<CSimpleEmitter> m_pEmitter;
|
||||
|
||||
Vector m_vecLastOrigin;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_WaterBullet, DT_WaterBullet, CWaterBullet )
|
||||
END_RECV_TABLE()
|
||||
49
sp/src/game/client/hl2/c_weapon__stubs_hl2.cpp
Normal file
49
sp/src/game/client/hl2/c_weapon__stubs_hl2.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_weapon__stubs.h"
|
||||
#include "basehlcombatweapon_shared.h"
|
||||
#include "c_basehlcombatweapon.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
STUB_WEAPON_CLASS( cycler_weapon, WeaponCycler, C_BaseCombatWeapon );
|
||||
|
||||
STUB_WEAPON_CLASS( weapon_binoculars, WeaponBinoculars, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_bugbait, WeaponBugBait, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_flaregun, Flaregun, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_annabelle, WeaponAnnabelle, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_gauss, WeaponGaussGun, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_cubemap, WeaponCubemap, C_BaseCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_alyxgun, WeaponAlyxGun, C_HLSelectFireMachineGun );
|
||||
STUB_WEAPON_CLASS( weapon_citizenpackage, WeaponCitizenPackage, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_citizensuitcase, WeaponCitizenSuitcase, C_WeaponCitizenPackage );
|
||||
|
||||
#ifndef HL2MP
|
||||
STUB_WEAPON_CLASS( weapon_ar2, WeaponAR2, C_HLMachineGun );
|
||||
STUB_WEAPON_CLASS( weapon_frag, WeaponFrag, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_rpg, WeaponRPG, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_pistol, WeaponPistol, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_shotgun, WeaponShotgun, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_smg1, WeaponSMG1, C_HLSelectFireMachineGun );
|
||||
STUB_WEAPON_CLASS( weapon_357, Weapon357, C_BaseHLCombatWeapon );
|
||||
STUB_WEAPON_CLASS( weapon_crossbow, WeaponCrossbow, C_BaseHLCombatWeapon );
|
||||
#ifndef MAPBASE
|
||||
STUB_WEAPON_CLASS( weapon_slam, Weapon_SLAM, C_BaseHLCombatWeapon );
|
||||
#endif
|
||||
STUB_WEAPON_CLASS( weapon_crowbar, WeaponCrowbar, C_BaseHLBludgeonWeapon );
|
||||
#ifdef HL2_EPISODIC
|
||||
STUB_WEAPON_CLASS( weapon_hopwire, WeaponHopwire, C_BaseHLCombatWeapon );
|
||||
//STUB_WEAPON_CLASS( weapon_proto1, WeaponProto1, C_BaseHLCombatWeapon );
|
||||
#endif
|
||||
#ifdef HL2_LOSTCOAST
|
||||
STUB_WEAPON_CLASS( weapon_oldmanharpoon, WeaponOldManHarpoon, C_WeaponCitizenPackage );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
159
sp/src/game/client/hl2/c_weapon_crossbow.cpp
Normal file
159
sp/src/game/client/hl2/c_weapon_crossbow.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "model_types.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
#include "fx.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#include "beamdraw.h"
|
||||
|
||||
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectCrossbow )
|
||||
CLIENTEFFECT_MATERIAL( "effects/muzzleflash1" )
|
||||
CLIENTEFFECT_REGISTER_END()
|
||||
|
||||
//
|
||||
// Crossbow bolt
|
||||
//
|
||||
|
||||
class C_CrossbowBolt : public C_BaseCombatCharacter
|
||||
{
|
||||
DECLARE_CLASS( C_CrossbowBolt, C_BaseCombatCharacter );
|
||||
DECLARE_CLIENTCLASS();
|
||||
public:
|
||||
|
||||
C_CrossbowBolt( void );
|
||||
|
||||
virtual RenderGroup_t GetRenderGroup( void )
|
||||
{
|
||||
// We want to draw translucent bits as well as our main model
|
||||
return RENDER_GROUP_TWOPASS;
|
||||
}
|
||||
|
||||
virtual void ClientThink( void );
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual int DrawModel( int flags );
|
||||
|
||||
private:
|
||||
|
||||
C_CrossbowBolt( const C_CrossbowBolt & ); // not defined, not accessible
|
||||
|
||||
Vector m_vecLastOrigin;
|
||||
bool m_bUpdated;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_CrossbowBolt, DT_CrossbowBolt, CCrossbowBolt )
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_CrossbowBolt::C_CrossbowBolt( void )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_CrossbowBolt::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
m_bUpdated = false;
|
||||
m_vecLastOrigin = GetAbsOrigin();
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flags -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_CrossbowBolt::DrawModel( int flags )
|
||||
{
|
||||
// See if we're drawing the motion blur
|
||||
if ( flags & STUDIO_TRANSPARENCY )
|
||||
{
|
||||
float color[3];
|
||||
IMaterial *pBlurMaterial = materials->FindMaterial( "effects/muzzleflash1", NULL, false );
|
||||
|
||||
Vector vecDir = GetAbsOrigin() - m_vecLastOrigin;
|
||||
float speed = VectorNormalize( vecDir );
|
||||
|
||||
speed = clamp( speed, 0, 32 );
|
||||
|
||||
if ( speed > 0 )
|
||||
{
|
||||
float stepSize = MIN( ( speed * 0.5f ), 4.0f );
|
||||
|
||||
Vector spawnPos = GetAbsOrigin() + ( vecDir * 24.0f );
|
||||
Vector spawnStep = -vecDir * stepSize;
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->Bind( pBlurMaterial );
|
||||
|
||||
float alpha;
|
||||
|
||||
// Draw the motion blurred trail
|
||||
for ( int i = 0; i < 20; i++ )
|
||||
{
|
||||
spawnPos += spawnStep;
|
||||
|
||||
alpha = RemapValClamped( i, 5, 11, 0.25f, 0.05f );
|
||||
|
||||
color[0] = color[1] = color[2] = alpha;
|
||||
|
||||
DrawHalo( pBlurMaterial, spawnPos, 3.0f, color );
|
||||
}
|
||||
}
|
||||
|
||||
if ( gpGlobals->frametime > 0.0f && !m_bUpdated)
|
||||
{
|
||||
m_bUpdated = true;
|
||||
m_vecLastOrigin = GetAbsOrigin();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Draw the normal portion
|
||||
return BaseClass::DrawModel( flags );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_CrossbowBolt::ClientThink( void )
|
||||
{
|
||||
m_bUpdated = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &data -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CrosshairLoadCallback( const CEffectData &data )
|
||||
{
|
||||
IClientRenderable *pRenderable = data.GetRenderable( );
|
||||
if ( !pRenderable )
|
||||
return;
|
||||
|
||||
Vector position;
|
||||
QAngle angles;
|
||||
|
||||
// If we found the attachment, emit sparks there
|
||||
if ( pRenderable->GetAttachment( data.m_nAttachmentIndex, position, angles ) )
|
||||
{
|
||||
FX_ElectricSpark( position, 1.0f, 1.0f, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "CrossbowLoad", CrosshairLoadCallback );
|
||||
166
sp/src/game/client/hl2/c_weapon_gravitygun.cpp
Normal file
166
sp/src/game/client/hl2/c_weapon_gravitygun.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "hud.h"
|
||||
#include "in_buttons.h"
|
||||
#include "beamdraw.h"
|
||||
#include "c_weapon__stubs.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectGravityGun )
|
||||
CLIENTEFFECT_MATERIAL( "sprites/physbeam" )
|
||||
CLIENTEFFECT_REGISTER_END()
|
||||
|
||||
class C_BeamQuadratic : public CDefaultClientRenderable
|
||||
{
|
||||
public:
|
||||
C_BeamQuadratic();
|
||||
void Update( C_BaseEntity *pOwner );
|
||||
|
||||
// IClientRenderable
|
||||
virtual const Vector& GetRenderOrigin( void ) { return m_worldPosition; }
|
||||
virtual const QAngle& GetRenderAngles( void ) { return vec3_angle; }
|
||||
virtual bool ShouldDraw( void ) { return true; }
|
||||
virtual bool IsTransparent( void ) { return true; }
|
||||
virtual bool ShouldReceiveProjectedTextures( int flags ) { return false; }
|
||||
virtual int DrawModel( int flags );
|
||||
|
||||
// Returns the bounds relative to the origin (render bounds)
|
||||
virtual void GetRenderBounds( Vector& mins, Vector& maxs )
|
||||
{
|
||||
// bogus. But it should draw if you can see the end point
|
||||
mins.Init(-32,-32,-32);
|
||||
maxs.Init(32,32,32);
|
||||
}
|
||||
|
||||
C_BaseEntity *m_pOwner;
|
||||
Vector m_targetPosition;
|
||||
Vector m_worldPosition;
|
||||
int m_active;
|
||||
int m_glueTouching;
|
||||
int m_viewModelIndex;
|
||||
};
|
||||
|
||||
|
||||
class C_WeaponGravityGun : public C_BaseCombatWeapon
|
||||
{
|
||||
DECLARE_CLASS( C_WeaponGravityGun, C_BaseCombatWeapon );
|
||||
public:
|
||||
C_WeaponGravityGun() {}
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
|
||||
{
|
||||
if ( gHUD.m_iKeyBits & IN_ATTACK )
|
||||
{
|
||||
switch ( keynum )
|
||||
{
|
||||
case MOUSE_WHEEL_UP:
|
||||
gHUD.m_iKeyBits |= IN_WEAPON1;
|
||||
return 0;
|
||||
|
||||
case MOUSE_WHEEL_DOWN:
|
||||
gHUD.m_iKeyBits |= IN_WEAPON2;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow engine to process
|
||||
return BaseClass::KeyInput( down, keynum, pszCurrentBinding );
|
||||
}
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
m_beam.Update( this );
|
||||
}
|
||||
|
||||
private:
|
||||
C_WeaponGravityGun( const C_WeaponGravityGun & );
|
||||
|
||||
C_BeamQuadratic m_beam;
|
||||
};
|
||||
|
||||
STUB_WEAPON_CLASS_IMPLEMENT( weapon_physgun, C_WeaponGravityGun );
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_WeaponGravityGun, DT_WeaponGravityGun, CWeaponGravityGun )
|
||||
RecvPropVector( RECVINFO_NAME(m_beam.m_targetPosition,m_targetPosition) ),
|
||||
RecvPropVector( RECVINFO_NAME(m_beam.m_worldPosition, m_worldPosition) ),
|
||||
RecvPropInt( RECVINFO_NAME(m_beam.m_active, m_active) ),
|
||||
RecvPropInt( RECVINFO_NAME(m_beam.m_glueTouching, m_glueTouching) ),
|
||||
RecvPropInt( RECVINFO_NAME(m_beam.m_viewModelIndex, m_viewModelIndex) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
C_BeamQuadratic::C_BeamQuadratic()
|
||||
{
|
||||
m_pOwner = NULL;
|
||||
}
|
||||
|
||||
void C_BeamQuadratic::Update( C_BaseEntity *pOwner )
|
||||
{
|
||||
m_pOwner = pOwner;
|
||||
if ( m_active )
|
||||
{
|
||||
if ( m_hRenderHandle == INVALID_CLIENT_RENDER_HANDLE )
|
||||
{
|
||||
ClientLeafSystem()->AddRenderable( this, RENDER_GROUP_TRANSLUCENT_ENTITY );
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientLeafSystem()->RenderableChanged( m_hRenderHandle );
|
||||
}
|
||||
}
|
||||
else if ( !m_active && m_hRenderHandle != INVALID_CLIENT_RENDER_HANDLE )
|
||||
{
|
||||
ClientLeafSystem()->RemoveRenderable( m_hRenderHandle );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int C_BeamQuadratic::DrawModel( int )
|
||||
{
|
||||
Vector points[3];
|
||||
QAngle tmpAngle;
|
||||
|
||||
if ( !m_active )
|
||||
return 0;
|
||||
|
||||
C_BaseEntity *pEnt = cl_entitylist->GetEnt( m_viewModelIndex );
|
||||
if ( !pEnt )
|
||||
return 0;
|
||||
pEnt->GetAttachment( 1, points[0], tmpAngle );
|
||||
|
||||
points[1] = 0.5 * (m_targetPosition + points[0]);
|
||||
|
||||
// a little noise 11t & 13t should be somewhat non-periodic looking
|
||||
//points[1].z += 4*sin( gpGlobals->curtime*11 ) + 5*cos( gpGlobals->curtime*13 );
|
||||
points[2] = m_worldPosition;
|
||||
|
||||
IMaterial *pMat = materials->FindMaterial( "sprites/physbeam", TEXTURE_GROUP_CLIENT_EFFECTS );
|
||||
Vector color;
|
||||
if ( m_glueTouching )
|
||||
{
|
||||
color.Init(1,0,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
color.Init(1,1,1);
|
||||
}
|
||||
|
||||
float scrollOffset = gpGlobals->curtime - (int)gpGlobals->curtime;
|
||||
materials->Bind( pMat );
|
||||
DrawBeamQuadratic( points[0], points[1], points[2], 13, color, scrollOffset );
|
||||
return 1;
|
||||
}
|
||||
|
||||
442
sp/src/game/client/hl2/c_weapon_physcannon.cpp
Normal file
442
sp/src/game/client/hl2/c_weapon_physcannon.cpp
Normal file
@@ -0,0 +1,442 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "c_weapon__stubs.h"
|
||||
#include "c_basehlcombatweapon.h"
|
||||
#include "fx.h"
|
||||
#include "particles_localspace.h"
|
||||
#include "view.h"
|
||||
#include "particles_attractor.h"
|
||||
|
||||
class C_WeaponPhysCannon: public C_BaseHLCombatWeapon
|
||||
{
|
||||
DECLARE_CLASS( C_WeaponPhysCannon, C_BaseHLCombatWeapon );
|
||||
public:
|
||||
C_WeaponPhysCannon( void );
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual int DrawModel( int flags );
|
||||
virtual void ClientThink( void );
|
||||
|
||||
virtual bool ShouldUseLargeViewModelVROverride() OVERRIDE { return true; }
|
||||
|
||||
private:
|
||||
|
||||
bool SetupEmitter( void );
|
||||
|
||||
bool m_bIsCurrentlyUpgrading;
|
||||
float m_flTimeForceView;
|
||||
float m_flTimeIgnoreForceView;
|
||||
bool m_bWasUpgraded;
|
||||
|
||||
CSmartPtr<CLocalSpaceEmitter> m_pLocalEmitter;
|
||||
CSmartPtr<CSimpleEmitter> m_pEmitter;
|
||||
CSmartPtr<CParticleAttractor> m_pAttractor;
|
||||
};
|
||||
|
||||
STUB_WEAPON_CLASS_IMPLEMENT( weapon_physcannon, C_WeaponPhysCannon );
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_WeaponPhysCannon, DT_WeaponPhysCannon, CWeaponPhysCannon )
|
||||
RecvPropBool( RECVINFO( m_bIsCurrentlyUpgrading ) ),
|
||||
RecvPropFloat( RECVINFO( m_flTimeForceView) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_WeaponPhysCannon::C_WeaponPhysCannon( void )
|
||||
{
|
||||
m_bWasUpgraded = false;
|
||||
m_flTimeIgnoreForceView = -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_WeaponPhysCannon::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool C_WeaponPhysCannon::SetupEmitter( void )
|
||||
{
|
||||
if ( !m_pLocalEmitter.IsValid() )
|
||||
{
|
||||
m_pLocalEmitter = CLocalSpaceEmitter::Create( "physpowerup", GetRefEHandle(), LookupAttachment( "core" ) );
|
||||
|
||||
if ( m_pLocalEmitter.IsValid() == false )
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !m_pAttractor.IsValid() )
|
||||
{
|
||||
m_pAttractor = CParticleAttractor::Create( vec3_origin, "physpowerup_att" );
|
||||
|
||||
if ( m_pAttractor.IsValid() == false )
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !m_pEmitter.IsValid() )
|
||||
{
|
||||
m_pEmitter = CSimpleEmitter::Create( "physpowerup_glow" );
|
||||
|
||||
if ( m_pEmitter.IsValid() == false )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flags -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_WeaponPhysCannon::DrawModel( int flags )
|
||||
{
|
||||
// If we're not ugrading, don't do anything special
|
||||
if ( m_bIsCurrentlyUpgrading == false && m_bWasUpgraded == false )
|
||||
return BaseClass::DrawModel( flags );
|
||||
|
||||
if ( gpGlobals->frametime == 0 )
|
||||
return BaseClass::DrawModel( flags );
|
||||
|
||||
if ( !m_bReadyToDraw )
|
||||
return 0;
|
||||
|
||||
m_bWasUpgraded = true;
|
||||
|
||||
// Create the particle emitter if it's not already
|
||||
if ( SetupEmitter() )
|
||||
{
|
||||
// Add the power-up particles
|
||||
|
||||
// See if we should draw
|
||||
if ( m_bReadyToDraw == false )
|
||||
return 0;
|
||||
|
||||
C_BaseAnimating *pAnimating = GetBaseAnimating();
|
||||
if (!pAnimating)
|
||||
return 0;
|
||||
|
||||
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
|
||||
if ( !pAnimating->HitboxToWorldTransforms( hitboxbones ) )
|
||||
return 0;
|
||||
|
||||
studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
|
||||
if (!pStudioHdr)
|
||||
return false;
|
||||
|
||||
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );
|
||||
if ( !set )
|
||||
return false;
|
||||
|
||||
int i;
|
||||
|
||||
float fadePerc = 1.0f;
|
||||
|
||||
if ( m_bIsCurrentlyUpgrading )
|
||||
{
|
||||
Vector vecSkew = vec3_origin;
|
||||
|
||||
// Skew the particles in front or in back of their targets
|
||||
vecSkew = CurrentViewForward() * 4.0f;
|
||||
|
||||
float spriteScale = 1.0f;
|
||||
spriteScale = clamp( spriteScale, 0.75f, 1.0f );
|
||||
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
for ( 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( 4.0f * fadePerc, 1, 3 );
|
||||
|
||||
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), m_pEmitter->GetPMaterial( "effects/combinemuzzle1" ), vecAbsOrigin + offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return 1;
|
||||
|
||||
sParticle->m_vecVelocity = vec3_origin;
|
||||
sParticle->m_uchStartSize = 16.0f * spriteScale;
|
||||
sParticle->m_flDieTime = 0.2f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = Helper_RandomFloat( -2.0f, 2.0f );
|
||||
|
||||
float alpha = 40;
|
||||
|
||||
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 = sParticle->m_uchStartSize * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int attachment = LookupAttachment( "core" );
|
||||
Vector coreOrigin;
|
||||
QAngle coreAngles;
|
||||
|
||||
GetAttachment( attachment, coreOrigin, coreAngles );
|
||||
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
// Do the core effects
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
sParticle = (SimpleParticle *) m_pLocalEmitter->AddParticle( sizeof(SimpleParticle), m_pLocalEmitter->GetPMaterial( "effects/strider_muzzle" ), vec3_origin );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return 1;
|
||||
|
||||
sParticle->m_vecVelocity = vec3_origin;
|
||||
sParticle->m_flDieTime = 0.1f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.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;
|
||||
|
||||
if ( i < 2 )
|
||||
{
|
||||
sParticle->m_uchStartSize = random->RandomFloat( 1, 2 ) * (i+1);
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( random->RandomInt( 0, 20 ) == 0 )
|
||||
{
|
||||
sParticle->m_uchStartSize = random->RandomFloat( 1, 2 ) * (i+1);
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 4.0f;
|
||||
sParticle->m_flDieTime = 0.25f;
|
||||
}
|
||||
else
|
||||
{
|
||||
sParticle->m_uchStartSize = random->RandomFloat( 1, 2 ) * (i+1);
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_bWasUpgraded && m_bIsCurrentlyUpgrading )
|
||||
{
|
||||
// Update our attractor point
|
||||
m_pAttractor->SetAttractorOrigin( coreOrigin );
|
||||
|
||||
Vector offset;
|
||||
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
offset = coreOrigin + RandomVector( -32.0f, 32.0f );
|
||||
|
||||
sParticle = (SimpleParticle *) m_pAttractor->AddParticle( sizeof(SimpleParticle), m_pAttractor->GetPMaterial( "effects/strider_muzzle" ), offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return 1;
|
||||
|
||||
sParticle->m_vecVelocity = Vector(0,0,8);
|
||||
sParticle->m_flDieTime = 0.5f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.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_uchStartSize = random->RandomFloat( 1, 2 );
|
||||
sParticle->m_uchEndSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::DrawModel( flags );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// On 360, raise up the player's view if the server has
|
||||
// asked us to.
|
||||
//---------------------------------------------------------
|
||||
#define PHYSCANNON_RAISE_VIEW_GOAL 0.0f
|
||||
void C_WeaponPhysCannon::ClientThink( void )
|
||||
{
|
||||
if( m_flTimeIgnoreForceView > gpGlobals->curtime )
|
||||
return;
|
||||
|
||||
float flTime = (m_flTimeForceView - gpGlobals->curtime);
|
||||
|
||||
if( flTime < 0.0f )
|
||||
return;
|
||||
|
||||
float flDT = 1.0f - flTime;
|
||||
if( flDT > 0.0f )
|
||||
{
|
||||
QAngle viewangles;
|
||||
engine->GetViewAngles( viewangles );
|
||||
|
||||
if( viewangles.x > PHYSCANNON_RAISE_VIEW_GOAL + 1.0f )
|
||||
{
|
||||
float flDelta = PHYSCANNON_RAISE_VIEW_GOAL - viewangles.x;
|
||||
viewangles.x += (flDelta * flDT);
|
||||
engine->SetViewAngles(viewangles);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We've reached our goal. Ignore the forced view angles for now.
|
||||
m_flTimeIgnoreForceView = m_flTimeForceView + 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::ClientThink();
|
||||
}
|
||||
|
||||
|
||||
187
sp/src/game/client/hl2/c_weapon_stunstick.cpp
Normal file
187
sp/src/game/client/hl2/c_weapon_stunstick.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "c_basehlcombatweapon.h"
|
||||
#include "iviewrender_beams.h"
|
||||
#include "beam_shared.h"
|
||||
#include "c_weapon__stubs.h"
|
||||
#include "materialsystem/imaterial.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
#include "beamdraw.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectStunstick )
|
||||
CLIENTEFFECT_MATERIAL( "effects/stunstick" )
|
||||
CLIENTEFFECT_REGISTER_END()
|
||||
|
||||
class C_WeaponStunStick : public C_BaseHLBludgeonWeapon
|
||||
{
|
||||
DECLARE_CLASS( C_WeaponStunStick, C_BaseHLBludgeonWeapon );
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
int DrawModel( int flags )
|
||||
{
|
||||
//FIXME: This sucks, but I can't easily create temp ents...
|
||||
|
||||
if ( m_bActive )
|
||||
{
|
||||
Vector vecOrigin;
|
||||
QAngle vecAngles;
|
||||
float color[3];
|
||||
|
||||
color[0] = color[1] = color[2] = random->RandomFloat( 0.1f, 0.2f );
|
||||
|
||||
GetAttachment( 1, vecOrigin, vecAngles );
|
||||
|
||||
Vector vForward;
|
||||
AngleVectors( vecAngles, &vForward );
|
||||
|
||||
Vector vEnd = vecOrigin - vForward * 1.0f;
|
||||
|
||||
IMaterial *pMaterial = materials->FindMaterial( "effects/stunstick", NULL, false );
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->Bind( pMaterial );
|
||||
DrawHalo( pMaterial, vEnd, random->RandomFloat( 4.0f, 6.0f ), color );
|
||||
|
||||
color[0] = color[1] = color[2] = random->RandomFloat( 0.9f, 1.0f );
|
||||
|
||||
DrawHalo( pMaterial, vEnd, random->RandomFloat( 2.0f, 3.0f ), color );
|
||||
}
|
||||
|
||||
return BaseClass::DrawModel( flags );
|
||||
}
|
||||
|
||||
// Do part of our effect
|
||||
void ClientThink( void )
|
||||
{
|
||||
// Update our effects
|
||||
if ( m_bActive &&
|
||||
gpGlobals->frametime != 0.0f &&
|
||||
( random->RandomInt( 0, 5 ) == 0 ) )
|
||||
{
|
||||
Vector vecOrigin;
|
||||
QAngle vecAngles;
|
||||
|
||||
GetAttachment( 1, vecOrigin, vecAngles );
|
||||
|
||||
Vector vForward;
|
||||
AngleVectors( vecAngles, &vForward );
|
||||
|
||||
Vector vEnd = vecOrigin - vForward * 1.0f;
|
||||
|
||||
// Inner beams
|
||||
BeamInfo_t beamInfo;
|
||||
|
||||
beamInfo.m_vecStart = vEnd;
|
||||
Vector offset = RandomVector( -6, 2 );
|
||||
|
||||
offset += Vector(2,2,2);
|
||||
beamInfo.m_vecEnd = vecOrigin + offset;
|
||||
|
||||
beamInfo.m_pStartEnt= cl_entitylist->GetEnt( BEAMENT_ENTITY( entindex() ) );
|
||||
beamInfo.m_pEndEnt = cl_entitylist->GetEnt( BEAMENT_ENTITY( entindex() ) );
|
||||
beamInfo.m_nStartAttachment = 1;
|
||||
beamInfo.m_nEndAttachment = 2;
|
||||
|
||||
beamInfo.m_nType = TE_BEAMTESLA;
|
||||
beamInfo.m_pszModelName = "sprites/physbeam.vmt";
|
||||
beamInfo.m_flHaloScale = 0.0f;
|
||||
beamInfo.m_flLife = 0.01f;
|
||||
beamInfo.m_flWidth = random->RandomFloat( 0.5f, 2.0f );
|
||||
beamInfo.m_flEndWidth = 0;
|
||||
beamInfo.m_flFadeLength = 0.0f;
|
||||
beamInfo.m_flAmplitude = random->RandomFloat( 1, 2 );
|
||||
beamInfo.m_flBrightness = 255.0;
|
||||
beamInfo.m_flSpeed = 0.0;
|
||||
beamInfo.m_nStartFrame = 0.0;
|
||||
beamInfo.m_flFrameRate = 1.0f;
|
||||
beamInfo.m_flRed = 255.0f;;
|
||||
beamInfo.m_flGreen = 255.0f;
|
||||
beamInfo.m_flBlue = 255.0f;
|
||||
beamInfo.m_nSegments = 8;
|
||||
beamInfo.m_bRenderable = true;
|
||||
beamInfo.m_nFlags = (FBEAM_ONLYNOISEONCE|FBEAM_SHADEOUT);
|
||||
|
||||
beams->CreateBeamPoints( beamInfo );
|
||||
}
|
||||
}
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void StartStunEffect( void )
|
||||
{
|
||||
//TODO: Play startup sound
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void StopStunEffect( void )
|
||||
{
|
||||
//TODO: Play shutdown sound
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : RenderGroup_t
|
||||
//-----------------------------------------------------------------------------
|
||||
RenderGroup_t GetRenderGroup( void )
|
||||
{
|
||||
return RENDER_GROUP_TRANSLUCENT_ENTITY;
|
||||
}
|
||||
|
||||
private:
|
||||
CNetworkVar( bool, m_bActive );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pData -
|
||||
// *pStruct -
|
||||
// *pOut -
|
||||
//-----------------------------------------------------------------------------
|
||||
void RecvProxy_StunActive( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
bool state = *((bool *)&pData->m_Value.m_Int);
|
||||
|
||||
C_WeaponStunStick *pWeapon = (C_WeaponStunStick *) pStruct;
|
||||
|
||||
if ( state )
|
||||
{
|
||||
// Turn on the effect
|
||||
pWeapon->StartStunEffect();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Turn off the effect
|
||||
pWeapon->StopStunEffect();
|
||||
}
|
||||
|
||||
*(bool *)pOut = state;
|
||||
}
|
||||
|
||||
STUB_WEAPON_CLASS_IMPLEMENT( weapon_stunstick, C_WeaponStunStick );
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_WeaponStunStick, DT_WeaponStunStick, CWeaponStunStick )
|
||||
RecvPropInt( RECVINFO(m_bActive), 0, RecvProxy_StunActive ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
99
sp/src/game/client/hl2/clientmode_hlnormal.cpp
Normal file
99
sp/src/game/client/hl2/clientmode_hlnormal.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Draws the normal TF2 or HL2 HUD.
|
||||
//
|
||||
//=============================================================================
|
||||
#include "cbase.h"
|
||||
#include "clientmode_hlnormal.h"
|
||||
#include "vgui_int.h"
|
||||
#include "hud.h"
|
||||
#include <vgui/IInput.h>
|
||||
#include <vgui/IPanel.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/AnimationController.h>
|
||||
#include "iinput.h"
|
||||
#include "ienginevgui.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern bool g_bRollingCredits;
|
||||
|
||||
ConVar fov_desired( "fov_desired", "75", FCVAR_ARCHIVE | FCVAR_USERINFO, "Sets the base field-of-view.", true, 75.0, true, 90.0 );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Globals
|
||||
//-----------------------------------------------------------------------------
|
||||
vgui::HScheme g_hVGuiCombineScheme = 0;
|
||||
|
||||
|
||||
// Instance the singleton and expose the interface to it.
|
||||
IClientMode *GetClientModeNormal()
|
||||
{
|
||||
static ClientModeHLNormal g_ClientModeNormal;
|
||||
return &g_ClientModeNormal;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: this is the viewport that contains all the hud elements
|
||||
//-----------------------------------------------------------------------------
|
||||
class CHudViewport : public CBaseViewport
|
||||
{
|
||||
private:
|
||||
DECLARE_CLASS_SIMPLE( CHudViewport, CBaseViewport );
|
||||
|
||||
protected:
|
||||
virtual void ApplySchemeSettings( vgui::IScheme *pScheme )
|
||||
{
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
|
||||
gHUD.InitColors( pScheme );
|
||||
|
||||
SetPaintBackgroundEnabled( false );
|
||||
}
|
||||
|
||||
virtual void CreateDefaultPanels( void ) { /* don't create any panels yet*/ };
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ClientModeHLNormal implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
ClientModeHLNormal::ClientModeHLNormal()
|
||||
{
|
||||
m_pViewport = new CHudViewport();
|
||||
m_pViewport->Start( gameuifuncs, gameeventmanager );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
ClientModeHLNormal::~ClientModeHLNormal()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void ClientModeHLNormal::Init()
|
||||
{
|
||||
BaseClass::Init();
|
||||
|
||||
// Load up the combine control panel scheme
|
||||
g_hVGuiCombineScheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), IsXbox() ? "resource/ClientScheme.res" : "resource/CombinePanelScheme.res", "CombineScheme" );
|
||||
if (!g_hVGuiCombineScheme)
|
||||
{
|
||||
Warning( "Couldn't load combine panel scheme!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientModeHLNormal::ShouldDrawCrosshair( void )
|
||||
{
|
||||
return ( g_bRollingCredits == false );
|
||||
}
|
||||
|
||||
|
||||
|
||||
45
sp/src/game/client/hl2/clientmode_hlnormal.h
Normal file
45
sp/src/game/client/hl2/clientmode_hlnormal.h
Normal file
@@ -0,0 +1,45 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#if !defined( CLIENTMODE_HLNORMAL_H )
|
||||
#define CLIENTMODE_HLNORMAL_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "clientmode_shared.h"
|
||||
#include <vgui_controls/EditablePanel.h>
|
||||
#include <vgui/Cursor.h>
|
||||
|
||||
class CHudViewport;
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
typedef unsigned long HScheme;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class ClientModeHLNormal : public ClientModeShared
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( ClientModeHLNormal, ClientModeShared );
|
||||
|
||||
ClientModeHLNormal();
|
||||
~ClientModeHLNormal();
|
||||
|
||||
virtual void Init();
|
||||
virtual bool ShouldDrawCrosshair( void );
|
||||
};
|
||||
|
||||
extern IClientMode *GetClientModeNormal();
|
||||
extern vgui::HScheme g_hVGuiCombineScheme;
|
||||
|
||||
#endif // CLIENTMODE_HLNORMAL_H
|
||||
334
sp/src/game/client/hl2/fx_antlion.cpp
Normal file
334
sp/src/game/client/hl2/fx_antlion.cpp
Normal file
@@ -0,0 +1,334 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "fx.h"
|
||||
#include "c_gib.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#include "iefx.h"
|
||||
#include "decals.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
PMaterialHandle g_Material_Blood[2] = { NULL, NULL };
|
||||
|
||||
#ifdef _XBOX
|
||||
|
||||
// XBox only uses a few gibs
|
||||
#define NUM_ANTLION_GIBS 3
|
||||
const char *pszAntlionGibs[NUM_ANTLION_GIBS] = {
|
||||
"models/gibs/antlion_gib_large_2.mdl", // Head
|
||||
"models/gibs/antlion_gib_medium_1.mdl", // Pincher
|
||||
"models/gibs/antlion_gib_medium_2.mdl", // Leg
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
// Use all the gibs
|
||||
#define NUM_ANTLION_GIBS_UNIQUE 3
|
||||
const char *pszAntlionGibs_Unique[NUM_ANTLION_GIBS_UNIQUE] = {
|
||||
"models/gibs/antlion_gib_large_1.mdl",
|
||||
"models/gibs/antlion_gib_large_2.mdl",
|
||||
"models/gibs/antlion_gib_large_3.mdl"
|
||||
};
|
||||
|
||||
#define NUM_ANTLION_GIBS_MEDIUM 3
|
||||
const char *pszAntlionGibs_Medium[NUM_ANTLION_GIBS_MEDIUM] = {
|
||||
"models/gibs/antlion_gib_medium_1.mdl",
|
||||
"models/gibs/antlion_gib_medium_2.mdl",
|
||||
"models/gibs/antlion_gib_medium_3.mdl"
|
||||
};
|
||||
|
||||
// XBox doesn't use the smaller gibs, so don't cache them
|
||||
#define NUM_ANTLION_GIBS_SMALL 3
|
||||
const char *pszAntlionGibs_Small[NUM_ANTLION_GIBS_SMALL] = {
|
||||
"models/gibs/antlion_gib_small_1.mdl",
|
||||
"models/gibs/antlion_gib_small_2.mdl",
|
||||
"models/gibs/antlion_gib_small_3.mdl"
|
||||
};
|
||||
#endif
|
||||
|
||||
ConVar g_antlion_maxgibs( "g_antlion_maxgibs", "16", FCVAR_ARCHIVE );
|
||||
|
||||
void CAntlionGibManager::LevelInitPreEntity( void )
|
||||
{
|
||||
m_LRU.Purge();
|
||||
}
|
||||
|
||||
CAntlionGibManager s_AntlionGibManager( "CAntlionGibManager" );
|
||||
|
||||
void CAntlionGibManager::AddGib( C_BaseEntity *pEntity )
|
||||
{
|
||||
m_LRU.AddToTail( pEntity );
|
||||
}
|
||||
|
||||
void CAntlionGibManager::RemoveGib( C_BaseEntity *pEntity )
|
||||
{
|
||||
m_LRU.FindAndRemove( pEntity );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Methods of IGameSystem
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAntlionGibManager::Update( float frametime )
|
||||
{
|
||||
if ( m_LRU.Count() < g_antlion_maxgibs.GetInt() )
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
i = m_LRU.Head();
|
||||
|
||||
if ( m_LRU[ i ].Get() )
|
||||
{
|
||||
m_LRU[ i ].Get()->SetNextClientThink( gpGlobals->curtime );
|
||||
}
|
||||
|
||||
m_LRU.Remove(i);
|
||||
}
|
||||
|
||||
// Antlion gib - marks surfaces when it bounces
|
||||
|
||||
class C_AntlionGib : public C_Gib
|
||||
{
|
||||
typedef C_Gib BaseClass;
|
||||
public:
|
||||
|
||||
static C_AntlionGib *CreateClientsideGib( const char *pszModelName, Vector vecOrigin, Vector vecForceDir, AngularImpulse vecAngularImp, float m_flLifetime = DEFAULT_GIB_LIFETIME )
|
||||
{
|
||||
C_AntlionGib *pGib = new C_AntlionGib;
|
||||
|
||||
if ( pGib == NULL )
|
||||
return NULL;
|
||||
|
||||
if ( pGib->InitializeGib( pszModelName, vecOrigin, vecForceDir, vecAngularImp, m_flLifetime ) == false )
|
||||
return NULL;
|
||||
|
||||
s_AntlionGibManager.AddGib( pGib );
|
||||
|
||||
return pGib;
|
||||
}
|
||||
|
||||
// Decal the surface
|
||||
virtual void HitSurface( C_BaseEntity *pOther )
|
||||
{
|
||||
//JDW: Removed for the time being
|
||||
|
||||
/*
|
||||
int index = decalsystem->GetDecalIndexForName( "YellowBlood" );
|
||||
|
||||
if (index >= 0 )
|
||||
{
|
||||
effects->DecalShoot( index, pOther->entindex(), pOther->GetModel(), pOther->GetAbsOrigin(), pOther->GetAbsAngles(), GetAbsOrigin(), 0, 0 );
|
||||
}
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &origin -
|
||||
//-----------------------------------------------------------------------------
|
||||
void FX_AntlionGib( const Vector &origin, const Vector &direction, float scale )
|
||||
{
|
||||
Vector offset;
|
||||
|
||||
#ifdef _XBOX
|
||||
|
||||
// Throw less gibs for XBox
|
||||
for ( int i = 0; i < NUM_ANTLION_GIBS; i++ )
|
||||
{
|
||||
offset = RandomVector( -32, 32 ) + origin;
|
||||
C_AntlionGib::CreateClientsideGib( pszAntlionGibs[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 250 * scale ), RandomAngularImpulse( -32, 32 ), 1.0f );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int numGibs = random->RandomInt( 1, NUM_ANTLION_GIBS_UNIQUE );
|
||||
|
||||
// Spawn all the unique gibs
|
||||
for ( int i = 0; i < numGibs; i++ )
|
||||
{
|
||||
offset = RandomVector( -16, 16 ) + origin;
|
||||
|
||||
C_AntlionGib::CreateClientsideGib( pszAntlionGibs_Unique[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 150 * scale ), RandomAngularImpulse( -32, 32 ), 2.0f);
|
||||
}
|
||||
|
||||
numGibs = random->RandomInt( 1, NUM_ANTLION_GIBS_MEDIUM );
|
||||
|
||||
// Spawn all the medium gibs
|
||||
for ( int i = 0; i < numGibs; i++ )
|
||||
{
|
||||
offset = RandomVector( -16, 16 ) + origin;
|
||||
|
||||
C_AntlionGib::CreateClientsideGib( pszAntlionGibs_Medium[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 250 * scale ), RandomAngularImpulse( -200, 200 ), 1.0f );
|
||||
}
|
||||
|
||||
numGibs = random->RandomInt( 1, NUM_ANTLION_GIBS_SMALL );
|
||||
|
||||
// Spawn all the small gibs
|
||||
for ( int i = 0; i < NUM_ANTLION_GIBS_SMALL; i++ )
|
||||
{
|
||||
offset = RandomVector( -16, 16 ) + origin;
|
||||
|
||||
C_AntlionGib::CreateClientsideGib( pszAntlionGibs_Small[i], offset, ( direction + RandomVector( -0.8f, 0.8f ) ) * ( 400 * scale ), RandomAngularImpulse( -300, 300 ), 0.5f );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _XBOX
|
||||
|
||||
//
|
||||
// Throw some blood
|
||||
//
|
||||
|
||||
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_AntlionGib" );
|
||||
pSimple->SetSortOrigin( origin );
|
||||
pSimple->GetBinding().SetBBox( origin - Vector(64,64,64), origin + Vector(64,64,64) );
|
||||
|
||||
// Cache this if we're not already
|
||||
if ( g_Material_Blood[0] == NULL )
|
||||
{
|
||||
g_Material_Blood[0] = g_Mat_BloodPuff[0];
|
||||
}
|
||||
|
||||
if ( g_Material_Blood[1] == NULL )
|
||||
{
|
||||
g_Material_Blood[1] = g_Mat_BloodPuff[1];
|
||||
}
|
||||
|
||||
Vector vDir;
|
||||
vDir.Random( -1.0f, 1.0f );
|
||||
|
||||
// Gore bits
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Material_Blood[0], origin + RandomVector(-16,16));
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
sParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
|
||||
|
||||
float speed = random->RandomFloat( 16.0f, 64.0f );
|
||||
|
||||
sParticle->m_vecVelocity.Init();
|
||||
|
||||
sParticle->m_uchColor[0] = 255;
|
||||
sParticle->m_uchColor[1] = 200;
|
||||
sParticle->m_uchColor[2] = 32;
|
||||
sParticle->m_uchStartAlpha = 255;
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
sParticle->m_uchStartSize = random->RandomInt( 4, 16 );
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 4;
|
||||
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = 0.0f;
|
||||
}
|
||||
|
||||
// Middle core
|
||||
SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Material_Blood[1], origin );
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
sParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.75f );
|
||||
|
||||
float speed = random->RandomFloat( 16.0f, 64.0f );
|
||||
|
||||
sParticle->m_vecVelocity = vDir * -speed;
|
||||
sParticle->m_vecVelocity[2] += 16.0f;
|
||||
|
||||
sParticle->m_uchColor[0] = 255;
|
||||
sParticle->m_uchColor[1] = 200;
|
||||
sParticle->m_uchColor[2] = 32;
|
||||
sParticle->m_uchStartAlpha = random->RandomInt( 64, 128 );
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
sParticle->m_uchStartSize = random->RandomInt( 16, 32 );
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 3;
|
||||
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = random->RandomFloat( -0.2f, 0.2f );
|
||||
|
||||
#else
|
||||
|
||||
//
|
||||
// Non-XBox blood
|
||||
//
|
||||
|
||||
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_AntlionGib" );
|
||||
pSimple->SetSortOrigin( origin );
|
||||
|
||||
Vector vDir;
|
||||
|
||||
vDir.Random( -1.0f, 1.0f );
|
||||
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return;
|
||||
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
sParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.75f );
|
||||
|
||||
float speed = random->RandomFloat( 16.0f, 64.0f );
|
||||
|
||||
sParticle->m_vecVelocity = vDir * -speed;
|
||||
sParticle->m_vecVelocity[2] += 16.0f;
|
||||
|
||||
sParticle->m_uchColor[0] = 255;
|
||||
sParticle->m_uchColor[1] = 200;
|
||||
sParticle->m_uchColor[2] = 32;
|
||||
sParticle->m_uchStartAlpha = 255;
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
sParticle->m_uchStartSize = random->RandomInt( 16, 32 );
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2;
|
||||
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f );
|
||||
}
|
||||
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], origin );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
sParticle->m_flDieTime = random->RandomFloat( 0.5f, 0.75f );
|
||||
|
||||
float speed = random->RandomFloat( 16.0f, 64.0f );
|
||||
|
||||
sParticle->m_vecVelocity = vDir * -speed;
|
||||
sParticle->m_vecVelocity[2] += 16.0f;
|
||||
|
||||
sParticle->m_uchColor[0] = 255;
|
||||
sParticle->m_uchColor[1] = 200;
|
||||
sParticle->m_uchColor[2] = 32;
|
||||
sParticle->m_uchStartAlpha = random->RandomInt( 64, 128 );
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
sParticle->m_uchStartSize = random->RandomInt( 16, 32 );
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2;
|
||||
sParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = random->RandomFloat( -1.0f, 1.0f );
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &data -
|
||||
//-----------------------------------------------------------------------------
|
||||
void AntlionGibCallback( const CEffectData &data )
|
||||
{
|
||||
FX_AntlionGib( data.m_vOrigin, data.m_vNormal, data.m_flScale );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( "AntlionGib", AntlionGibCallback );
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user