588 lines
17 KiB
C++
588 lines
17 KiB
C++
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "SpriteTrail.h"
|
|
|
|
#ifdef CLIENT_DLL
|
|
|
|
#include "clientsideeffects.h"
|
|
#include "materialsystem/IMaterialSystem.h"
|
|
#include "materialsystem/IMesh.h"
|
|
#include "mathlib/VMatrix.h"
|
|
#include "view.h"
|
|
#include "beamdraw.h"
|
|
#include "enginesprite.h"
|
|
#include "tier0/vprof.h"
|
|
|
|
extern CEngineSprite *Draw_SetSpriteTexture( const model_t *pSpriteModel, int frame, int rendermode );
|
|
|
|
#endif // CLIENT_DLL
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// constants
|
|
//-----------------------------------------------------------------------------
|
|
#define SCREEN_SPACE_TRAILS 0
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Save/Restore
|
|
//-----------------------------------------------------------------------------
|
|
#if defined( CLIENT_DLL )
|
|
|
|
BEGIN_SIMPLE_DATADESC( TrailPoint_t )
|
|
// DEFINE_FIELD( m_vecScreenPos, FIELD_CLASSCHECK_IGNORE ) // do this or else we get a warning about multiply-defined fields
|
|
#if SCREEN_SPACE_TRAILS
|
|
DEFINE_FIELD( m_vecScreenPos, FIELD_VECTOR ),
|
|
#else
|
|
DEFINE_FIELD( m_vecScreenPos, FIELD_POSITION_VECTOR ),
|
|
#endif
|
|
|
|
DEFINE_FIELD( m_flDieTime, FIELD_TIME ),
|
|
DEFINE_FIELD( m_flTexCoord, FIELD_FLOAT ),
|
|
DEFINE_FIELD( m_flWidthVariance,FIELD_FLOAT ),
|
|
END_DATADESC()
|
|
|
|
#endif
|
|
|
|
BEGIN_DATADESC( CSpriteTrail )
|
|
|
|
DEFINE_KEYFIELD( m_flLifeTime, FIELD_FLOAT, "lifetime" ),
|
|
DEFINE_KEYFIELD( m_flStartWidth, FIELD_FLOAT, "startwidth" ),
|
|
DEFINE_KEYFIELD( m_flEndWidth, FIELD_FLOAT, "endwidth" ),
|
|
DEFINE_KEYFIELD( m_iszSpriteName, FIELD_STRING, "spritename" ),
|
|
DEFINE_KEYFIELD( m_bAnimate, FIELD_BOOLEAN, "animate" ),
|
|
DEFINE_FIELD( m_flStartWidthVariance, FIELD_FLOAT ),
|
|
DEFINE_FIELD( m_flTextureRes, FIELD_FLOAT ),
|
|
DEFINE_FIELD( m_flMinFadeLength, FIELD_FLOAT ),
|
|
DEFINE_FIELD( m_vecSkyboxOrigin, FIELD_POSITION_VECTOR ),
|
|
DEFINE_FIELD( m_flSkyboxScale, FIELD_FLOAT ),
|
|
|
|
// These are client-only
|
|
#if defined( CLIENT_DLL )
|
|
DEFINE_EMBEDDED_AUTO_ARRAY( m_vecSteps ),
|
|
DEFINE_FIELD( m_nFirstStep, FIELD_INTEGER ),
|
|
DEFINE_FIELD( m_nStepCount, FIELD_INTEGER ),
|
|
DEFINE_FIELD( m_flUpdateTime, FIELD_TIME ),
|
|
DEFINE_FIELD( m_vecPrevSkyboxOrigin, FIELD_POSITION_VECTOR ),
|
|
DEFINE_FIELD( m_flPrevSkyboxScale, FIELD_FLOAT ),
|
|
DEFINE_FIELD( m_vecRenderMins, FIELD_VECTOR ),
|
|
DEFINE_FIELD( m_vecRenderMaxs, FIELD_VECTOR ),
|
|
#endif
|
|
|
|
END_DATADESC()
|
|
|
|
LINK_ENTITY_TO_CLASS( env_spritetrail, CSpriteTrail );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Networking
|
|
//-----------------------------------------------------------------------------
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( SpriteTrail, DT_SpriteTrail );
|
|
|
|
BEGIN_NETWORK_TABLE( CSpriteTrail, DT_SpriteTrail )
|
|
#if !defined( CLIENT_DLL )
|
|
SendPropFloat( SENDINFO(m_flLifeTime), 0, SPROP_NOSCALE ),
|
|
SendPropFloat( SENDINFO(m_flStartWidth), 0, SPROP_NOSCALE ),
|
|
SendPropFloat( SENDINFO(m_flEndWidth), 0, SPROP_NOSCALE ),
|
|
SendPropFloat( SENDINFO(m_flStartWidthVariance), 0, SPROP_NOSCALE ),
|
|
SendPropFloat( SENDINFO(m_flTextureRes), 0, SPROP_NOSCALE ),
|
|
SendPropFloat( SENDINFO(m_flMinFadeLength), 0, SPROP_NOSCALE ),
|
|
SendPropVector( SENDINFO(m_vecSkyboxOrigin),0, SPROP_NOSCALE ),
|
|
SendPropFloat( SENDINFO(m_flSkyboxScale), 0, SPROP_NOSCALE ),
|
|
#else
|
|
RecvPropFloat( RECVINFO(m_flLifeTime)),
|
|
RecvPropFloat( RECVINFO(m_flStartWidth)),
|
|
RecvPropFloat( RECVINFO(m_flEndWidth)),
|
|
RecvPropFloat( RECVINFO(m_flStartWidthVariance)),
|
|
RecvPropFloat( RECVINFO(m_flTextureRes)),
|
|
RecvPropFloat( RECVINFO(m_flMinFadeLength)),
|
|
RecvPropVector( RECVINFO(m_vecSkyboxOrigin)),
|
|
RecvPropFloat( RECVINFO(m_flSkyboxScale)),
|
|
#endif
|
|
END_NETWORK_TABLE()
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Prediction
|
|
//-----------------------------------------------------------------------------
|
|
BEGIN_PREDICTION_DATA( CSpriteTrail )
|
|
END_PREDICTION_DATA()
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CSpriteTrail::CSpriteTrail( void )
|
|
{
|
|
#ifdef CLIENT_DLL
|
|
m_nFirstStep = 0;
|
|
m_nStepCount = 0;
|
|
#endif
|
|
|
|
m_flStartWidthVariance = 0;
|
|
m_vecSkyboxOrigin.Init( 0, 0, 0 );
|
|
m_flSkyboxScale = 1.0f;
|
|
m_flEndWidth = -1.0f;
|
|
}
|
|
|
|
void CSpriteTrail::Spawn( void )
|
|
{
|
|
#ifdef CLIENT_DLL
|
|
BaseClass::Spawn();
|
|
#else
|
|
|
|
if ( GetModelName() != NULL_STRING )
|
|
{
|
|
BaseClass::Spawn();
|
|
return;
|
|
}
|
|
|
|
SetModelName( m_iszSpriteName );
|
|
BaseClass::Spawn();
|
|
|
|
SetSolid( SOLID_NONE );
|
|
SetMoveType( MOVETYPE_NOCLIP );
|
|
|
|
SetCollisionBounds( vec3_origin, vec3_origin );
|
|
TurnOn();
|
|
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets parameters of the sprite trail
|
|
//-----------------------------------------------------------------------------
|
|
void CSpriteTrail::Precache( void )
|
|
{
|
|
BaseClass::Precache();
|
|
|
|
if ( m_iszSpriteName != NULL_STRING )
|
|
{
|
|
PrecacheModel( STRING(m_iszSpriteName) );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets parameters of the sprite trail
|
|
//-----------------------------------------------------------------------------
|
|
void CSpriteTrail::SetLifeTime( float time )
|
|
{
|
|
m_flLifeTime = time;
|
|
}
|
|
|
|
void CSpriteTrail::SetStartWidth( float flStartWidth )
|
|
{
|
|
m_flStartWidth = flStartWidth;
|
|
m_flStartWidth /= m_flSkyboxScale;
|
|
}
|
|
|
|
void CSpriteTrail::SetStartWidthVariance( float flStartWidthVariance )
|
|
{
|
|
m_flStartWidthVariance = flStartWidthVariance;
|
|
m_flStartWidthVariance /= m_flSkyboxScale;
|
|
}
|
|
|
|
void CSpriteTrail::SetEndWidth( float flEndWidth )
|
|
{
|
|
m_flEndWidth = flEndWidth;
|
|
m_flEndWidth /= m_flSkyboxScale;
|
|
}
|
|
|
|
void CSpriteTrail::SetTextureResolution( float flTexelsPerInch )
|
|
{
|
|
m_flTextureRes = flTexelsPerInch;
|
|
m_flTextureRes *= m_flSkyboxScale;
|
|
}
|
|
|
|
void CSpriteTrail::SetMinFadeLength( float flMinFadeLength )
|
|
{
|
|
m_flMinFadeLength = flMinFadeLength;
|
|
m_flMinFadeLength /= m_flSkyboxScale;
|
|
}
|
|
|
|
void CSpriteTrail::SetSkybox( const Vector &vecSkyboxOrigin, float flSkyboxScale )
|
|
{
|
|
m_flTextureRes /= m_flSkyboxScale;
|
|
m_flMinFadeLength *= m_flSkyboxScale;
|
|
m_flStartWidth *= m_flSkyboxScale;
|
|
m_flEndWidth *= m_flSkyboxScale;
|
|
m_flStartWidthVariance *= m_flSkyboxScale;
|
|
|
|
m_vecSkyboxOrigin = vecSkyboxOrigin;
|
|
m_flSkyboxScale = flSkyboxScale;
|
|
|
|
m_flTextureRes *= m_flSkyboxScale;
|
|
m_flMinFadeLength /= m_flSkyboxScale;
|
|
m_flStartWidth /= m_flSkyboxScale;
|
|
m_flEndWidth /= m_flSkyboxScale;
|
|
m_flStartWidthVariance /= m_flSkyboxScale;
|
|
|
|
if ( IsInSkybox() )
|
|
{
|
|
AddEFlags( EFL_IN_SKYBOX );
|
|
}
|
|
else
|
|
{
|
|
RemoveEFlags( EFL_IN_SKYBOX );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Is the trail in the skybox?
|
|
//-----------------------------------------------------------------------------
|
|
bool CSpriteTrail::IsInSkybox() const
|
|
{
|
|
return (m_flSkyboxScale != 1.0f) || (m_vecSkyboxOrigin != vec3_origin);
|
|
}
|
|
|
|
|
|
#ifdef CLIENT_DLL
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// On data update
|
|
//-----------------------------------------------------------------------------
|
|
void CSpriteTrail::OnPreDataChanged( DataUpdateType_t updateType )
|
|
{
|
|
BaseClass::OnPreDataChanged( updateType );
|
|
m_vecPrevSkyboxOrigin = m_vecSkyboxOrigin;
|
|
m_flPrevSkyboxScale = m_flSkyboxScale;
|
|
}
|
|
|
|
void CSpriteTrail::OnDataChanged( DataUpdateType_t updateType )
|
|
{
|
|
BaseClass::OnDataChanged( updateType );
|
|
if ( updateType == DATA_UPDATE_CREATED )
|
|
{
|
|
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
|
}
|
|
else
|
|
{
|
|
if ((m_flPrevSkyboxScale != m_flSkyboxScale) || (m_vecPrevSkyboxOrigin != m_vecSkyboxOrigin))
|
|
{
|
|
ConvertSkybox();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Compute position + bounding box
|
|
//-----------------------------------------------------------------------------
|
|
void CSpriteTrail::ClientThink()
|
|
{
|
|
// Update the trail + bounding box
|
|
UpdateTrail();
|
|
UpdateBoundingBox();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Render bounds
|
|
//-----------------------------------------------------------------------------
|
|
void CSpriteTrail::GetRenderBounds( Vector& mins, Vector& maxs )
|
|
{
|
|
mins = m_vecRenderMins;
|
|
maxs = m_vecRenderMaxs;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Converts the trail when it changes skyboxes
|
|
//-----------------------------------------------------------------------------
|
|
void CSpriteTrail::ConvertSkybox()
|
|
{
|
|
for ( int i = 0; i < m_nStepCount; ++i )
|
|
{
|
|
// This makes it so that we're always drawing to the current location
|
|
TrailPoint_t *pPoint = GetTrailPoint(i);
|
|
|
|
VectorSubtract( pPoint->m_vecScreenPos, m_vecPrevSkyboxOrigin, pPoint->m_vecScreenPos );
|
|
pPoint->m_vecScreenPos *= m_flPrevSkyboxScale / m_flSkyboxScale;
|
|
VectorSubtract( pPoint->m_vecScreenPos, m_vecSkyboxOrigin, pPoint->m_vecScreenPos );
|
|
pPoint->m_flWidthVariance *= m_flPrevSkyboxScale / m_flSkyboxScale;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Gets at the nth item in the list
|
|
//-----------------------------------------------------------------------------
|
|
TrailPoint_t *CSpriteTrail::GetTrailPoint( int n )
|
|
{
|
|
Assert( n < MAX_SPRITE_TRAIL_POINTS );
|
|
COMPILE_TIME_ASSERT( (MAX_SPRITE_TRAIL_POINTS & (MAX_SPRITE_TRAIL_POINTS-1)) == 0 );
|
|
int nIndex = (n + m_nFirstStep) & MAX_SPRITE_TRAIL_MASK;
|
|
return &m_vecSteps[nIndex];
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CSpriteTrail::ComputeScreenPosition( Vector *pScreenPos )
|
|
{
|
|
#if SCREEN_SPACE_TRAILS
|
|
VMatrix viewMatrix;
|
|
materials->GetMatrix( MATERIAL_VIEW, &viewMatrix );
|
|
*pScreenPos = viewMatrix * GetRenderOrigin();
|
|
#else
|
|
*pScreenPos = GetRenderOrigin();
|
|
#endif
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Compute position + bounding box
|
|
//-----------------------------------------------------------------------------
|
|
void CSpriteTrail::UpdateBoundingBox( void )
|
|
{
|
|
Vector vecRenderOrigin = GetRenderOrigin();
|
|
m_vecRenderMins = vecRenderOrigin;
|
|
m_vecRenderMaxs = vecRenderOrigin;
|
|
|
|
float flMaxWidth = m_flStartWidth;
|
|
if (( m_flEndWidth >= 0.0f ) && ( m_flEndWidth > m_flStartWidth ))
|
|
{
|
|
flMaxWidth = m_flEndWidth;
|
|
}
|
|
|
|
Vector mins, maxs;
|
|
for ( int i = 0; i < m_nStepCount; ++i )
|
|
{
|
|
TrailPoint_t *pPoint = GetTrailPoint(i);
|
|
|
|
float flActualWidth = (flMaxWidth + pPoint->m_flWidthVariance) * 0.5f;
|
|
Vector size( flActualWidth, flActualWidth, flActualWidth );
|
|
VectorSubtract( pPoint->m_vecScreenPos, size, mins );
|
|
VectorAdd( pPoint->m_vecScreenPos, size, maxs );
|
|
|
|
VectorMin( m_vecRenderMins, mins, m_vecRenderMins );
|
|
VectorMax( m_vecRenderMaxs, maxs, m_vecRenderMaxs );
|
|
}
|
|
|
|
m_vecRenderMins -= vecRenderOrigin;
|
|
m_vecRenderMaxs -= vecRenderOrigin;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CSpriteTrail::UpdateTrail( void )
|
|
{
|
|
// Can't update too quickly
|
|
if ( m_flUpdateTime > gpGlobals->curtime )
|
|
return;
|
|
|
|
Vector screenPos;
|
|
ComputeScreenPosition( &screenPos );
|
|
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_SPRITE_TRAIL_POINTS )
|
|
{
|
|
--m_nStepCount;
|
|
++m_nFirstStep;
|
|
}
|
|
|
|
// Save off its screen position, not its world position
|
|
TrailPoint_t *pNewPoint = GetTrailPoint( m_nStepCount );
|
|
pNewPoint->m_vecScreenPos = screenPos;
|
|
pNewPoint->m_flDieTime = gpGlobals->curtime + m_flLifeTime;
|
|
pNewPoint->m_flWidthVariance = random->RandomFloat( -m_flStartWidthVariance, m_flStartWidthVariance );
|
|
if (pLast)
|
|
{
|
|
pNewPoint->m_flTexCoord = pLast->m_flTexCoord + pLast->m_vecScreenPos.DistTo( screenPos ) * m_flTextureRes;
|
|
}
|
|
else
|
|
{
|
|
pNewPoint->m_flTexCoord = 0.0f;
|
|
}
|
|
|
|
++m_nStepCount;
|
|
}
|
|
|
|
// Don't update again for a bit
|
|
m_flUpdateTime = gpGlobals->curtime + ( m_flLifeTime / (float) MAX_SPRITE_TRAIL_POINTS );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
int CSpriteTrail::DrawModel( int flags, const RenderableInstance_t &instance )
|
|
{
|
|
VPROF_BUDGET( "CSpriteTrail::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
|
|
|
|
// Must have at least one point
|
|
if ( m_nStepCount < 1 )
|
|
return 1;
|
|
|
|
//See if we should draw
|
|
if ( !IsVisible() || ( m_bReadyToDraw == false ) )
|
|
return 0;
|
|
|
|
CEngineSprite *pSprite = Draw_SetSpriteTexture( GetModel(), m_flFrame, GetRenderMode() );
|
|
if ( pSprite == NULL )
|
|
return 0;
|
|
|
|
// Specify all the segments.
|
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
|
|
CBeamSegDraw segDraw;
|
|
segDraw.Start( pRenderContext, m_nStepCount + 1, pSprite->GetMaterial( GetRenderMode() ) );
|
|
|
|
// Setup the first point, always emanating from the attachment point
|
|
TrailPoint_t *pLast = GetTrailPoint( m_nStepCount-1 );
|
|
TrailPoint_t currentPoint;
|
|
currentPoint.m_flDieTime = gpGlobals->curtime + m_flLifeTime;
|
|
ComputeScreenPosition( ¤tPoint.m_vecScreenPos );
|
|
currentPoint.m_flTexCoord = pLast->m_flTexCoord + currentPoint.m_vecScreenPos.DistTo(pLast->m_vecScreenPos) * m_flTextureRes;
|
|
currentPoint.m_flWidthVariance = 0.0f;
|
|
|
|
#if SCREEN_SPACE_TRAILS
|
|
VMatrix viewMatrix;
|
|
materials->GetMatrix( MATERIAL_VIEW, &viewMatrix );
|
|
viewMatrix = viewMatrix.InverseTR();
|
|
#endif
|
|
|
|
TrailPoint_t *pPrevPoint = NULL;
|
|
float flTailAlphaDist = m_flMinFadeLength;
|
|
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 = (pPoint->m_flDieTime - gpGlobals->curtime) / m_flLifeTime;
|
|
flLifePerc = clamp( flLifePerc, 0.0f, 1.0f );
|
|
|
|
color24 c = GetRenderColor();
|
|
BeamSeg_t curSeg;
|
|
curSeg.m_color.r = c.r; curSeg.m_color.g = c.g; curSeg.m_color.b = c.b;
|
|
|
|
float flAlphaFade = flLifePerc;
|
|
if ( flTailAlphaDist > 0.0f )
|
|
{
|
|
if ( pPrevPoint )
|
|
{
|
|
float flDist = pPoint->m_vecScreenPos.DistTo( pPrevPoint->m_vecScreenPos );
|
|
flTailAlphaDist -= flDist;
|
|
}
|
|
|
|
if ( flTailAlphaDist > 0.0f )
|
|
{
|
|
float flTailFade = Lerp( (m_flMinFadeLength - flTailAlphaDist) / m_flMinFadeLength, 0.0f, 1.0f );
|
|
if ( flTailFade < flAlphaFade )
|
|
{
|
|
flAlphaFade = flTailFade;
|
|
}
|
|
}
|
|
}
|
|
curSeg.m_color.a = GetRenderBrightness() * flAlphaFade;
|
|
|
|
#if SCREEN_SPACE_TRAILS
|
|
curSeg.m_vPos = viewMatrix * pPoint->m_vecScreenPos;
|
|
#else
|
|
curSeg.m_vPos = pPoint->m_vecScreenPos;
|
|
#endif
|
|
|
|
if ( m_flEndWidth >= 0.0f )
|
|
{
|
|
curSeg.m_flWidth = Lerp( flLifePerc, m_flEndWidth.Get(), m_flStartWidth.Get() );
|
|
}
|
|
else
|
|
{
|
|
curSeg.m_flWidth = m_flStartWidth.Get();
|
|
}
|
|
curSeg.m_flWidth += pPoint->m_flWidthVariance;
|
|
if ( curSeg.m_flWidth < 0.0f )
|
|
{
|
|
curSeg.m_flWidth = 0.0f;
|
|
}
|
|
|
|
curSeg.m_flTexCoord = pPoint->m_flTexCoord;
|
|
|
|
segDraw.NextSeg( &curSeg );
|
|
|
|
// See if we're done with this bad boy
|
|
if ( pPoint->m_flDieTime <= gpGlobals->curtime )
|
|
{
|
|
// Push this back onto the top for use
|
|
++m_nFirstStep;
|
|
--i;
|
|
--m_nStepCount;
|
|
}
|
|
|
|
pPrevPoint = pPoint;
|
|
}
|
|
|
|
segDraw.End();
|
|
|
|
return 1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Output : Vector const&
|
|
//-----------------------------------------------------------------------------
|
|
const Vector &CSpriteTrail::GetRenderOrigin( void )
|
|
{
|
|
static Vector vOrigin;
|
|
vOrigin = GetAbsOrigin();
|
|
|
|
if ( m_hAttachedToEntity )
|
|
{
|
|
C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity();
|
|
if ( ent )
|
|
{
|
|
QAngle dummyAngles;
|
|
ent->GetAttachment( m_nAttachment, vOrigin, dummyAngles );
|
|
}
|
|
}
|
|
|
|
return vOrigin;
|
|
}
|
|
|
|
const QAngle &CSpriteTrail::GetRenderAngles( void )
|
|
{
|
|
return vec3_angle;
|
|
}
|
|
|
|
#endif //CLIENT_DLL
|
|
|
|
#if !defined( CLIENT_DLL )
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : *pSpriteName -
|
|
// &origin -
|
|
// animate -
|
|
// Output : CSpriteTrail
|
|
//-----------------------------------------------------------------------------
|
|
CSpriteTrail *CSpriteTrail::SpriteTrailCreate( const char *pSpriteName, const Vector &origin, bool animate )
|
|
{
|
|
CSpriteTrail *pSprite = CREATE_ENTITY( CSpriteTrail, "env_spritetrail" );
|
|
|
|
pSprite->SpriteInit( pSpriteName, origin );
|
|
pSprite->SetSolid( SOLID_NONE );
|
|
pSprite->SetMoveType( MOVETYPE_NOCLIP );
|
|
|
|
UTIL_SetSize( pSprite, vec3_origin, vec3_origin );
|
|
|
|
if ( animate )
|
|
{
|
|
pSprite->TurnOn();
|
|
}
|
|
|
|
return pSprite;
|
|
}
|
|
|
|
#endif //CLIENT_DLL == false
|