summaryrefslogtreecommitdiff
path: root/game/client/tf2/c_obj_mortar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/client/tf2/c_obj_mortar.cpp')
-rw-r--r--game/client/tf2/c_obj_mortar.cpp389
1 files changed, 389 insertions, 0 deletions
diff --git a/game/client/tf2/c_obj_mortar.cpp b/game/client/tf2/c_obj_mortar.cpp
new file mode 100644
index 0000000..ea4e79b
--- /dev/null
+++ b/game/client/tf2/c_obj_mortar.cpp
@@ -0,0 +1,389 @@
+//========= 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);
+}
+