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.
390 lines
12 KiB
390 lines
12 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: Client version of CObjectMortar
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
#include "cbase.h"
|
||
|
#include "hud.h"
|
||
|
#include "CommanderOverlay.h"
|
||
|
#include "c_baseobject.h"
|
||
|
#include "tf_shareddefs.h"
|
||
|
#include "c_basetfplayer.h"
|
||
|
#include "ObjectControlPanel.h"
|
||
|
#include <vgui_controls/Label.h>
|
||
|
#include <vgui_controls/Button.h>
|
||
|
#include "vgui_rotation_slider.h"
|
||
|
#include <vgui/ISurface.h>
|
||
|
#include "vgui_basepanel.h"
|
||
|
#include "vgui_bitmapimage.h"
|
||
|
#include "iusesmortarpanel.h"
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class C_ObjectMortar : public C_BaseObject, public IUsesMortarPanel
|
||
|
{
|
||
|
DECLARE_CLASS( C_ObjectMortar, C_BaseObject );
|
||
|
public:
|
||
|
DECLARE_CLIENTCLASS();
|
||
|
DECLARE_ENTITY_PANEL();
|
||
|
|
||
|
C_ObjectMortar();
|
||
|
|
||
|
virtual void SetDormant( bool bDormant );
|
||
|
virtual void Select( void );
|
||
|
virtual void RecalculateIDString( void );
|
||
|
|
||
|
void FireMortar( void );
|
||
|
|
||
|
// IUsesMortarPanel
|
||
|
public:
|
||
|
// Get the data from this mortar needed by the panel
|
||
|
virtual void GetMortarData( float *flClientMortarYaw, bool *bAllowedToFire, float *flPower, float *flFiringPower, float *flFiringAccuracy, int *iFiringState );
|
||
|
virtual void SendYawCommand( void );
|
||
|
virtual void ForceClientYawCountdown( float flTime );
|
||
|
virtual void ClickFire( void );
|
||
|
|
||
|
public:
|
||
|
int m_iRoundType;
|
||
|
int m_iMortarRounds[ MA_LASTAMMOTYPE ];
|
||
|
|
||
|
// Mortar firing info.
|
||
|
int m_iFiringState; // One of the MORTAR_ defines.
|
||
|
bool m_bMortarReloading;
|
||
|
float m_flPower;
|
||
|
bool m_bAllowedToFire;
|
||
|
|
||
|
// Parameters for the next shot.
|
||
|
float m_flFiringPower;
|
||
|
float m_flFiringAccuracy;
|
||
|
|
||
|
float m_flMortarYaw; // What direction the mortar is aimed in.
|
||
|
float m_flMortarPitch;
|
||
|
|
||
|
// This is what is used on the client to draw the ground line and orient the mortar.
|
||
|
// It is usually copied right over from m_flClientMortarYaw (which comes from the server),
|
||
|
// but this is also used when rotating the mortar so you can see the line move smoothly.
|
||
|
float m_flClientMortarYaw;
|
||
|
|
||
|
// This is set to about 1/4 seconds when you rotate the mortar line so you use the client's
|
||
|
// (smooth, non-lagged) yaw changes instead of the server's.
|
||
|
float m_flForceClientYawCountdown;
|
||
|
|
||
|
private:
|
||
|
C_ObjectMortar( const C_ObjectMortar & ); // not defined, not accessible
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_CLIENTCLASS_DT(C_ObjectMortar, DT_ObjectMortar, CObjectMortar)
|
||
|
RecvPropInt( RECVINFO(m_iRoundType) ),
|
||
|
RecvPropArray( RecvPropInt( RECVINFO(m_iMortarRounds[0]) ), m_iMortarRounds )
|
||
|
END_RECV_TABLE()
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
C_ObjectMortar::C_ObjectMortar( void )
|
||
|
{
|
||
|
memset( m_iMortarRounds, 0, sizeof( m_iMortarRounds ) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_ObjectMortar::SetDormant( bool bDormant )
|
||
|
{
|
||
|
BaseClass::SetDormant( bDormant );
|
||
|
ENTITY_PANEL_ACTIVATE( "mortar", !bDormant );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Cycle ammo types on the mortar
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_ObjectMortar::Select( void )
|
||
|
{
|
||
|
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer();
|
||
|
if ( pPlayer == NULL )
|
||
|
return;
|
||
|
|
||
|
int iOldType = m_iRoundType++;
|
||
|
|
||
|
// Cycle to the next ammo type
|
||
|
while ( m_iRoundType != iOldType )
|
||
|
{
|
||
|
// Hit the end of the round types?
|
||
|
if ( m_iRoundType == MA_LASTAMMOTYPE )
|
||
|
{
|
||
|
m_iRoundType = MA_SHELL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Does this round type need a technology?
|
||
|
if ( MortarAmmoTechs[ m_iRoundType ] && MortarAmmoTechs[ m_iRoundType ][0] )
|
||
|
{
|
||
|
// Does the player have the technology?
|
||
|
if ( pPlayer->HasNamedTechnology( MortarAmmoTechs[ m_iRoundType ] ) )
|
||
|
{
|
||
|
// Do we have ammo?
|
||
|
if ( m_iMortarRounds[ m_iRoundType ] > 0 )
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Go to the next round type
|
||
|
m_iRoundType++;
|
||
|
}
|
||
|
|
||
|
engine->ClientCmd( VarArgs("mortarround %d", m_iRoundType) );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_ObjectMortar::RecalculateIDString( void )
|
||
|
{
|
||
|
// Only owners get full data
|
||
|
if ( IsOwnedByLocalPlayer() )
|
||
|
{
|
||
|
if ( m_iRoundType >= 0 )
|
||
|
{
|
||
|
// -1 means we have infinite rounds of this type
|
||
|
if ( m_iMortarRounds[ m_iRoundType ] == -1 )
|
||
|
{
|
||
|
Q_snprintf( m_szIDString, sizeof(m_szIDString), "%s - %s", GetTargetDescription(), MortarAmmoNames[ m_iRoundType ] );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Q_snprintf( m_szIDString, sizeof(m_szIDString), "%s - %d %s", GetTargetDescription(), m_iMortarRounds[ m_iRoundType ], MortarAmmoNames[ m_iRoundType ] );
|
||
|
}
|
||
|
Q_strncat( m_szIDString, "\nUse it to change ammo types.", sizeof(m_szIDString), COPY_ALL_CHARACTERS );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BaseClass::RecalculateIDString();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_ObjectMortar::ClickFire( void )
|
||
|
{
|
||
|
switch( m_iFiringState )
|
||
|
{
|
||
|
case MORTAR_IDLE:
|
||
|
m_iFiringState = MORTAR_CHARGING_POWER;
|
||
|
break;
|
||
|
|
||
|
case MORTAR_CHARGING_POWER:
|
||
|
m_flFiringPower = m_flPower;
|
||
|
m_iFiringState = MORTAR_CHARGING_ACCURACY;
|
||
|
break;
|
||
|
|
||
|
case MORTAR_CHARGING_ACCURACY:
|
||
|
m_flFiringAccuracy = m_flPower;
|
||
|
m_iFiringState = MORTAR_IDLE;
|
||
|
|
||
|
FireMortar();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_ObjectMortar::GetMortarData( float *flClientMortarYaw, bool *bAllowedToFire, float *flPower, float *flFiringPower, float *flFiringAccuracy, int *iFiringState )
|
||
|
{
|
||
|
*flClientMortarYaw = m_flClientMortarYaw;
|
||
|
*bAllowedToFire = m_bAllowedToFire;
|
||
|
*flPower = m_flPower;
|
||
|
*flFiringPower = m_flFiringPower;
|
||
|
*flFiringAccuracy = m_flFiringAccuracy;
|
||
|
*iFiringState = m_iFiringState;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_ObjectMortar::SendYawCommand( void )
|
||
|
{
|
||
|
char szbuf[48];
|
||
|
Q_snprintf( szbuf, sizeof( szbuf ), "MortarYaw %0.2f\n", m_flClientMortarYaw );
|
||
|
SendClientCommand( szbuf );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_ObjectMortar::ForceClientYawCountdown( float flTime )
|
||
|
{
|
||
|
m_flForceClientYawCountdown = flTime;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Control screen
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CMortarControlPanel : public CObjectControlPanel
|
||
|
{
|
||
|
DECLARE_CLASS( CMortarControlPanel, CObjectControlPanel );
|
||
|
public:
|
||
|
CMortarControlPanel( vgui::Panel *parent, const char *panelName );
|
||
|
virtual ~CMortarControlPanel();
|
||
|
|
||
|
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
|
||
|
virtual void OnCommand( const char *command );
|
||
|
C_ObjectMortar* GetMortar() const;
|
||
|
|
||
|
protected:
|
||
|
virtual vgui::Panel* TickCurrentPanel();
|
||
|
|
||
|
private:
|
||
|
CMortarMinimapPanel *m_pMinimapPanel;
|
||
|
};
|
||
|
|
||
|
|
||
|
DECLARE_VGUI_SCREEN_FACTORY( CMortarControlPanel, "mortar_control_panel" );
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Constructor:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CMortarControlPanel::CMortarControlPanel( vgui::Panel *parent, const char *panelName )
|
||
|
: BaseClass( parent, "CMortarControlPanel" )
|
||
|
{
|
||
|
m_pMinimapPanel = new CMortarMinimapPanel( this, "MinimapPanel" );
|
||
|
m_pMinimapPanel->Init( NULL );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CMortarControlPanel::~CMortarControlPanel()
|
||
|
{
|
||
|
delete m_pMinimapPanel;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Initialization
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CMortarControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
|
||
|
{
|
||
|
// Make sure all named panels are created up above because BaseClass::Init initializes them
|
||
|
// all from their keyvalues.
|
||
|
if ( !BaseClass::Init( pKeyValues, pInitData ) )
|
||
|
return false;
|
||
|
|
||
|
// Init subpanels.
|
||
|
int x, y, w, h;
|
||
|
GetBounds( x, y, w, h );
|
||
|
|
||
|
m_pMinimapPanel->LevelInit( engine->GetLevelName() );
|
||
|
m_pMinimapPanel->SetVisible( true );
|
||
|
m_pMinimapPanel->InitMortarMinimap( GetMortar() );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
C_ObjectMortar* CMortarControlPanel::GetMortar() const
|
||
|
{
|
||
|
return dynamic_cast< C_ObjectMortar* >( GetOwningObject() );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void C_ObjectMortar::FireMortar( void )
|
||
|
{
|
||
|
char cmd[512];
|
||
|
Q_snprintf( cmd, sizeof( cmd ), "FireMortar %.2f %.2f", m_flFiringPower, m_flFiringAccuracy );
|
||
|
SendClientCommand( cmd );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Frame-based update
|
||
|
//-----------------------------------------------------------------------------
|
||
|
vgui::Panel* CMortarControlPanel::TickCurrentPanel()
|
||
|
{
|
||
|
C_BaseObject *pObj = GetOwningObject();
|
||
|
if (!pObj)
|
||
|
return BaseClass::TickCurrentPanel();;
|
||
|
|
||
|
ShowOwnerLabel( true );
|
||
|
ShowHealthLabel( true );
|
||
|
|
||
|
C_ObjectMortar *pMortar = GetMortar();
|
||
|
if ( !pMortar )
|
||
|
return BaseClass::TickCurrentPanel();;
|
||
|
|
||
|
ShowOwnerLabel( false );
|
||
|
ShowHealthLabel( false );
|
||
|
|
||
|
m_pMinimapPanel->Repaint();
|
||
|
|
||
|
float flAccuracySpeed = (1.0 / MORTAR_CHARGE_ACCURACY_RATE);
|
||
|
|
||
|
// Handle power charging
|
||
|
switch( pMortar->m_iFiringState )
|
||
|
{
|
||
|
case MORTAR_IDLE:
|
||
|
pMortar->m_flPower = 0;
|
||
|
break;
|
||
|
|
||
|
case MORTAR_CHARGING_POWER:
|
||
|
pMortar->m_flPower = MIN( pMortar->m_flPower + ( (1.0 / MORTAR_CHARGE_POWER_RATE) * gpGlobals->frametime), 1 );
|
||
|
pMortar->m_flFiringPower = 0;
|
||
|
pMortar->m_flFiringAccuracy = 0;
|
||
|
if ( pMortar->m_flPower >= 1.0 )
|
||
|
{
|
||
|
// Hit Max, start going down
|
||
|
pMortar->m_flFiringPower = pMortar->m_flPower;
|
||
|
pMortar->m_iFiringState = MORTAR_CHARGING_ACCURACY;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case MORTAR_CHARGING_ACCURACY:
|
||
|
// Calculate accuracy speed
|
||
|
if ( pMortar->m_flFiringPower > 0.5 )
|
||
|
{
|
||
|
// Shots over halfway suffer an increased speed to the accuracy power, making accurate shots harder
|
||
|
float flAdjustedPower = (pMortar->m_flFiringPower - 0.5) * 3.0;
|
||
|
flAccuracySpeed += (pMortar->m_flFiringPower * flAdjustedPower);
|
||
|
}
|
||
|
|
||
|
pMortar->m_flPower = MAX( pMortar->m_flPower - ( flAccuracySpeed * gpGlobals->frametime), -0.25f);
|
||
|
if ( pMortar->m_flPower <= -0.25 )
|
||
|
{
|
||
|
// Hit Min, fire mortar
|
||
|
pMortar->m_flFiringAccuracy = pMortar->m_flPower;
|
||
|
pMortar->m_iFiringState = MORTAR_IDLE;
|
||
|
|
||
|
pMortar->FireMortar();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return BaseClass::TickCurrentPanel();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Button click handlers
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CMortarControlPanel::OnCommand( const char *command )
|
||
|
{
|
||
|
C_ObjectMortar *pMortar = GetMortar();
|
||
|
if ( !pMortar )
|
||
|
return;
|
||
|
|
||
|
if ( !Q_stricmp( command, "FireMortar" ) )
|
||
|
{
|
||
|
pMortar->ClickFire();
|
||
|
}
|
||
|
|
||
|
BaseClass::OnCommand(command);
|
||
|
}
|
||
|
|