diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf2/c_obj_mortar.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/tf2/c_obj_mortar.cpp')
| -rw-r--r-- | game/client/tf2/c_obj_mortar.cpp | 389 |
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); +} + |