Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

359 lines
9.7 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "iefx.h"
#include "dlight.h"
#include "engine/IEngineSound.h"
#include "view.h"
#include "beamdraw.h"
#include "clienteffectprecachesystem.h"
#include "weapon_combat_usedwithshieldbase.h"
#include "c_weapon__stubs.h"
#include <vgui/ISurface.h>
#define BALL_GROW_TIME 1.5
// Precache the effects
CLIENTEFFECT_REGISTER_BEGIN( PrecacheWeaponCombat_ChargeablePlasma )
CLIENTEFFECT_MATERIAL( "sprites/chargeball_team1" )
CLIENTEFFECT_MATERIAL( "sprites/chargeball_team2" )
CLIENTEFFECT_REGISTER_END()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_WeaponCombat_ChargeablePlasma : public C_WeaponCombatUsedWithShieldBase
{
DECLARE_CLASS( C_WeaponCombat_ChargeablePlasma, C_WeaponCombatUsedWithShieldBase );
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
C_WeaponCombat_ChargeablePlasma( void );
~C_WeaponCombat_ChargeablePlasma( void );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
virtual void DrawCrosshair( void );
virtual void ClientThink( );
virtual int DrawModel( int flags );
virtual void ViewModelDrawn( C_BaseViewModel *pBaseViewModel );
virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
virtual bool IsTransparent( );
private:
void StartCharging();
void StopCharging();
void DrawChargingEffect( float flSize, C_BaseAnimating *pAttachedEnt );
private:
bool m_bCharging;
bool m_bLastCharging;
float m_flPower;
float m_flChargeStartTime;
CMaterialReference m_hMaterial;
private:
C_WeaponCombat_ChargeablePlasma( const C_WeaponCombat_ChargeablePlasma & );
};
STUB_WEAPON_CLASS_IMPLEMENT( weapon_combat_chargeableplasma, C_WeaponCombat_ChargeablePlasma );
IMPLEMENT_CLIENTCLASS_DT( C_WeaponCombat_ChargeablePlasma, DT_WeaponCombat_ChargeablePlasma, CWeaponCombat_ChargeablePlasma )
RecvPropInt( RECVINFO(m_bCharging) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_WeaponCombat_ChargeablePlasma::C_WeaponCombat_ChargeablePlasma( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_WeaponCombat_ChargeablePlasma::~C_WeaponCombat_ChargeablePlasma( void )
{
Holster( NULL );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_WeaponCombat_ChargeablePlasma::PreDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PreDataUpdate( updateType );
m_bLastCharging = m_bCharging;
}
void C_WeaponCombat_ChargeablePlasma::NotifyShouldTransmit( ShouldTransmitState_t state )
{
BaseClass::NotifyShouldTransmit(state);
if (state == SHOULDTRANSMIT_START)
{
if (m_bCharging)
StartCharging();
}
else if (state == SHOULDTRANSMIT_END)
{
if (m_bCharging)
StopCharging();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_WeaponCombat_ChargeablePlasma::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
switch( updateType )
{
case DATA_UPDATE_CREATED:
// So we can update our lights
if ( GetTeamNumber() == 1 )
m_hMaterial.Init( "sprites/chargeball_team1" );
else
m_hMaterial.Init( "sprites/chargeball_team2" );
break;
case DATA_UPDATE_DATATABLE_CHANGED:
if ( m_bCharging != m_bLastCharging )
{
if ( m_bCharging )
{
StartCharging();
}
else
{
StopCharging();
}
}
break;
};
if (WeaponState() == WEAPON_IS_ACTIVE)
{
// Start thinking so we can manipulate the light
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
else
{
SetNextClientThink( CLIENT_THINK_NEVER );
}
}
//-----------------------------------------------------------------------------
// Deal with dynamic lighting
//-----------------------------------------------------------------------------
void C_WeaponCombat_ChargeablePlasma::ClientThink( )
{
BaseClass::ClientThink();
C_BaseTFPlayer *pPlayer = (C_BaseTFPlayer *)GetOwner();
if ( !pPlayer || (pPlayer->GetHealth() <= 0))
{
SetNextClientThink( CLIENT_THINK_NEVER );
return;
}
if (!m_bCharging)
return;
// Determine the ball size...
m_flPower = (gpGlobals->curtime - m_flChargeStartTime) / BALL_GROW_TIME;
m_flPower = clamp( m_flPower, 0, 1 );
// FIXME: dl->origin should be based on the attachment point
dlight_t *dl = effects->CL_AllocDlight( entindex() );
dl->origin = GetRenderOrigin();
if (GetTeamNumber() == 1)
{
dl->color.r = 40;
dl->color.g = 60;
dl->color.b = 250;
}
else
{
dl->color.r = 250;
dl->color.g = 60;
dl->color.b = 40;
}
dl->color.exponent = 5;
dl->radius = 20 * m_flPower + 10;
dl->die = gpGlobals->curtime + 0.01;
}
//-----------------------------------------------------------------------------
// Purpose: Remove the ball if we're switching away
//-----------------------------------------------------------------------------
bool C_WeaponCombat_ChargeablePlasma::Holster( C_BaseCombatWeapon *pSwitchingTo )
{
StopCharging();
return BaseClass::Holster( pSwitchingTo );
}
void C_WeaponCombat_ChargeablePlasma::StartCharging()
{
CLocalPlayerFilter filter;
EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "WeaponCombat_ChargeablePlasma.Charging" );
m_flChargeStartTime = gpGlobals->curtime;
}
void C_WeaponCombat_ChargeablePlasma::StopCharging()
{
StopSound( SOUND_FROM_LOCAL_PLAYER, "WeaponCombat_ChargeablePlasma.Charging" );
m_bCharging = false;
}
//-----------------------------------------------------------------------------
// We're transparent because we draw a transparent charging effect
//-----------------------------------------------------------------------------
bool C_WeaponCombat_ChargeablePlasma::IsTransparent( )
{
if (m_bCharging)
return true;
return BaseClass::IsTransparent();
}
//-----------------------------------------------------------------------------
// Purpose: Draws the charging effect
//-----------------------------------------------------------------------------
void C_WeaponCombat_ChargeablePlasma::DrawChargingEffect( float flSize, C_BaseAnimating *pAttachedEnt )
{
if (!pAttachedEnt)
return;
Vector vecOrigin;
QAngle vecAngles;
int iAttachment = pAttachedEnt->LookupAttachment( "muzzle" );
if ( pAttachedEnt->GetAttachment( iAttachment, vecOrigin, vecAngles ) )
{
color32 color = { 255, 255, 255, 255 };
materials->Bind( m_hMaterial, (IClientRenderable*)this );
DrawSprite( vecOrigin, flSize, flSize, color );
}
}
//-----------------------------------------------------------------------------
// Purpose: Draws the model
//-----------------------------------------------------------------------------
int C_WeaponCombat_ChargeablePlasma::DrawModel( int flags )
{
int retval = BaseClass::DrawModel( flags );
if (retval == 0)
return 0;
if (m_bCharging && IsCarrierAlive())
{
// Draw the charging effect
float flSize = 20 * m_flPower + 10;
DrawChargingEffect( flSize, this );
}
return retval;
}
//-----------------------------------------------------------------------------
// Purpose: Draws the model
//-----------------------------------------------------------------------------
void C_WeaponCombat_ChargeablePlasma::ViewModelDrawn( C_BaseViewModel *pBaseViewModel )
{
if (!m_bCharging)
return;
// Draw the charging effect
float flSize = 12 * m_flPower + 6;
if ( m_iClip1 > 0 )
{
DrawChargingEffect( flSize, pBaseViewModel );
}
}
//-----------------------------------------------------------------------------
// Purpose: Draw targeting reticle
//-----------------------------------------------------------------------------
void C_WeaponCombat_ChargeablePlasma::DrawCrosshair( void )
{
BaseClass::DrawCrosshair();
// Find enemy players in front of me
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( !pPlayer )
return;
trace_t tr;
Vector vecStart, vecEnd;
VectorMA( CurrentViewOrigin(), 1500, CurrentViewForward(), vecEnd );
VectorMA( CurrentViewOrigin(), 48, CurrentViewForward(), vecStart );
UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr );
if ( tr.DidHitNonWorldEntity() )
{
C_BaseEntity *pEntity = tr.m_pEnt;
if ( pEntity && pEntity->IsPlayer() && !pPlayer->InSameTeam( pEntity ) )
{
// Draw a reticle
vgui::Color clr = gHUD.m_clrYellowish;
clr[3] = 128;
// Calculate circle size
int iRatio = 30;
// Draw the circle
int iDegrees = 0;
Vector vecPoint, vecLastPoint(0,0,0);
vecPoint.z = 0.0f;
for ( int i = 0; i < 360; i++ )
{
float flRadians = DEG2RAD( iDegrees );
iDegrees += (360 / 360);
float ca = cos( flRadians );
float sa = sin( flRadians );
// Rotate it around the circle
vecPoint.x = (int)((ScreenWidth() / 2) + (iRatio * sa));
vecPoint.y = (int)((ScreenHeight() / 2) - (iRatio * ca));
// Draw the point, if it's not on the previous point, to avoid smaller circles being brighter
if ( vecLastPoint != vecPoint )
{
vgui::surface()->DrawSetColor( clr );
vgui::surface()->DrawFilledRect( vecPoint.x, vecPoint.y, vecPoint.x + 1, vecPoint.y + 1 );
}
vecLastPoint = vecPoint;
}
}
}
}