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.
634 lines
17 KiB
634 lines
17 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: Client's CWeaponMortar class
|
||
|
//
|
||
|
// $Workfile: $
|
||
|
// $Date: $
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
#include "cbase.h"
|
||
|
#include "hud.h"
|
||
|
#include "hudelement.h"
|
||
|
#include "in_buttons.h"
|
||
|
#include "ground_line.h"
|
||
|
#include "clientmode_tfnormal.h"
|
||
|
#include "vgui_basepanel.h"
|
||
|
#include "c_tf_basecombatweapon.h"
|
||
|
#include "engine/IEngineSound.h"
|
||
|
#include "iinput.h"
|
||
|
#include "imessagechars.h"
|
||
|
#include "c_weapon__stubs.h"
|
||
|
|
||
|
//=============================================================================
|
||
|
// Purpose: Hud Element for Mortar firing
|
||
|
//=============================================================================
|
||
|
class CHudMortar : public CHudElement, public vgui::Panel
|
||
|
{
|
||
|
DECLARE_CLASS_SIMPLE( CHudMortar, vgui::Panel );
|
||
|
|
||
|
public:
|
||
|
DECLARE_MULTIPLY_INHERITED();
|
||
|
|
||
|
CHudMortar( const char *pElementName );
|
||
|
virtual void Paint( void );
|
||
|
|
||
|
float m_flPower;
|
||
|
float m_flFiringPower;
|
||
|
float m_flFiringAccuracy;
|
||
|
float m_flReset;
|
||
|
};
|
||
|
|
||
|
DECLARE_HUDELEMENT( CHudMortar );
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CHudMortar::CHudMortar( const char *pElementName ) :
|
||
|
CHudElement( pElementName ), vgui::Panel( NULL, pElementName )
|
||
|
{
|
||
|
m_flPower = 0;
|
||
|
m_flFiringPower = 0;
|
||
|
m_flFiringAccuracy = 0;
|
||
|
m_flReset = 0;
|
||
|
SetPaintBackgroundEnabled( false );
|
||
|
SetAutoDelete( false );
|
||
|
SetName( "mortar" );
|
||
|
|
||
|
SetHiddenBits( HIDEHUD_PLAYERDEAD );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CHudMortar::Paint()
|
||
|
{
|
||
|
// Clear out markers
|
||
|
if ( m_flReset && m_flReset < gpGlobals->curtime )
|
||
|
{
|
||
|
m_flFiringPower = 0;
|
||
|
m_flFiringAccuracy = 0;
|
||
|
m_flReset = 0;
|
||
|
}
|
||
|
|
||
|
int w, h;
|
||
|
GetSize( w, h );
|
||
|
|
||
|
// Use an eighth of the height for each side
|
||
|
int iOffset = h / 8;
|
||
|
int iBarHeight = h - (2 * iOffset);
|
||
|
int iZero = (w / 5);
|
||
|
int iMarker = iZero + (m_flPower * (w - iZero));
|
||
|
int iPower = iZero + (m_flFiringPower * (w - iZero));
|
||
|
int iAccuracy = iZero + (m_flFiringAccuracy * (w - iZero));
|
||
|
|
||
|
// Shade the bar
|
||
|
int alpha = 205;
|
||
|
int colorAmt = 255;
|
||
|
int nSegs = 20;
|
||
|
|
||
|
int i;
|
||
|
for(i=0; i < nSegs; i++)
|
||
|
{
|
||
|
int left = iZero + (i*w) / nSegs;
|
||
|
int right = iZero + ((i+1)*w) / nSegs;
|
||
|
|
||
|
// Don't draw past the marker
|
||
|
if ( m_flFiringPower && right > iPower )
|
||
|
right = iPower;
|
||
|
else if ( !m_flFiringPower && right > iMarker )
|
||
|
right = iMarker;
|
||
|
|
||
|
vgui::surface()->DrawSetColor( ((i + 5) * colorAmt) / nSegs, 0, 0, alpha );
|
||
|
vgui::surface()->DrawFilledRect( left, iOffset, right, iBarHeight);
|
||
|
}
|
||
|
|
||
|
// Shade back from zero
|
||
|
nSegs = 10;
|
||
|
for(i=0; i < nSegs; i++)
|
||
|
{
|
||
|
int left = (i*iZero) / nSegs;
|
||
|
int right = ((i+1)*iZero) / nSegs;
|
||
|
|
||
|
if ( m_flFiringAccuracy && left < iAccuracy )
|
||
|
left = iAccuracy;
|
||
|
else if ( !m_flFiringAccuracy && left < iMarker )
|
||
|
left = iMarker;
|
||
|
|
||
|
vgui::surface()->DrawSetColor( ((nSegs - i) * colorAmt) / nSegs, 0, 0, alpha );
|
||
|
vgui::surface()->DrawFilledRect(left, iOffset, right, iBarHeight);
|
||
|
}
|
||
|
|
||
|
// Draw the zero marker
|
||
|
vgui::surface()->DrawSetColor(255,255,255,255);
|
||
|
vgui::surface()->DrawFilledRect(iZero-2, iOffset, iZero+2, iBarHeight);
|
||
|
|
||
|
// Draw the marker
|
||
|
vgui::surface()->DrawSetColor(255,255,255,255);
|
||
|
vgui::surface()->DrawFilledRect(iMarker-1, 0, iMarker+1, h);
|
||
|
|
||
|
// Draw the power mark if we've set one
|
||
|
if ( m_flFiringPower )
|
||
|
{
|
||
|
vgui::surface()->DrawSetColor(255,255,255,255);
|
||
|
vgui::surface()->DrawFilledRect(iPower-1, iOffset, iPower+1, iBarHeight);
|
||
|
}
|
||
|
|
||
|
// Draw the accuracy mark if we've set one
|
||
|
if ( m_flFiringAccuracy )
|
||
|
{
|
||
|
vgui::surface()->DrawSetColor(255,255,255,255);
|
||
|
vgui::surface()->DrawFilledRect(iAccuracy-1, iOffset, iAccuracy+1, iBarHeight);
|
||
|
}
|
||
|
|
||
|
// Draw box
|
||
|
vgui::surface()->DrawSetColor(255,255,255,255);
|
||
|
vgui::surface()->DrawOutlinedRect(0, iOffset, w, iBarHeight);
|
||
|
}
|
||
|
|
||
|
static ConVar g_CVMortarGroundLineUpdateInterval( "mortar_groundlineupdateinterval", "0.1", 0, "Number of seconds, mininum, between ground line position updates." );
|
||
|
|
||
|
|
||
|
//=============================================================================
|
||
|
// Purpose: Client version of CWeaponMortar
|
||
|
//=============================================================================
|
||
|
class C_WeaponMortar : public C_BaseTFCombatWeapon
|
||
|
{
|
||
|
public:
|
||
|
DECLARE_CLASS( C_WeaponMortar, C_BaseTFCombatWeapon );
|
||
|
DECLARE_CLIENTCLASS();
|
||
|
DECLARE_PREDICTABLE();
|
||
|
|
||
|
C_WeaponMortar();
|
||
|
~C_WeaponMortar();
|
||
|
|
||
|
void FireMortar( void );
|
||
|
|
||
|
virtual void PreDataUpdate( DataUpdateType_t updateType );
|
||
|
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||
|
virtual void HandleInput( void );
|
||
|
virtual void Redraw();
|
||
|
virtual void OverrideMouseInput( float *x, float *y );
|
||
|
|
||
|
// Deploy / Holster
|
||
|
virtual bool Deploy( void );
|
||
|
virtual bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
|
||
|
|
||
|
// Mortar Data
|
||
|
bool m_bCarried;
|
||
|
bool m_bMortarReloading;
|
||
|
Vector m_vecMortarOrigin;
|
||
|
Vector m_vecMortarAngles;
|
||
|
float m_flPrevMortarServerYaw;
|
||
|
float m_flMortarYaw;
|
||
|
float m_flPrevMortarYaw;
|
||
|
|
||
|
// Input Handling
|
||
|
float m_flNextClick;
|
||
|
float m_flAccuracySpeed;
|
||
|
int m_iFiringState;
|
||
|
bool m_bRotating;
|
||
|
|
||
|
CGroundLine *m_pGroundLine;
|
||
|
CGroundLine *m_pDarkLine;
|
||
|
CHudMortar *m_pPowerBar;
|
||
|
IMaterial *m_pRotateIcon;
|
||
|
|
||
|
vgui::HFont m_hFontText;
|
||
|
|
||
|
private:
|
||
|
C_WeaponMortar( const C_WeaponMortar & );
|
||
|
|
||
|
float m_flLastGroundlineUpdateTime;
|
||
|
|
||
|
};
|
||
|
|
||
|
STUB_WEAPON_CLASS_IMPLEMENT( weapon_mortar, C_WeaponMortar );
|
||
|
|
||
|
IMPLEMENT_CLIENTCLASS_DT(C_WeaponMortar, DT_WeaponMortar, CWeaponMortar)
|
||
|
RecvPropInt( RECVINFO(m_bCarried) ),
|
||
|
RecvPropInt( RECVINFO(m_bMortarReloading) ),
|
||
|
RecvPropVector( RECVINFO(m_vecMortarOrigin) ),
|
||
|
RecvPropVector( RECVINFO(m_vecMortarAngles) ),
|
||
|
END_RECV_TABLE()
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
C_WeaponMortar::C_WeaponMortar()
|
||
|
{
|
||
|
m_bCarried = true;
|
||
|
m_bMortarReloading = false;
|
||
|
m_iFiringState = MORTAR_IDLE;
|
||
|
m_flNextClick = 0;
|
||
|
m_flAccuracySpeed = 0;
|
||
|
m_bRotating = false;
|
||
|
m_pGroundLine = NULL;
|
||
|
m_pDarkLine = NULL;
|
||
|
m_flMortarYaw = 0;
|
||
|
m_flPrevMortarYaw = -1;
|
||
|
|
||
|
m_pRotateIcon = materials->FindMaterial( "Hud/mortar/mortar_rotate", TEXTURE_GROUP_VGUI );
|
||
|
m_pRotateIcon->IncrementReferenceCount();
|
||
|
|
||
|
m_pPowerBar = GET_HUDELEMENT( CHudMortar );
|
||
|
|
||
|
m_flLastGroundlineUpdateTime = 0.0f;
|
||
|
|
||
|
m_hFontText = g_hFontTrebuchet24;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
C_WeaponMortar::~C_WeaponMortar()
|
||
|
{
|
||
|
m_pPowerBar->SetParent( (vgui::Panel *)NULL );
|
||
|
|
||
|
if ( m_pRotateIcon != NULL )
|
||
|
{
|
||
|
m_pRotateIcon->DecrementReferenceCount();
|
||
|
m_pRotateIcon = NULL;
|
||
|
}
|
||
|
|
||
|
if ( m_pGroundLine )
|
||
|
{
|
||
|
delete m_pGroundLine;
|
||
|
}
|
||
|
if ( m_pDarkLine )
|
||
|
{
|
||
|
delete m_pDarkLine;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_WeaponMortar::PreDataUpdate( DataUpdateType_t updateType )
|
||
|
{
|
||
|
BaseClass::PreDataUpdate(updateType);
|
||
|
|
||
|
m_flPrevMortarServerYaw = m_vecMortarAngles.y;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_WeaponMortar::OnDataChanged( DataUpdateType_t updateType )
|
||
|
{
|
||
|
BaseClass::OnDataChanged(updateType);
|
||
|
|
||
|
// If the mortar's being carried by some other player, don't make a ground line
|
||
|
if ( !IsCarriedByLocalPlayer() )
|
||
|
return;
|
||
|
|
||
|
// Draw power chart if the mortar is deployed
|
||
|
if ( !m_bCarried && !m_bMortarReloading )
|
||
|
{
|
||
|
vgui::Panel *pParent = GetClientModeNormal()->GetViewport();
|
||
|
int parentWidth, parentHeight;
|
||
|
pParent->GetSize(parentWidth, parentHeight);
|
||
|
|
||
|
int iWidth = 256;
|
||
|
int iHeight = 40;
|
||
|
int iX = (parentWidth - iWidth) / 2;
|
||
|
int iY = (parentHeight - 200);
|
||
|
|
||
|
// Only show the power bar if the mortar's the active weapon
|
||
|
if ( IsActiveByLocalPlayer() )
|
||
|
{
|
||
|
m_pPowerBar->SetBounds( iX, iY, iWidth, iHeight );
|
||
|
m_pPowerBar->SetParent(pParent);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pPowerBar->SetParent( (vgui::Panel *)NULL );
|
||
|
}
|
||
|
|
||
|
if ( !m_bRotating && m_flPrevMortarServerYaw != m_vecMortarAngles.y )
|
||
|
{
|
||
|
m_flMortarYaw = m_vecMortarAngles.y;
|
||
|
}
|
||
|
|
||
|
// Create the Ground lines
|
||
|
if ( !m_pGroundLine )
|
||
|
{
|
||
|
m_pGroundLine = new CGroundLine();
|
||
|
m_pGroundLine->Init( "player/support/mortarline" );
|
||
|
}
|
||
|
if ( !m_pDarkLine )
|
||
|
{
|
||
|
m_pDarkLine = new CGroundLine();
|
||
|
m_pDarkLine->Init( "player/support/mortarline" );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pPowerBar->SetParent( (vgui::Panel *)NULL );
|
||
|
|
||
|
if ( m_pGroundLine )
|
||
|
{
|
||
|
delete m_pGroundLine;
|
||
|
m_pGroundLine = NULL;
|
||
|
}
|
||
|
if ( m_pDarkLine )
|
||
|
{
|
||
|
delete m_pDarkLine;
|
||
|
m_pDarkLine = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_WeaponMortar::HandleInput( void )
|
||
|
{
|
||
|
// If it's being carried, ignore input
|
||
|
if ( m_bCarried )
|
||
|
return;
|
||
|
// If the player's dead, ignore input
|
||
|
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer();
|
||
|
if ( pPlayer == NULL )
|
||
|
return;
|
||
|
if ( pPlayer->GetHealth() < 1 )
|
||
|
return;
|
||
|
|
||
|
// Ignore input if it's reloading
|
||
|
if ( m_bMortarReloading )
|
||
|
return;
|
||
|
|
||
|
// Secondary fire rotates the mortar
|
||
|
if ( gHUD.m_iKeyBits & IN_ATTACK2 )
|
||
|
{
|
||
|
if ( pPlayer->HasPowerup(POWERUP_EMP) )
|
||
|
{
|
||
|
CLocalPlayerFilter filter;
|
||
|
EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "WeaponMortar.EMPed" );
|
||
|
return;
|
||
|
}
|
||
|
m_bRotating = true;
|
||
|
|
||
|
gHUD.m_iKeyBits &= ~IN_ATTACK2;
|
||
|
|
||
|
// Prevent firing while rotating
|
||
|
m_pPowerBar->SetParent( (vgui::Panel *)NULL );
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( m_bRotating )
|
||
|
{
|
||
|
// Bring up the firing bar again
|
||
|
vgui::Panel *pParent = GetClientModeNormal()->GetViewport();
|
||
|
m_pPowerBar->SetParent(pParent);
|
||
|
m_bRotating = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Primary fire launches mortars
|
||
|
if (gHUD.m_iKeyBits & IN_ATTACK)
|
||
|
{
|
||
|
if ( pPlayer->HasPowerup(POWERUP_EMP) )
|
||
|
{
|
||
|
CLocalPlayerFilter filter;
|
||
|
EmitSound( filter, SOUND_FROM_LOCAL_PLAYER, "WeaponMortar.EMPed" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( m_flNextClick <= gpGlobals->curtime )
|
||
|
{
|
||
|
// Play click animation
|
||
|
// SendWeaponAnim( ACT_SLAM_DETONATOR_DETONATE );
|
||
|
|
||
|
// Switch states
|
||
|
switch( m_iFiringState )
|
||
|
{
|
||
|
case MORTAR_IDLE:
|
||
|
m_iFiringState = MORTAR_CHARGING_POWER;
|
||
|
break;
|
||
|
case MORTAR_CHARGING_POWER:
|
||
|
m_pPowerBar->m_flFiringPower = m_pPowerBar->m_flPower;
|
||
|
m_iFiringState = MORTAR_CHARGING_ACCURACY;
|
||
|
break;
|
||
|
case MORTAR_CHARGING_ACCURACY:
|
||
|
m_pPowerBar->m_flFiringAccuracy = m_pPowerBar->m_flPower;
|
||
|
m_iFiringState = MORTAR_IDLE;
|
||
|
|
||
|
FireMortar();
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
input->ClearInputButton( IN_ATTACK );
|
||
|
gHUD.m_iKeyBits &= ~IN_ATTACK;
|
||
|
|
||
|
m_flNextClick = gpGlobals->curtime + 0.05;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_WeaponMortar::Redraw()
|
||
|
{
|
||
|
BaseClass::Redraw();
|
||
|
|
||
|
// If the player's dead, abort
|
||
|
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer();
|
||
|
if ( pPlayer == NULL )
|
||
|
return;
|
||
|
if ( pPlayer->GetHealth() < 1 )
|
||
|
{
|
||
|
m_iFiringState = MORTAR_IDLE;
|
||
|
m_bCarried = true;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// If it's reloading, tell the player
|
||
|
if ( m_bMortarReloading )
|
||
|
{
|
||
|
int width, height;
|
||
|
messagechars->GetStringLength( m_hFontText, &width, &height, "Mortar is reloading..." );
|
||
|
messagechars->DrawString( m_hFontText, (ScreenWidth() - width) / 2, YRES(350), 192, 192, 192, 255, "Mortar is reloading...", IMessageChars::MESSAGESTRINGID_NONE );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Handle power charging
|
||
|
switch( m_iFiringState )
|
||
|
{
|
||
|
case MORTAR_IDLE:
|
||
|
m_pPowerBar->m_flPower = 0;
|
||
|
break;
|
||
|
case MORTAR_CHARGING_POWER:
|
||
|
m_pPowerBar->m_flPower = MIN( m_pPowerBar->m_flPower + ( (1.0 / MORTAR_CHARGE_POWER_RATE) * gpGlobals->curtimeDelta), 1.0f);
|
||
|
m_pPowerBar->m_flFiringPower = 0;
|
||
|
m_pPowerBar->m_flFiringAccuracy = 0;
|
||
|
if ( m_pPowerBar->m_flPower >= 1.0 )
|
||
|
{
|
||
|
// Hit Max, start going down
|
||
|
m_pPowerBar->m_flFiringPower = m_pPowerBar->m_flPower;
|
||
|
m_iFiringState = MORTAR_CHARGING_ACCURACY;
|
||
|
m_flNextClick = gpGlobals->curtime + 0.25;
|
||
|
}
|
||
|
break;
|
||
|
case MORTAR_CHARGING_ACCURACY:
|
||
|
// Calculate accuracy speed
|
||
|
m_flAccuracySpeed = (1.0 / MORTAR_CHARGE_ACCURACY_RATE);
|
||
|
if ( m_pPowerBar->m_flFiringPower > 0.5 )
|
||
|
{
|
||
|
// Shots over halfway suffer an increased speed to the accuracy power, making accurate shots harder
|
||
|
float flAdjustedPower = (m_pPowerBar->m_flFiringPower - 0.5) * 3.0;
|
||
|
m_flAccuracySpeed += (m_pPowerBar->m_flFiringPower * flAdjustedPower);
|
||
|
}
|
||
|
|
||
|
m_pPowerBar->m_flPower = MAX( m_pPowerBar->m_flPower - ( m_flAccuracySpeed * gpGlobals->curtimeDelta), -0.25f);
|
||
|
if ( m_pPowerBar->m_flPower <= -0.25 )
|
||
|
{
|
||
|
// Hit Min, fire mortar
|
||
|
m_pPowerBar->m_flFiringAccuracy = m_pPowerBar->m_flPower;
|
||
|
m_iFiringState = MORTAR_IDLE;
|
||
|
|
||
|
FireMortar();
|
||
|
m_flNextClick = gpGlobals->curtime + 0.25;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Draw the rotate icon if the player's rotating the mortar
|
||
|
if ( m_bRotating )
|
||
|
{
|
||
|
vgui::Panel *pParent = GetClientModeNormal()->GetViewport();
|
||
|
int parentWidth, parentHeight;
|
||
|
pParent->GetSize(parentWidth, parentHeight);
|
||
|
int iWidth = 64;
|
||
|
int iHeight = 64;
|
||
|
int iX = (parentWidth - iWidth) / 2;
|
||
|
int iY = (parentHeight - 216);
|
||
|
|
||
|
IMesh* pMesh = materials->GetDynamicMesh( true, NULL, NULL, m_pRotateIcon );
|
||
|
|
||
|
CMeshBuilder meshBuilder;
|
||
|
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
|
||
|
|
||
|
meshBuilder.Color3f( 1.0, 1.0, 1.0 );
|
||
|
meshBuilder.TexCoord2f( 0,0,0 );
|
||
|
meshBuilder.Position3f( iX,iY,0 );
|
||
|
meshBuilder.AdvanceVertex();
|
||
|
|
||
|
meshBuilder.Color3f( 1.0, 1.0, 1.0 );
|
||
|
meshBuilder.TexCoord2f( 0,1,0 );
|
||
|
meshBuilder.Position3f( iX+iWidth, iY, 0 );
|
||
|
meshBuilder.AdvanceVertex();
|
||
|
|
||
|
meshBuilder.Color3f( 1.0, 1.0, 1.0 );
|
||
|
meshBuilder.TexCoord2f( 0,1,1 );
|
||
|
meshBuilder.Position3f( iX+iWidth, iY+iHeight, 0 );
|
||
|
meshBuilder.AdvanceVertex();
|
||
|
|
||
|
meshBuilder.Color3f( 1.0, 1.0, 1.0 );
|
||
|
meshBuilder.TexCoord2f( 0,0,1 );
|
||
|
meshBuilder.Position3f( iX, iY+iHeight, 0 );
|
||
|
meshBuilder.AdvanceVertex();
|
||
|
|
||
|
meshBuilder.End();
|
||
|
pMesh->Draw();
|
||
|
}
|
||
|
|
||
|
// Update the ground line if it's moved
|
||
|
if ( !m_bCarried && (m_flPrevMortarYaw != m_flMortarYaw ) &&
|
||
|
gpGlobals->curtime > m_flLastGroundlineUpdateTime + g_CVMortarGroundLineUpdateInterval.GetFloat() )
|
||
|
{
|
||
|
// Create the Ground line start & end points
|
||
|
Vector vecForward;
|
||
|
AngleVectors( QAngle( 0, m_flMortarYaw, 0 ), &vecForward );
|
||
|
Vector vecStart = m_vecMortarOrigin + (vecForward * MORTAR_RANGE_MIN);
|
||
|
|
||
|
float flRange = MORTAR_RANGE_MAX_INITIAL;
|
||
|
if ( pPlayer->HasNamedTechnology( "mortar_range" ) )
|
||
|
flRange = MORTAR_RANGE_MAX_UPGRADED;
|
||
|
Vector vecEnd = m_vecMortarOrigin + (vecForward * flRange);
|
||
|
|
||
|
m_pDarkLine->SetParameters( m_vecMortarOrigin, vecStart, Vector( 0.1,0.1,0.1 ), Vector( 0.1,0.1,0.1 ), 0.5, 22 );
|
||
|
m_pGroundLine->SetParameters( vecStart, vecEnd, Vector(0,1,0), Vector(1,0,0), 0.5, 22 );
|
||
|
|
||
|
m_flPrevMortarYaw = m_flMortarYaw;
|
||
|
|
||
|
m_flLastGroundlineUpdateTime = gpGlobals->curtime;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Capture mouse input for mortar rotation
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_WeaponMortar::OverrideMouseInput( float *x, float *y )
|
||
|
{
|
||
|
if ( !m_bRotating )
|
||
|
return;
|
||
|
|
||
|
float flX = ( *x ) * 0.05f;
|
||
|
|
||
|
m_flMortarYaw = anglemod(m_flMortarYaw - flX);
|
||
|
|
||
|
*x = 0.0f;
|
||
|
*y = 0.0f;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Weapon's been deployed
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool C_WeaponMortar::Deploy( void )
|
||
|
{
|
||
|
if ( m_pDarkLine )
|
||
|
{
|
||
|
m_pDarkLine->SetVisible( true );
|
||
|
}
|
||
|
if ( m_pGroundLine )
|
||
|
{
|
||
|
m_pGroundLine->SetVisible( true );
|
||
|
}
|
||
|
|
||
|
return BaseClass::Deploy();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Weapon's been holstered
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool C_WeaponMortar::Holster( C_BaseCombatWeapon *pSwitchingTo )
|
||
|
{
|
||
|
if ( m_pDarkLine )
|
||
|
{
|
||
|
m_pDarkLine->SetVisible( false );
|
||
|
}
|
||
|
if ( m_pGroundLine )
|
||
|
{
|
||
|
m_pGroundLine->SetVisible( false );
|
||
|
}
|
||
|
|
||
|
return BaseClass::Holster( pSwitchingTo );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_WeaponMortar::FireMortar( void )
|
||
|
{
|
||
|
// Clamp inaccuracy
|
||
|
float flTempAcc = m_pPowerBar->m_flFiringAccuracy;
|
||
|
if ( flTempAcc > 0.25 )
|
||
|
flTempAcc = 0.25;
|
||
|
else if ( flTempAcc < -0.25 )
|
||
|
flTempAcc = -0.25;
|
||
|
|
||
|
// HACKHACK: This is an amazingly bad way to do it. Replace this when the
|
||
|
// client DLL can insert commands into the usercmds
|
||
|
char szbuf[48];
|
||
|
Q_snprintf( szbuf, sizeof( szbuf ), "mortar %0.2f %0.2f %0.2f\n", m_pPowerBar->m_flFiringPower, flTempAcc, m_flMortarYaw );
|
||
|
engine->ClientCmd(szbuf);
|
||
|
|
||
|
// Tell the power bar to reset soon
|
||
|
m_pPowerBar->m_flReset = gpGlobals->curtime + 1.0;
|
||
|
}
|