//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "ObjectControlPanel.h" #include #include #include "vgui_bitmapbutton.h" #include #include #include "C_BaseTFPlayer.h" #include "clientmode_tfbase.h" #include #include #include "vgui_rotation_slider.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" #define DISMANTLE_WAIT_TIME 5.0 //----------------------------------------------------------------------------- // Standard VGUI panel for objects //----------------------------------------------------------------------------- DECLARE_VGUI_SCREEN_FACTORY( CObjectControlPanel, "object_control_panel" ); //----------------------------------------------------------------------------- // Constructor: //----------------------------------------------------------------------------- CObjectControlPanel::CObjectControlPanel( vgui::Panel *parent, const char *panelName ) : BaseClass( parent, panelName, g_hVGuiObjectScheme ) { // Make some high-level panels to group stuff we want to activate/deactivate m_pActivePanel = new CCommandChainingPanel( this, "ActivePanel" ); m_pDeterioratingPanel = new CCommandChainingPanel( this, "DeterioratingPanel" ); m_pDismantlingPanel = new CCommandChainingPanel( this, "DismantlingPanel" ); SetCursor( vgui::dc_none ); // don't draw a VGUI cursor for this panel, and for its children // Make sure these are behind everything m_pActivePanel->SetZPos( -1 ); m_pDeterioratingPanel->SetZPos( -1 ); m_pDismantlingPanel->SetZPos( -1 ); } //----------------------------------------------------------------------------- // Initialization //----------------------------------------------------------------------------- bool CObjectControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData ) { // Grab ahold of certain well-known controls m_pHealthLabel = new vgui::Label( this, "HealthReadout", "" ); m_pOwnerLabel = new vgui::Label( this, "OwnerReadout", "" ); m_pDismantleButton = new CBitmapButton( this, "DismantleButton", "Dismantle" ); m_pAssumeControlButton = new CBitmapButton( GetDeterioratingPanel(), "AssumeControl", "" ); m_pDismantleTimeLabel = new vgui::Label( GetDismantlingPanel(), "DismantleTime", "" ); m_flDismantleTime = -1; // Make sure we get ticked... vgui::ivgui()->AddTickSignal( GetVPanel() ); if (!BaseClass::Init(pKeyValues, pInitData)) return false; SetCursor( vgui::dc_none ); // don't draw a VGUI cursor for this panel, and for its children // Make the bounds of the sub-panels match int x, y, w, h; GetBounds( x, y, w, h ); m_pActivePanel->SetBounds( x, y, w, h ); m_pDeterioratingPanel->SetBounds( x, y, w, h ); m_pDismantlingPanel->SetBounds( x, y, w, h ); // Make em all invisible m_pActivePanel->SetVisible( false ); m_pDeterioratingPanel->SetVisible( false ); m_pDismantlingPanel->SetVisible( false ); m_pCurrentPanel = m_pActivePanel; return true; } //----------------------------------------------------------------------------- // Returns the object it's attached to //----------------------------------------------------------------------------- C_BaseObject *CObjectControlPanel::GetOwningObject() const { C_BaseEntity *pScreenEnt = GetEntity(); if (!pScreenEnt) return NULL; C_BaseEntity *pObj = pScreenEnt->GetOwnerEntity(); if (!pObj) return NULL; Assert( dynamic_cast(pObj) ); return static_cast(pObj); } //----------------------------------------------------------------------------- // Ticks the panel when its in its various states //----------------------------------------------------------------------------- void CObjectControlPanel::OnTickDeteriorating( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer ) { char buf[256]; if ( pLocalPlayer && ClassCanBuild( pLocalPlayer->PlayerClass(), pObj->GetType() ) ) { int nCost = CalculateObjectCost( pObj->GetType(), pLocalPlayer->GetNumObjects( pObj->GetType() ), pLocalPlayer->GetTeamNumber() ); Q_snprintf( buf, sizeof( buf ), "Buy for %d", nCost ); m_pAssumeControlButton->SetText( buf ); m_pAssumeControlButton->SetVisible( true ); bool bHasEnoughResources = pLocalPlayer->GetBankResources() >= nCost; m_pAssumeControlButton->SetEnabled( bHasEnoughResources ); } else { m_pAssumeControlButton->SetVisible( false ); } ShowDismantleButton( false ); } void CObjectControlPanel::OnTickActive( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer ) { ShowDismantleButton( !(pObj->GetFlags() & OF_CANNOT_BE_DISMANTLED) && pObj->GetOwner() == pLocalPlayer ); } void CObjectControlPanel::OnTickDismantling( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer ) { ShowDismantleButton( false ); if ( !m_bDismantled && (gpGlobals->curtime >= m_flDismantleTime)) { Dismantle(); m_bDismantled = true; } int nSec = (int)(m_flDismantleTime - 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_pDismantleTimeLabel->SetText( buf ); } vgui::Panel* CObjectControlPanel::TickCurrentPanel() { C_BaseTFPlayer *pLocalPlayer = C_BaseTFPlayer::GetLocalPlayer(); C_BaseObject *pObj = GetOwningObject(); if (IsDismantling()) { m_pCurrentPanel = GetDismantlingPanel(); OnTickDismantling(pObj, pLocalPlayer); } else if (pObj->IsDeteriorating()) { m_pCurrentPanel = GetDeterioratingPanel(); OnTickDeteriorating(pObj, pLocalPlayer); } else { m_pCurrentPanel = GetActivePanel(); OnTickActive(pObj, pLocalPlayer); } return m_pCurrentPanel; } void CObjectControlPanel::ShowDismantleButton( bool bShow ) { m_pDismantleButton->SetVisible( bShow ); } void CObjectControlPanel::ShowOwnerLabel( bool bShow ) { m_pOwnerLabel->SetVisible( bShow ); } void CObjectControlPanel::ShowHealthLabel( bool bShow ) { m_pHealthLabel->SetVisible( bShow ); } void CObjectControlPanel::SendToServerObject( const char *pMsg ) { C_BaseObject *pObj = GetOwningObject(); if (pObj) { pObj->SendClientCommand( pMsg ); } } //----------------------------------------------------------------------------- // Frame-based update //----------------------------------------------------------------------------- void CObjectControlPanel::OnTick() { BaseClass::OnTick(); C_BaseObject *pObj = GetOwningObject(); if (!pObj) return; char buf[256]; Q_snprintf( buf, sizeof( buf ), "Health: %d%%", (int)(pObj->HealthFraction() * 100.0f) ); m_pHealthLabel->SetText( buf ); C_BaseTFPlayer *pPlayer = pObj->GetOwner(); if (pPlayer) { Q_snprintf( buf, sizeof( buf ), "Owner: %s", pPlayer->GetPlayerName() ); } else { Q_snprintf( buf, sizeof( buf ), "No Owner" ); } m_pOwnerLabel->SetText( buf ); // Update the current subpanel m_pCurrentPanel->SetVisible( false ); m_pCurrentPanel = TickCurrentPanel(); m_pCurrentPanel->SetVisible( true ); } //----------------------------------------------------------------------------- // Dismantles the object //----------------------------------------------------------------------------- void CObjectControlPanel::Dismantle() { SendToServerObject( "dismantle" ); } //----------------------------------------------------------------------------- // Starts/stops dismantling //----------------------------------------------------------------------------- void CObjectControlPanel::StartDismantling() { m_flDismantleTime = gpGlobals->curtime + DISMANTLE_WAIT_TIME; m_bDismantled = false; } void CObjectControlPanel::StopDismantling() { m_flDismantleTime = -1.0f; } bool CObjectControlPanel::IsDismantling() const { return m_flDismantleTime >= 0.0f; } //----------------------------------------------------------------------------- // Assumes control of the object //----------------------------------------------------------------------------- void CObjectControlPanel::AssumeControl() { SendToServerObject( "takecontrol" ); } //----------------------------------------------------------------------------- // Button click handlers //----------------------------------------------------------------------------- void CObjectControlPanel::OnCommand( const char *command ) { if (!Q_strnicmp(command, "Dismantle", 10)) { StartDismantling(); return; } if (!Q_strnicmp(command, "CancelDismantle", 20)) { StopDismantling(); return; } if (!Q_strnicmp(command, "AssumeControl", 15)) { AssumeControl(); return; } BaseClass::OnCommand(command); } DECLARE_VGUI_SCREEN_FACTORY( CRotatingObjectControlPanel, "rotating_object_control_panel" ); //----------------------------------------------------------------------------- // This is a panel for an object that has rotational controls //----------------------------------------------------------------------------- CRotatingObjectControlPanel::CRotatingObjectControlPanel( vgui::Panel *parent, const char *panelName ) : BaseClass( parent, panelName ) { } bool CRotatingObjectControlPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData ) { // Grab ahold of certain well-known controls m_pRotationSlider = new CRotationSlider( GetActivePanel(), "RotationSlider" ); m_pRotationLabel = new vgui::Label( GetActivePanel(), "RotationLabel", "Rotation Control" ); if (!BaseClass::Init(pKeyValues, pInitData)) return false; m_pRotationSlider->SetControlledObject( GetOwningObject() ); return true; } void CRotatingObjectControlPanel::OnTickActive( C_BaseObject *pObj, C_BaseTFPlayer *pLocalPlayer ) { BaseClass::OnTickActive( pObj, pLocalPlayer ); bool bEnable = (pObj->GetOwner() == pLocalPlayer); m_pRotationSlider->SetVisible( bEnable ); m_pRotationLabel->SetVisible( bEnable ); }