diff options
Diffstat (limited to 'game/client/tf2/c_weapon_chargeableplasma.cpp')
| -rw-r--r-- | game/client/tf2/c_weapon_chargeableplasma.cpp | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/game/client/tf2/c_weapon_chargeableplasma.cpp b/game/client/tf2/c_weapon_chargeableplasma.cpp new file mode 100644 index 0000000..22e2471 --- /dev/null +++ b/game/client/tf2/c_weapon_chargeableplasma.cpp @@ -0,0 +1,358 @@ +//========= 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; + } + } + } +} + |