diff options
Diffstat (limited to 'game/client/tf2/c_vehicle_mortar.cpp')
| -rw-r--r-- | game/client/tf2/c_vehicle_mortar.cpp | 869 |
1 files changed, 869 insertions, 0 deletions
diff --git a/game/client/tf2/c_vehicle_mortar.cpp b/game/client/tf2/c_vehicle_mortar.cpp new file mode 100644 index 0000000..844c544 --- /dev/null +++ b/game/client/tf2/c_vehicle_mortar.cpp @@ -0,0 +1,869 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "c_basefourwheelvehicle.h" +#include "tf_movedata.h" +#include "ObjectControlPanel.h" +#include <vgui_controls/Label.h> +#include <vgui_controls/Button.h> +#include "vehicle_mortar_shared.h" +#include "vgui_rotation_slider.h" +#include <vgui/ISurface.h> +#include "vgui_basepanel.h" +#include "ground_line.h" +#include "hud_minimap.h" +#include "vgui_bitmapimage.h" +#include "iusesmortarpanel.h" + +// How long it waits after you've changed the mortar's yaw to draw using the server's value. +#define CLIENT_MORTAR_YAW_COUNTDOWN 0.5 + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class C_VehicleMortar : public C_BaseTFFourWheelVehicle, public IUsesMortarPanel +{ + DECLARE_CLASS( C_VehicleMortar, C_BaseTFFourWheelVehicle ); +public: + DECLARE_CLIENTCLASS(); + + C_VehicleMortar(); + + virtual void ReceiveMessage( int classID, bf_read &msg ); + + // Fire off a mortar. + void FireMortar(); + + virtual void ClientThink(); + +// C_BaseEntity overrides. +public: + virtual void GetBoneControllers(float controllers[MAXSTUDIOBONECTRLS]); + +// 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: + // 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_VehicleMortar( const C_VehicleMortar & ); // not defined, not accessible + +}; + + +IMPLEMENT_CLIENTCLASS_DT(C_VehicleMortar, DT_VehicleMortar, CVehicleMortar) + RecvPropFloat( RECVINFO( m_flMortarYaw ) ), + RecvPropFloat( RECVINFO( m_flMortarPitch ) ), + RecvPropBool( RECVINFO( m_bAllowedToFire ) ) +END_RECV_TABLE() + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- + +C_VehicleMortar::C_VehicleMortar() +{ + m_iFiringState = MORTAR_IDLE; + m_bMortarReloading = false; + m_flPower = 0; + + m_flMortarYaw = 0; + m_flClientMortarYaw = 0; + m_flMortarPitch = 0; + m_flForceClientYawCountdown = 0; + m_bAllowedToFire = true; + + SetNextClientThink( CLIENT_THINK_ALWAYS ); +} + + +void C_VehicleMortar::ReceiveMessage( int classID, bf_read &msg ) +{ + if ( classID != GetClientClass()->m_ClassID ) + { + // message is for subclass + BaseClass::ReceiveMessage( classID, msg ); + return; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_VehicleMortar::ClickFire() +{ + 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_VehicleMortar::FireMortar() +{ + char cmd[512]; + Q_snprintf( cmd, sizeof( cmd ), "FireMortar %.2f %.2f", m_flFiringPower, m_flFiringAccuracy ); + SendClientCommand( cmd ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_VehicleMortar::SendYawCommand( void ) +{ + char szbuf[48]; + Q_snprintf( szbuf, sizeof( szbuf ), "MortarYaw %0.2f\n", m_flClientMortarYaw ); + SendClientCommand( szbuf ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_VehicleMortar::ForceClientYawCountdown( float flTime ) +{ + m_flForceClientYawCountdown = flTime; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_VehicleMortar::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_VehicleMortar::ClientThink() +{ + m_flForceClientYawCountdown -= gpGlobals->frametime; + if ( m_flForceClientYawCountdown <= 0 ) + { + m_flClientMortarYaw = m_flMortarYaw; + } +} + + +void C_VehicleMortar::GetBoneControllers( float controllers[MAXSTUDIOBONECTRLS]) +{ + BaseClass::GetBoneControllers( controllers); + + controllers[0] = anglemod( m_flClientMortarYaw ) / 360.0; + controllers[1] = anglemod( m_flMortarPitch ) / 360.0; +} + + +//----------------------------------------------------------------------------- +// CMortarMinimapPanel +//----------------------------------------------------------------------------- +CMortarMinimapPanel::CMortarMinimapPanel( vgui::Panel *pParent, const char *pElementName ) + : CMinimapPanel( pElementName ) +{ + SetParent( pParent ); + + m_bMouseDown = false; + m_bFireButtonDown = false; + m_LastX = m_LastY = -1; + + m_nTextureId = vgui::surface()->CreateNewTextureID(); + vgui::surface()->DrawSetTextureFile( m_nTextureId, "hud/minimap/mortar_slider", true, false ); + + m_nTextureId_CantFire = vgui::surface()->CreateNewTextureID(); + vgui::surface()->DrawSetTextureFile( m_nTextureId_CantFire, "hud/minimap/mortar_slider_cantfire", true, false ); +} + + +CMortarMinimapPanel::~CMortarMinimapPanel() +{ +} + +void CMortarMinimapPanel::InitMortarMinimap( C_BaseEntity *pMortar ) +{ + BaseClass::Init( NULL ); + + m_hMortar = pMortar; + + m_MortarButtonUp.Init( GetVPanel(), "hud/minimap/icon_mortarbutton_up" ); + m_MortarButtonDown.Init( GetVPanel(), "hud/minimap/icon_mortarbutton_dn" ); + m_MortarButtonCantFire.Init( GetVPanel(), "hud/minimap/icon_mortarbutton_cantfire" ); + + m_MortarDirectionImage.Init( GetVPanel(), "hud/minimap/icon_player_arrow" ); + m_MortarDirectionImage.SetColor( Color( 0, 255, 0, 255 ) ); +} + + +C_BaseEntity *CMortarMinimapPanel::GetMortar() const +{ + return (C_BaseEntity*)m_hMortar; +} + + +void CMortarMinimapPanel::Paint() +{ + BaseClass::Paint(); + + C_BaseEntity *pMortar = GetMortar(); + IUsesMortarPanel *pMortarInterface = dynamic_cast< IUsesMortarPanel* >( pMortar ); + if ( pMortar && pMortarInterface ) + { + float flClientMortarYaw, flPower, flFiringPower, flFiringAccuracy; + int iFiringState; + bool bAllowedToFire; + pMortarInterface->GetMortarData( &flClientMortarYaw, &bAllowedToFire, &flPower, &flFiringPower, &flFiringAccuracy, &iFiringState ); + + float yaw = flClientMortarYaw + 90; + + float x, y; + if ( WorldToMinimap( MINIMAP_CLAMP, pMortar->GetAbsOrigin(), x, y ) ) + { + int size = 20; + + BitmapImage *pImage = &m_MortarButtonCantFire; + if ( bAllowedToFire ) + { + if ( m_bFireButtonDown ) + pImage = &m_MortarButtonDown; + else + pImage = &m_MortarButtonUp; + } + + pImage->DoPaint( x-size/2, y-size/2, size, size, yaw ); + + size = 40; + m_MortarDirectionImage.DoPaint( x-size/2, y-size/2, size, size, pMortar->GetAbsAngles()[YAW] + 90 ); + + + // Draw the power bar. + float flAngle = pMortar->GetAbsAngles()[YAW] + flClientMortarYaw; + Vector vForward( -sin( DEG2RAD( flAngle ) ), cos( DEG2RAD( flAngle ) ), 0 ); + Vector vRight( vForward.y, -vForward.x, 0 ); + + Vector vStartPoint = pMortar->GetAbsOrigin(); + Vector vEndPoint = vStartPoint + vForward * MORTAR_RANGE_MAX_INITIAL; + Vector vInaccuracy = vEndPoint + vRight * (MORTAR_RANGE_MAX_INITIAL * MORTAR_INACCURACY_MAX_INITIAL); + + Vector2D vStart2D, vEnd2D, vInaccuracy2D; + WorldToMinimap( MINIMAP_ALWAYS_ACCEPT, vStartPoint, vStart2D.x, vStart2D.y ); + WorldToMinimap( MINIMAP_ALWAYS_ACCEPT, vEndPoint, vEnd2D.x, vEnd2D.y ); + WorldToMinimap( MINIMAP_ALWAYS_ACCEPT, vInaccuracy, vInaccuracy2D.x, vInaccuracy2D.y ); + + Vector2D vDir = vEnd2D - vStart2D; + Vector2DNormalize( vDir ); + + + // These variables control the look. + float flLength = (vEnd2D - vStart2D).Length(); + float flZeroT = 1.0f / 5; + float flZero = flLength * flZeroT; + + float flFirePower = MAX( flPower, flFiringPower ); + + float flStartFatness = 2; + float flEndFatness = flStartFatness; + + float flScalePower = flFiringAccuracy; + if ( iFiringState != MORTAR_IDLE ) + flScalePower = flPower; + + Vector2D vInaccuracyDir = vInaccuracy2D - vEnd2D; + flEndFatness *= vInaccuracyDir.Length() * flScalePower * 0.4; + flEndFatness = MAX( fabs( flEndFatness ), flStartFatness ); + + Vector2D vPerp( vDir.y, -vDir.x ); + Vector2DNormalize( vPerp ); + + Vector2D vStartPerp = vPerp * flStartFatness; + Vector2D vEndPerp = vPerp * flEndFatness; + + + // Draw the red-black power bars. + vgui::ISurface *pSurface = vgui::surface(); + if ( bAllowedToFire ) + pSurface->DrawSetTexture( m_nTextureId ); + else + pSurface->DrawSetTexture( m_nTextureId_CantFire ); + + Vector2D vZeroPerp; + Vector2DLerp( vStartPerp, vEndPerp, flZero / flLength, vZeroPerp ); + + // Draw a black->red bar from zero to our current power. + float flFirePowerDistance = RemapVal( flFirePower, 0, 1, flZero, flLength ); + Vector2D vPowerPerp; + Vector2DLerp( vStartPerp, vEndPerp, RemapVal( flFirePowerDistance, flZero, flLength, flZeroT, 1 ), vPowerPerp ); + + vgui::Vertex_t verts[4]; + verts[0].Init( vStart2D + vDir * flZero - vZeroPerp ); + verts[1].Init( verts[0].m_Position + vZeroPerp * 2 ); + + verts[2].Init( vStart2D + vDir * flFirePowerDistance + vPowerPerp, Vector2D( flFirePower, 0 ) ); + verts[3] = verts[2]; + verts[3].m_Position -= vPowerPerp * 2; + + pSurface->DrawSetColor( 255, 255, 255, 255 ); + pSurface->DrawTexturedPolygon( 4, verts ); + + + // Draw the power slider. + pSurface->DrawSetTexture( -1 ); + + + vgui::Vertex_t line[2]; + line[0].Init( vStart2D + vDir * flFirePowerDistance - vPowerPerp ); + line[1].Init( line[0].m_Position + vPowerPerp * 2 ); + pSurface->DrawTexturedLine( line[0], line[1] ); + + + + // Draw a white outline. + pSurface->DrawSetColor( 255, 255, 255, 255 ); + vgui::Vertex_t pts[4] = + { + vgui::Vertex_t( vStart2D - vStartPerp ), + vgui::Vertex_t( vStart2D + vStartPerp ), + vgui::Vertex_t( vEnd2D + vEndPerp ), + vgui::Vertex_t( vEnd2D - vEndPerp ) + }; + pSurface->DrawTexturedPolyLine( pts, 4 ); + + + // Draw the zero line. + line[0].Init( vStart2D + vDir * flZero - vZeroPerp ); + line[1].Init( line[0].m_Position + vZeroPerp * 2 ); + pSurface->DrawTexturedLine( line[0], line[1] ); + } + } +} + + +void CMortarMinimapPanel::OnMousePressed( vgui::MouseCode code ) +{ + BaseClass::OnMousePressed( code ); + + if (code != vgui::MOUSE_LEFT) + return; + + C_BaseEntity *pMortar = GetMortar(); + IUsesMortarPanel *pMortarInterface = dynamic_cast< IUsesMortarPanel* >( pMortar ); + if ( !pMortar || !pMortarInterface ) + return; + + float flClientMortarYaw, flPower, flFiringPower, flFiringAccuracy; + int iFiringState; + bool bAllowedToFire; + pMortarInterface->GetMortarData( &flClientMortarYaw, &bAllowedToFire, &flPower, &flFiringPower, &flFiringAccuracy, &iFiringState ); + + // See if they clicked the "fire" button. + float x, y; + if ( WorldToMinimap( MINIMAP_ALWAYS_ACCEPT, pMortar->GetAbsOrigin(), x, y ) && + (Vector2D( x, y ) - Vector2D( m_LastX, m_LastY )).Length() <= 8 ) + { + if ( bAllowedToFire ) + { + // Treat it like they clicked the fire button. + m_bFireButtonDown = true; + pMortarInterface->ClickFire(); + } + } + else + { + pMortarInterface->ForceClientYawCountdown( 5000000 ); + } + + m_bMouseDown = true; +} + + +void CMortarMinimapPanel::OnCursorMoved( int x, int y ) +{ + m_LastX = x; + m_LastY = y; + + if ( !m_bMouseDown || m_bFireButtonDown ) + return; + + C_BaseEntity *pMortar = GetMortar(); + IUsesMortarPanel *pMortarInterface = dynamic_cast< IUsesMortarPanel* >( pMortar ); + if ( !pMortar || !pMortarInterface ) + return; + + float flClientMortarYaw, flPower, flFiringPower, flFiringAccuracy; + int iFiringState; + bool bAllowedToFire; + pMortarInterface->GetMortarData( &flClientMortarYaw, &bAllowedToFire, &flPower, &flFiringPower, &flFiringAccuracy, &iFiringState ); + + float mortarX, mortarY; + if ( WorldToMinimap( MINIMAP_ALWAYS_ACCEPT, pMortar->GetAbsOrigin(), mortarX, mortarY ) ) + { + float flAngle = atan2( x - mortarX, mortarY - y ); + flClientMortarYaw = -anglemod( flAngle * 180.0f / M_PI + pMortar->GetAbsAngles()[YAW] ); + } +} + + +void CMortarMinimapPanel::OnMouseReleased( vgui::MouseCode code ) +{ + BaseClass::OnMouseReleased( code ); + + if ( code != vgui::MOUSE_LEFT ) + return; + + m_bMouseDown = false; + + if ( m_bFireButtonDown ) + { + m_bFireButtonDown = false; + } + else + { + C_BaseEntity *pMortar = GetMortar(); + IUsesMortarPanel *pMortarInterface = dynamic_cast< IUsesMortarPanel* >( pMortar ); + if ( pMortar && pMortarInterface ) + { + pMortarInterface->SendYawCommand(); + pMortarInterface->ForceClientYawCountdown( CLIENT_MORTAR_YAW_COUNTDOWN ); + } + } +} + + +//----------------------------------------------------------------------------- +// Control screen +//----------------------------------------------------------------------------- +class CVehicleMortarControlPanel : public CObjectControlPanel +{ + DECLARE_CLASS( CVehicleMortarControlPanel, CObjectControlPanel ); + +public: + + CVehicleMortarControlPanel( vgui::Panel *parent, const char *panelName ); + virtual ~CVehicleMortarControlPanel(); + + virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData ); + virtual void OnCommand( const char *command ); + C_VehicleMortar* GetMortar() const; + + +protected: + + virtual vgui::Panel* TickCurrentPanel(); + + +private: + + void OnTickMainPanel(); + void OnTickDeployPanel( float flDeployTime ); + void OnTickGunnerPanel(); + + void GetInRam( void ); + + void StartDeploying(); + void StopDismantling(); + bool IsDeploying() const; + bool IsUndeploying() const; + bool IsDeployed() const; + +private: + vgui::Label *m_pDriverLabel; + vgui::Label *m_pPassengerLabel; + vgui::Button *m_pOccupyButton; + vgui::Button *m_pCancelDeployButton; + + vgui::Label *m_pDeployMessageLabel; // says "Deployed in" or "Undeployed in" + vgui::Label *m_pDeployTimeLabel; // says "N seconds" + + vgui::EditablePanel *m_pDeployPanel; + vgui::EditablePanel *m_pGunnerPanel; + + CMortarMinimapPanel *m_pMinimapPanel; + + vgui::Label *m_pReloadingLabel; +}; + + +DECLARE_VGUI_SCREEN_FACTORY( CVehicleMortarControlPanel, "vehicle_mortar_control_panel" ); + + +//----------------------------------------------------------------------------- +// Constructor: +//----------------------------------------------------------------------------- +CVehicleMortarControlPanel::CVehicleMortarControlPanel( vgui::Panel *parent, const char *panelName ) + : BaseClass( parent, "CVehicleMortarControlPanel" ) +{ + m_pDeployPanel = new CCommandChainingPanel( this, "DeployPanel" ); + m_pDeployPanel->SetZPos( -1 ); + + m_pGunnerPanel = new CCommandChainingPanel( this, "GunnerPanel" ); + m_pGunnerPanel->SetZPos( -1 ); + + m_pMinimapPanel = new CMortarMinimapPanel( m_pGunnerPanel, "MinimapPanel" ); + m_pMinimapPanel->SetZPos( 10 ); + m_pMinimapPanel->Init( NULL ); +} + + +CVehicleMortarControlPanel::~CVehicleMortarControlPanel() +{ + delete m_pMinimapPanel; +} + + +//----------------------------------------------------------------------------- +// Initialization +//----------------------------------------------------------------------------- +bool CVehicleMortarControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData ) +{ + m_pDriverLabel = new vgui::Label( this, "DriverReadout", "" ); + m_pPassengerLabel = new vgui::Label( this, "PassengerReadout", "" ); + m_pOccupyButton = new vgui::Button( this, "OccupyButton", "Occupy" ); + + m_pDeployMessageLabel = new vgui::Label( m_pDeployPanel, "DeployMessage", "" ); + m_pDeployTimeLabel = new vgui::Label( m_pDeployPanel, "DeployTime", "" ); + m_pCancelDeployButton = new vgui::Button( m_pDeployPanel, "CancelDeployButton", "" ); + + m_pReloadingLabel = new vgui::Label( m_pGunnerPanel, "ReloadingLabel", "" ); + + // 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() ); + + m_pDeployPanel->SetBounds( x, y, w, h ); + m_pDeployPanel->SetVisible( false ); + + m_pGunnerPanel->SetBounds( x, y, w, h ); + m_pGunnerPanel->SetVisible( false ); + + m_pReloadingLabel->SetVisible( false ); + return true; +} + + +//----------------------------------------------------------------------------- +// Frame-based update +//----------------------------------------------------------------------------- + +vgui::Panel* CVehicleMortarControlPanel::TickCurrentPanel() +{ + C_VehicleMortar *pMortar = GetMortar(); + if ( !pMortar ) + return BaseClass::TickCurrentPanel(); + + if ( IsUndeploying() ) + { + OnTickDeployPanel( pMortar->GetDeployFinishTime() ); + return m_pDeployPanel; + } + else if ( IsDeploying() ) + { + OnTickDeployPanel( pMortar->GetDeployFinishTime() ); + return m_pDeployPanel; + } + else if ( IsDeployed() ) + { + OnTickGunnerPanel(); + return m_pGunnerPanel; + } + else + { + OnTickMainPanel(); + return BaseClass::TickCurrentPanel(); + } +} + + +C_VehicleMortar* CVehicleMortarControlPanel::GetMortar() const +{ + return dynamic_cast< C_VehicleMortar* >( GetOwningObject() ); +} + + +void CVehicleMortarControlPanel::OnTickMainPanel() +{ + C_BaseObject *pObj = GetOwningObject(); + if (!pObj) + return; + + ShowOwnerLabel( true ); + ShowHealthLabel( true ); + + Assert( dynamic_cast<C_VehicleMortar*>(pObj) ); + C_VehicleMortar *pRam = static_cast<C_VehicleMortar*>(pObj); + + char buf[256]; + // Update the currently manned player label + if ( pRam->GetDriverPlayer() ) + { + Q_snprintf( buf, sizeof( buf ), "Driven by %s", pRam->GetDriverPlayer()->GetPlayerName() ); + m_pDriverLabel->SetText( buf ); + m_pDriverLabel->SetVisible( true ); + } + else + { + m_pDriverLabel->SetVisible( false ); + } + + int nPassengerCount = pRam->GetPassengerCount(); + int nMaxPassengerCount = pRam->GetMaxPassengerCount(); + + Q_snprintf( buf, sizeof( buf ), "Passengers %d/%d", nPassengerCount >= 1 ? nPassengerCount - 1 : 0, nMaxPassengerCount - 1 ); + m_pPassengerLabel->SetText( buf ); + + // Update the get in button + if ( pRam->IsPlayerInVehicle( C_BaseTFPlayer::GetLocalPlayer() ) ) + { + m_pOccupyButton->SetEnabled( false ); + return; + } + + if ( pRam->GetOwner() == C_BaseTFPlayer::GetLocalPlayer() ) + { + if (nPassengerCount == nMaxPassengerCount) + { + // Owners can boot other players to get in + C_BaseTFPlayer *pPlayer = static_cast<C_BaseTFPlayer*>(pRam->GetPassenger( VEHICLE_ROLE_DRIVER )); + Q_snprintf( buf, sizeof( buf ), "Get In (Ejecting %s)", pPlayer->GetPlayerName() ); + m_pDriverLabel->SetText( buf ); + m_pOccupyButton->SetEnabled( true ); + } + else + { + m_pOccupyButton->SetText( "Get In" ); + m_pOccupyButton->SetEnabled( true ); + } + } + else + { + m_pOccupyButton->SetText( "Get In" ); + m_pOccupyButton->SetEnabled( pRam->GetPassengerCount() < pRam->GetMaxPassengerCount() ); + } +} + + +void CVehicleMortarControlPanel::OnTickDeployPanel( float flDeployTime ) +{ + ShowDismantleButton( false ); + + // Update the countdown. + int nSec = (int)(flDeployTime - gpGlobals->curtime + 0.5f); + if (nSec < 0) + nSec = 0; + + char buf[256]; + int nLen = Q_snprintf( buf, sizeof( buf ), "%d second", nSec ); + if (nSec != 1) + { + buf[nLen] = 's'; + ++nLen; + buf[nLen] = 0; + } + + m_pDeployTimeLabel->SetText( buf ); +} + + +void CVehicleMortarControlPanel::OnTickGunnerPanel() +{ + C_VehicleMortar *pMortar = GetMortar(); + if ( !pMortar ) + return; + + ShowOwnerLabel( false ); + ShowHealthLabel( false ); + + m_pMinimapPanel->Repaint(); + + // If it's reloading, tell the player + m_pReloadingLabel->SetVisible( pMortar->m_bMortarReloading ); + if ( pMortar->m_bMortarReloading ) + { + return; + } + + 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; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Handle clicking on the Occupy button +//----------------------------------------------------------------------------- +void CVehicleMortarControlPanel::GetInRam( void ) +{ + SendToServerObject( "toggle_use" ); +} + +//----------------------------------------------------------------------------- +// Starts/stops deploying +//----------------------------------------------------------------------------- + +bool CVehicleMortarControlPanel::IsDeploying() const +{ + C_VehicleMortar *pMortar = GetMortar(); + if ( !pMortar ) + return false; + + return !IsDeployed() && pMortar->GetDeployFinishTime() > 0.0f; +} + +bool CVehicleMortarControlPanel::IsUndeploying() const +{ + C_VehicleMortar *pMortar = GetMortar(); + if ( !pMortar ) + return false; + + return IsDeployed() && pMortar->GetDeployFinishTime() > 0.0f; +} + +bool CVehicleMortarControlPanel::IsDeployed() const +{ + C_VehicleMortar *pMortar = GetMortar(); + if ( pMortar ) + return pMortar->GetVehicleModeDeploy() == VEHICLE_MODE_DEPLOYED; + else + return false; +} + +//----------------------------------------------------------------------------- +// Button click handlers +//----------------------------------------------------------------------------- +void CVehicleMortarControlPanel::OnCommand( const char *command ) +{ + C_VehicleMortar *pMortar = GetMortar(); + if ( !pMortar ) + return; + + if (!Q_strnicmp(command, "Occupy", 7)) + { + GetInRam(); + return; + } + else if ( !Q_stricmp( command, "Deploy" ) ) + { + m_pDeployMessageLabel->SetText( "Deployed in" ); + m_pCancelDeployButton->SetVisible( true ); + + SendToServerObject( "Deploy" ); // Tell the server. + } + else if ( !Q_stricmp( command, "CancelDeploy" ) ) + { + SendToServerObject( command ); + } + else if ( !Q_stricmp( command, "Undeploy" ) ) + { + m_pDeployMessageLabel->SetText( "Undeployed in" ); + m_pCancelDeployButton->SetVisible( false ); + + SendToServerObject( "Undeploy" ); // Tell the server. + } + else if ( !Q_stricmp( command, "FireMortar" ) ) + { + pMortar->ClickFire(); + } + + BaseClass::OnCommand(command); +} + |