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.
350 lines
8.4 KiB
350 lines
8.4 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Client's sheild entity |
|
// |
|
// $Workfile: $ |
|
// $Date: $ |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include "cbase.h" |
|
#include "C_Shield.h" |
|
#include "tf_shieldshared.h" |
|
#include "c_basetfplayer.h" |
|
|
|
enum |
|
{ |
|
NUM_SUBDIVISIONS = 21, |
|
}; |
|
|
|
#define EMP_WAVE_AMPLITUDE 6.0f |
|
#define EMP_GROW_WIDTH_DELAY 0.2f |
|
#define EMP_GROW_TIME 0.6f |
|
#define EMP_GROW_ATTEN 0.5f |
|
#define EMP_MIN_WIDTH 5.0f |
|
|
|
//----------------------------------------------------------------------------- |
|
// Flat version of the shield |
|
//----------------------------------------------------------------------------- |
|
|
|
class C_ShieldFlat : public C_Shield |
|
{ |
|
public: |
|
DECLARE_CLASS( C_ShieldFlat, C_Shield ); |
|
DECLARE_CLIENTCLASS(); |
|
|
|
C_ShieldFlat(); |
|
~C_ShieldFlat(); |
|
|
|
virtual void GetBounds( Vector& mins, Vector& maxs ); |
|
|
|
virtual void AddEntity( ); |
|
|
|
virtual void SetDormant( bool bDormant ); |
|
|
|
// 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 ); |
|
|
|
// Draws the model |
|
virtual int DrawModel( int flags ); |
|
|
|
public: |
|
// networked data |
|
unsigned char m_ShieldState; |
|
float m_Width; |
|
float m_Height; |
|
|
|
float m_DeathFade; |
|
float m_EMPFade; |
|
|
|
private: |
|
void ShieldMoved( void ); |
|
|
|
private: |
|
C_ShieldFlat( const C_ShieldFlat& ); |
|
void ComputeEMPFade(); |
|
void ComputeDeathFade(); |
|
void ComputeSize( float& w, float& h ); |
|
void PreRender( ); |
|
|
|
Vector m_pPositions[4]; |
|
Vector m_Forward; |
|
float m_EnterPVSTime; |
|
|
|
QAngle m_LastAngles; |
|
Vector m_LastPosition; |
|
Vector m_Pos[4]; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Data table |
|
//----------------------------------------------------------------------------- |
|
|
|
IMPLEMENT_CLIENTCLASS_DT(C_ShieldFlat, DT_Shield_Flat, CShieldFlat) |
|
|
|
RecvPropInt( RECVINFO(m_ShieldState) ), |
|
RecvPropFloat( RECVINFO(m_Width) ), |
|
RecvPropFloat( RECVINFO(m_Height) ), |
|
|
|
END_RECV_TABLE() |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Constructor, destructor |
|
//----------------------------------------------------------------------------- |
|
|
|
C_ShieldFlat::C_ShieldFlat() |
|
{ |
|
m_DeathFade = 1.0f; |
|
m_EMPFade = 1.0f; |
|
|
|
InitShield( 2, 2, 6 ); |
|
} |
|
|
|
C_ShieldFlat::~C_ShieldFlat() |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Leaving/entering the PVS on the server. |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldFlat::SetDormant( bool bDormant ) |
|
{ |
|
if (!bDormant) |
|
{ |
|
if (m_ShieldState & SHIELD_FLAT_EMP) |
|
{ |
|
m_EMPFade = 0.0f; |
|
} |
|
else |
|
{ |
|
m_EMPFade = 1.0f; |
|
} |
|
|
|
m_EnterPVSTime = 0.0f; |
|
if (m_ShieldState & SHIELD_FLAT_INACTIVE) |
|
{ |
|
m_DeathFade = 0.0f; |
|
} |
|
else |
|
{ |
|
m_EnterPVSTime = gpGlobals->curtime; |
|
m_DeathFade = 1.0f; |
|
} |
|
} |
|
|
|
BaseClass::SetDormant(bDormant); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Figures the EMP fade factor |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldFlat::ComputeEMPFade() |
|
{ |
|
if (m_ShieldState & SHIELD_FLAT_EMP) |
|
{ |
|
// Decay fade if we've been EMPed or if we're inactive |
|
if (m_EMPFade > 0.0f) |
|
{ |
|
m_EMPFade -= gpGlobals->frametime / SHIELD_EMP_FADE_TIME; |
|
if (m_EMPFade < 0.0f) |
|
{ |
|
m_EMPFade = 0.0f; |
|
} |
|
else |
|
{ |
|
Vector dir; |
|
|
|
// Futz with the control points if we've been EMPed |
|
for (int i = 0; i < 4; ++i) |
|
{ |
|
float dist = -EMP_WAVE_AMPLITUDE * sin( i * M_PI * 0.5f + gpGlobals->curtime * M_PI / SHIELD_EMP_WOBBLE_TIME ); |
|
VectorMA( m_pPositions[i], dist, m_Forward, m_pPositions[i] ); |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
// Fade back in, no longer EMPed |
|
if (m_EMPFade < 1.0f) |
|
{ |
|
m_EMPFade += gpGlobals->frametime / SHIELD_EMP_FADE_TIME; |
|
if (m_EMPFade >= 1.0f) |
|
{ |
|
m_EMPFade = 1.0f; |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Figures the networked fade factor |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldFlat::ComputeDeathFade() |
|
{ |
|
if (m_ShieldState & SHIELD_FLAT_INACTIVE) |
|
{ |
|
// Fade out when we become inactive |
|
if (m_DeathFade > 0.0f) |
|
{ |
|
m_DeathFade -= gpGlobals->frametime / SHIELD_FLAT_SHUTDOWN_TIME; |
|
if (m_DeathFade < 0.0f) |
|
{ |
|
m_DeathFade = 0.0f; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
// Active? We should be visible |
|
m_DeathFade = 1.0f; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// A little pre-render processing |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldFlat::ComputeSize( float& w, float& h ) |
|
{ |
|
w = m_Width; |
|
h = m_Height; |
|
|
|
float dt = gpGlobals->curtime - m_EnterPVSTime; |
|
if (dt > EMP_GROW_TIME) |
|
{ |
|
return; |
|
} |
|
|
|
if (dt < 0) |
|
dt = 0.0f; |
|
|
|
// Attenuate it up |
|
w *= 1.0f - pow ( EMP_GROW_ATTEN, 10 * (dt / EMP_GROW_TIME )); |
|
|
|
if (w < EMP_MIN_WIDTH) |
|
w = EMP_MIN_WIDTH; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// A little pre-render processing |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldFlat::PreRender( ) |
|
{ |
|
// Compute the shield positions... |
|
Vector right, up; |
|
AngleVectors( GetRenderAngles(), &m_Forward, &right, &up ); |
|
|
|
float w, h; |
|
ComputeSize( w, h ); |
|
|
|
VectorMA( GetRenderOrigin(), -w * 0.5, right, m_pPositions[0] ); |
|
VectorMA( m_pPositions[0], -h * 0.5, up, m_pPositions[0] ); |
|
VectorMA( m_pPositions[0], w, right, m_pPositions[1] ); |
|
VectorMA( m_pPositions[0], h, up, m_pPositions[2] ); |
|
VectorMA( m_pPositions[2], w, right, m_pPositions[3] ); |
|
|
|
ComputeEMPFade(); |
|
ComputeDeathFade(); |
|
|
|
m_FadeValue = m_DeathFade * m_EMPFade; |
|
} |
|
|
|
void C_ShieldFlat::AddEntity( ) |
|
{ |
|
BaseClass::AddEntity( ); |
|
PreRender(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Bounds computation |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldFlat::GetBounds( Vector& mins, Vector& maxs ) |
|
{ |
|
mins.Init( -1.0/16.0f, -m_Width * 0.5f, -m_Height * 0.5f ); |
|
maxs.Init( 1.0/16.0f, m_Width * 0.5f, m_Height * 0.5f ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Return true if the panel is active |
|
//----------------------------------------------------------------------------- |
|
|
|
bool C_ShieldFlat::IsPanelActive( int x, int y ) |
|
{ |
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Gets at the control point data; who knows how it was made? |
|
//----------------------------------------------------------------------------- |
|
|
|
void C_ShieldFlat::GetShieldData( Vector const** ppVerts, float* pOpacity, float* pBlend ) |
|
{ |
|
for ( int i = 0; i < 4; ++i ) |
|
{ |
|
ppVerts[i] = &m_pPositions[i]; |
|
pOpacity[i] = 32.0f; |
|
pBlend[i] = 0.0f; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Shield points |
|
//----------------------------------------------------------------------------- |
|
const Vector& C_ShieldFlat::GetPoint( int x, int y ) |
|
{ |
|
if ((m_LastAngles != GetAbsAngles()) || (m_LastPosition != GetAbsOrigin() )) |
|
{ |
|
ShieldMoved(); |
|
} |
|
|
|
int i = (x >= 1); |
|
i += (y >= 1) * 2; |
|
return m_Pos[i]; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Computes the shield bounding box |
|
//----------------------------------------------------------------------------- |
|
void C_ShieldFlat::ShieldMoved( void ) |
|
{ |
|
Vector forward, right, up; |
|
AngleVectors( GetAbsAngles(), &forward, &right, &up ); |
|
|
|
VectorMA( GetAbsOrigin(), -m_Width * 0.5, right, m_Pos[0] ); |
|
VectorMA( m_Pos[0], -m_Height * 0.5, up, m_Pos[0] ); |
|
VectorMA( m_Pos[0], m_Width, right, m_Pos[1] ); |
|
VectorMA( m_Pos[0], m_Height, up, m_Pos[2] ); |
|
VectorMA( m_Pos[2], m_Width, right, m_Pos[3] ); |
|
|
|
m_LastAngles = GetAbsAngles(); |
|
m_LastPosition = GetAbsOrigin(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Suppress rendering if the player owns it |
|
//----------------------------------------------------------------------------- |
|
|
|
int C_ShieldFlat::DrawModel( int flags ) |
|
{ |
|
if ( !m_bReadyToDraw ) |
|
return 0; |
|
|
|
// Don't draw it if the owner is the local player |
|
// if ( m_OwnerEntity == C_BasePlayer::GetLocalPlayer()->index ) |
|
// return 0; |
|
|
|
return BaseClass::DrawModel( flags ); |
|
} |
|
|
|
|