You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
274 lines
7.5 KiB
274 lines
7.5 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Client's sheild entity |
|
// |
|
// $Workfile: $ |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include "cbase.h" |
|
#include "C_Shield.h" |
|
#include "tf_shieldshared.h" |
|
|
|
enum |
|
{ |
|
NUM_SUBDIVISIONS = 21, |
|
}; |
|
|
|
#define EMP_WAVE_AMPLITUDE 8.0f |
|
|
|
//----------------------------------------------------------------------------- |
|
// Mobile version of the shield |
|
//----------------------------------------------------------------------------- |
|
|
|
class C_ShieldMobile; |
|
class C_ShieldMobileActiveVertList : public IActiveVertList |
|
{ |
|
public: |
|
void Init( C_ShieldMobile *pShield, unsigned char *pVertList ); |
|
|
|
// IActiveVertList overrides. |
|
public: |
|
|
|
virtual int GetActiveVertState( int iVert ); |
|
virtual void SetActiveVertState( int iVert, int bOn ); |
|
|
|
private: |
|
C_ShieldMobile *m_pShield; |
|
unsigned char *m_pVertsActive; |
|
}; |
|
|
|
|
|
class C_ShieldMobile : public C_Shield |
|
{ |
|
DECLARE_CLASS( C_ShieldMobile, C_Shield ); |
|
public: |
|
DECLARE_CLIENTCLASS(); |
|
|
|
C_ShieldMobile(); |
|
~C_ShieldMobile(); |
|
|
|
void OnDataChanged( DataUpdateType_t updateType ); |
|
virtual void GetBounds( Vector& mins, Vector& maxs ); |
|
|
|
virtual void AddEntity( ); |
|
|
|
// Return true if the panel is active |
|
virtual bool IsPanelActive( int x, int y ); |
|
|
|
// Gets at the control point data; who knows how it was made? |
|
virtual void GetShieldData( Vector const** ppVerts, float* pOpacity, float* pBlend ); |
|
virtual const Vector& GetPoint( int x, int y ) { return m_ShieldEffect.GetPoint( x, y ); } |
|
|
|
virtual void SetThetaPhi( float flTheta, float flPhi ) { m_ShieldEffect.SetThetaPhi(flTheta,flPhi); } |
|
|
|
public: |
|
// networked data |
|
unsigned char m_pVertsActive[SHIELD_VERTEX_BYTES]; |
|
unsigned char m_ShieldState; |
|
|
|
private: |
|
C_ShieldMobile( const C_ShieldMobile& ); |
|
|
|
// Is a particular panel an edge? |
|
bool IsVertexValid( float s, float t ) const; |
|
void PreRender( ); |
|
|
|
private: |
|
CShieldEffect m_ShieldEffect; |
|
C_ShieldMobileActiveVertList m_VertList; |
|
float m_flTheta; |
|
float m_flPhi; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// C_ShieldMobileActiveVertList functions |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldMobileActiveVertList::Init( C_ShieldMobile *pShield, unsigned char *pVertList ) |
|
{ |
|
m_pShield = pShield; |
|
m_pVertsActive = pVertList; |
|
} |
|
|
|
|
|
int C_ShieldMobileActiveVertList::GetActiveVertState( int iVert ) |
|
{ |
|
return m_pVertsActive[iVert>>3] & (1 << (iVert & 7)); |
|
} |
|
|
|
|
|
void C_ShieldMobileActiveVertList::SetActiveVertState( int iVert, int bOn ) |
|
{ |
|
if ( bOn ) |
|
m_pVertsActive[iVert>>3] |= (1 << (iVert & 7)); |
|
else |
|
m_pVertsActive[iVert>>3] &= ~(1 << (iVert & 7)); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Data table |
|
//----------------------------------------------------------------------------- |
|
|
|
IMPLEMENT_CLIENTCLASS_DT(C_ShieldMobile, DT_Shield_Mobile, CShieldMobile) |
|
|
|
RecvPropInt( RECVINFO(m_ShieldState) ), |
|
RecvPropArray( |
|
RecvPropInt( RECVINFO(m_pVertsActive[0])), |
|
m_pVertsActive |
|
), |
|
RecvPropFloat( RECVINFO(m_flTheta) ), |
|
RecvPropFloat( RECVINFO(m_flPhi) ), |
|
|
|
END_RECV_TABLE() |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Various raycasting routines |
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
void ShieldTraceLine(const Vector &vecStart, const Vector &vecEnd, |
|
unsigned int mask, int collisionGroup, trace_t *ptr) |
|
{ |
|
UTIL_TraceLine(vecStart, vecEnd, mask, NULL, collisionGroup, ptr ); |
|
} |
|
|
|
void ShieldTraceHull(const Vector &vecStart, const Vector &vecEnd, |
|
const Vector &hullMin, const Vector &hullMax, |
|
unsigned int mask, int collisionGroup, trace_t *ptr) |
|
{ |
|
CTraceFilterWorldOnly traceFilter; |
|
enginetrace->TraceHull( vecStart, vecEnd, hullMin, hullMax, mask, &traceFilter, ptr ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Constructor, destructor |
|
//----------------------------------------------------------------------------- |
|
|
|
C_ShieldMobile::C_ShieldMobile() : m_ShieldEffect(ShieldTraceLine, ShieldTraceHull) |
|
{ |
|
m_VertList.Init( this, m_pVertsActive ); |
|
m_ShieldEffect.SetActiveVertexList( &m_VertList ); |
|
m_ShieldEffect.Spawn(vec3_origin, vec3_angle); |
|
InitShield( SHIELD_NUM_HORIZONTAL_POINTS, SHIELD_NUM_VERTICAL_POINTS, NUM_SUBDIVISIONS ); |
|
} |
|
|
|
C_ShieldMobile::~C_ShieldMobile() |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Get this after the data changes |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldMobile::OnDataChanged( DataUpdateType_t updateType ) |
|
{ |
|
BaseClass::OnDataChanged( updateType ); |
|
|
|
m_ShieldEffect.SetCurrentPosition( GetAbsOrigin() ); |
|
m_ShieldEffect.SetCurrentAngles( GetAbsAngles() ); |
|
m_ShieldEffect.SetThetaPhi( m_flTheta, m_flPhi ); |
|
|
|
// No need to simulate, just compute active panels from network data |
|
m_ShieldEffect.ComputeControlPoints(); |
|
m_ShieldEffect.ComputePanelActivity(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// A little pre-render processing |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldMobile::PreRender( ) |
|
{ |
|
if (m_ShieldState & SHIELD_MOBILE_EMP) |
|
{ |
|
// Decay fade if we've been EMPed or if we're inactive |
|
if (m_FadeValue > 0.0f) |
|
{ |
|
m_FadeValue -= gpGlobals->frametime / SHIELD_EMP_FADE_TIME; |
|
if (m_FadeValue < 0.0f) |
|
{ |
|
m_FadeValue = 0.0f; |
|
|
|
// Reset the shield to un-wobbled state |
|
m_ShieldEffect.ComputeControlPoints(); |
|
} |
|
else |
|
{ |
|
Vector dir; |
|
AngleVectors( m_ShieldEffect.GetCurrentAngles(), & dir ); |
|
|
|
// Futz with the control points if we've been EMPed |
|
for (int i = 0; i < SHIELD_NUM_CONTROL_POINTS; ++i) |
|
{ |
|
// Get the direction for the point |
|
float factor = -EMP_WAVE_AMPLITUDE * sin( i * M_PI * 0.5f + gpGlobals->curtime * M_PI / SHIELD_EMP_WOBBLE_TIME ); |
|
m_ShieldEffect.GetPoint(i) += dir * factor; |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
// Fade back in, no longer EMPed |
|
if (m_FadeValue < 1.0f) |
|
{ |
|
m_FadeValue += gpGlobals->frametime / SHIELD_EMP_FADE_TIME; |
|
if (m_FadeValue >= 1.0f) |
|
{ |
|
m_FadeValue = 1.0f; |
|
} |
|
} |
|
} |
|
} |
|
|
|
void C_ShieldMobile::AddEntity( ) |
|
{ |
|
BaseClass::AddEntity( ); |
|
PreRender(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Bounds computation |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldMobile::GetBounds( Vector& mins, Vector& maxs ) |
|
{ |
|
m_ShieldEffect.ComputeBounds( mins, maxs ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Return true if the panel is active |
|
//----------------------------------------------------------------------------- |
|
|
|
bool C_ShieldMobile::IsPanelActive( int x, int y ) |
|
{ |
|
return m_ShieldEffect.IsPanelActive(x, y); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Gets at the control point data; who knows how it was made? |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldMobile::GetShieldData( Vector const** ppVerts, float* pOpacity, float* pBlend ) |
|
{ |
|
for ( int i = 0; i < SHIELD_NUM_CONTROL_POINTS; ++i ) |
|
{ |
|
ppVerts[i] = &m_ShieldEffect.GetControlPoint(i); |
|
|
|
if ( m_pVertsActive[i >> 3] & (1 << (i & 0x7)) ) |
|
{ |
|
pOpacity[i] = m_ShieldEffect.ComputeOpacity( *ppVerts[i], GetAbsOrigin() ); |
|
pBlend[i] = 1.0f; |
|
} |
|
else |
|
{ |
|
pOpacity[i] = 192.0f; |
|
pBlend[i] = 0.0f; |
|
} |
|
} |
|
} |
|
|
|
|