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.
462 lines
12 KiB
462 lines
12 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Client Side COrder class |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include "cbase.h" |
|
#include "hud_orders.h" |
|
#include "c_order.h" |
|
#include <vgui_controls/Controls.h> |
|
#include <vgui/ISurface.h> |
|
#include "minimap_trace.h" |
|
#include "VGuiMatSurface/IMatSystemSurface.h" |
|
#include "c_func_resource.h" |
|
#include "tf_shareddefs.h" |
|
#include "c_baseobject.h" |
|
#include "tf_hints.h" |
|
#include "hud.h" |
|
#include "c_basetfplayer.h" |
|
#include "c_tf_hintmanager.h" |
|
#include "clientmode_tfnormal.h" |
|
|
|
#define NEW_ORDER_ANIM_DURATION 1.0f |
|
#define NEW_ORDERS_RIGHT XRES(640-8) |
|
#define NEW_ORDERS_LEFT XRES(8) |
|
#define NEW_ORDERS_WIDTH (ORDERS_RIGHT - NEW_ORDERS_LEFT) //(NEW_ORDERS_RIGHT - ORDERS_LEFT) |
|
|
|
|
|
class COrderLabel : public vgui::Label |
|
{ |
|
public: |
|
COrderLabel( vgui::Panel *pParent, const char *pPanelName, const char *pText ) |
|
: vgui::Label( pParent, pPanelName, pText ) |
|
{ |
|
} |
|
|
|
virtual void OnThink() |
|
{ |
|
BaseClass::OnThink(); |
|
|
|
// Resize? |
|
int x, y, w, h; |
|
if( m_flAnimCounter < NEW_ORDER_ANIM_DURATION ) |
|
{ |
|
int wantedWidth, dummy; |
|
GetContentSize( wantedWidth, dummy ); |
|
wantedWidth += 10; |
|
|
|
float flPercent = m_flAnimCounter / NEW_ORDER_ANIM_DURATION; |
|
int newWidth = (int)(NEW_ORDERS_WIDTH + (wantedWidth - NEW_ORDERS_WIDTH) * flPercent); |
|
|
|
GetBounds( x, y, w, h ); |
|
|
|
m_flAnimCounter += gpGlobals->frametime; |
|
if( m_flAnimCounter >= NEW_ORDER_ANIM_DURATION ) |
|
{ |
|
SetBounds( ORDERS_RIGHT - wantedWidth, y, wantedWidth, h ); |
|
} |
|
else |
|
{ |
|
SetBounds( ORDERS_RIGHT - newWidth, y, newWidth, h ); |
|
} |
|
} |
|
} |
|
|
|
virtual void PaintBackground() |
|
{ |
|
// BaseClass::PaintBackground(); |
|
|
|
// Draw our background. |
|
int x, y, w, h; |
|
GetBounds( x, y, w, h ); |
|
|
|
vgui::surface()->DrawSetColor( Color( 0, 0, 0, 160 ) ); |
|
vgui::surface()->DrawFilledRect( 0, 0, w, h ); |
|
|
|
vgui::surface()->DrawSetColor( Color( 63, 63, 63, 255 ) ); |
|
vgui::surface()->DrawOutlinedRect( 0, 0, w, h ); |
|
} |
|
|
|
public: |
|
float m_flAnimCounter; |
|
}; |
|
|
|
|
|
class CMinimapOrderPanel : public CMinimapTraceBitmapPanel |
|
{ |
|
DECLARE_CLASS( CMinimapOrderPanel, CMinimapTraceBitmapPanel ); |
|
|
|
public: |
|
CMinimapOrderPanel( vgui::Panel *parent, const char *panelName ) |
|
: BaseClass( parent, "CMinimapOrderPanel" ) |
|
{ |
|
} |
|
virtual bool Init( KeyValues* pKeyValues, MinimapInitData_t* pInitData ); |
|
virtual void OnTick(); |
|
virtual void Paint( ); |
|
|
|
private: |
|
C_Order *m_pOrder; |
|
}; |
|
|
|
|
|
DECLARE_MINIMAP_FACTORY( CMinimapOrderPanel, "minimap_order_panel" ); |
|
|
|
bool CMinimapOrderPanel::Init( KeyValues* pKeyValues, MinimapInitData_t* pInitData ) |
|
{ |
|
m_pOrder = dynamic_cast<C_Order*>(pInitData->m_pEntity); |
|
if (!m_pOrder) |
|
return false; |
|
|
|
if (!BaseClass::Init( pKeyValues, pInitData )) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// called when we're ticked... |
|
//----------------------------------------------------------------------------- |
|
void CMinimapOrderPanel::OnTick() |
|
{ |
|
// NOTE: Do *not* chain down the the base OnTick; it's going to do |
|
// a totally different computation that will conflict with ours |
|
Assert( m_pOrder ); |
|
if( m_pOrder->GetTarget() <= 0 ) |
|
{ |
|
SetVisible(false); |
|
return; |
|
} |
|
|
|
C_BaseEntity *pTarget = ClientEntityList().GetEnt( m_pOrder->GetTarget() ); |
|
if( !pTarget ) |
|
{ |
|
SetVisible(false); |
|
return; |
|
} |
|
|
|
SetEntity( pTarget ); |
|
|
|
// Now that we're attached to the correct target, compute position! |
|
BaseClass::OnTick(); |
|
} |
|
|
|
|
|
void CMinimapOrderPanel::Paint( ) |
|
{ |
|
Assert( m_pOrder ); |
|
|
|
if( m_pOrder->GetTarget() <= 0 ) |
|
return; |
|
|
|
C_BaseEntity *pTarget = ClientEntityList().GetEnt( m_pOrder->GetTarget() ); |
|
if( !pTarget ) |
|
return; |
|
|
|
g_pMatSystemSurface->DisableClipping( true ); |
|
|
|
static float flStrobeDuration = 0.5; |
|
float flShade = sin( gpGlobals->curtime * M_PI / flStrobeDuration ) * 0.5f + 0.5f; |
|
|
|
Color color(255*flShade, 0, 0, 255); |
|
m_Image.SetColor( color ); |
|
m_Image.Paint(); |
|
|
|
g_pMatSystemSurface->DisableClipping( false ); |
|
} |
|
|
|
|
|
|
|
enum GetTargetDescriptionType_t |
|
{ |
|
GETDESC_RESOURCEZONE=0, |
|
GETDESC_OBJECT |
|
}; |
|
|
|
char* GetTargetDescription( int entindex, GetTargetDescriptionType_t type ) |
|
{ |
|
static char szDesc[128]; |
|
szDesc[0]=0; |
|
|
|
// Order target |
|
if ( entindex ) |
|
{ |
|
C_BaseEntity *pEnt = cl_entitylist->GetEnt( entindex ); |
|
if ( pEnt ) |
|
{ |
|
if( type == GETDESC_RESOURCEZONE ) |
|
{ |
|
C_ResourceZone *pZone = dynamic_cast<C_ResourceZone*>(pEnt); |
|
if ( pZone ) |
|
Q_strncpy( szDesc, pZone->GetTargetDescription(), sizeof( szDesc ) ); |
|
} |
|
else if( type == GETDESC_OBJECT ) |
|
{ |
|
C_BaseObject *pObj = dynamic_cast<C_BaseObject*>( pEnt ); |
|
if( pObj ) |
|
Q_strncpy( szDesc, pObj->GetTargetDescription(), sizeof( szDesc ) ); |
|
} |
|
} |
|
} |
|
|
|
return szDesc; |
|
} |
|
|
|
|
|
IMPLEMENT_CLIENTCLASS_DT(C_Order, DT_Order, COrder) |
|
RecvPropInt( RECVINFO(m_iPriority) ), |
|
RecvPropInt( RECVINFO(m_iOrderType) ), |
|
RecvPropInt( RECVINFO(m_iTargetEntIndex) ), |
|
END_RECV_TABLE() |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
C_Order::C_Order( void ) |
|
{ |
|
m_nHintID = TF_HINT_UNDEFINED; |
|
|
|
m_pNameLabel = NULL; |
|
|
|
CONSTRUCT_MINIMAP_PANEL( "minimap_order", MINIMAP_PERSONAL_ORDERS ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
C_Order::~C_Order( void ) |
|
{ |
|
RemoveOrder(); |
|
|
|
if( C_BaseTFPlayer::GetLocalPlayer() ) |
|
C_BaseTFPlayer::GetLocalPlayer()->RemoveOrderTarget(); |
|
|
|
|
|
if ( m_nHintID != TF_HINT_UNDEFINED ) |
|
{ |
|
DestroyGlobalHint( m_nHintID ); |
|
} |
|
} |
|
|
|
void C_Order::ClientThink( void ) |
|
{ |
|
BaseClass::ClientThink(); |
|
|
|
if ( m_nHintID != TF_HINT_UNDEFINED ) |
|
{ |
|
switch ( m_iOrderType ) |
|
{ |
|
case ORDER_REPAIR: |
|
m_nHintID = TF_HINT_REPAIROBJECT; |
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
|
|
if ( m_nHintID != TF_HINT_UNDEFINED ) |
|
{ |
|
CreateGlobalHint_Panel( m_pNameLabel, m_nHintID, NULL, index ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void C_Order::OnDataChanged( DataUpdateType_t updateType ) |
|
{ |
|
BaseClass::OnDataChanged( updateType ); |
|
|
|
C_BaseTFPlayer *pPlayer = C_BaseTFPlayer::GetLocalPlayer(); |
|
pPlayer->SetPersonalOrder( this ); |
|
|
|
// Update us if we've changed |
|
if( updateType == DATA_UPDATE_CREATED ) |
|
{ |
|
CreateStatus( GetClientModeNormal()->GetViewport() ); |
|
} |
|
else |
|
{ |
|
GetHudOrderList()->RecalculateOrderList(); |
|
UpdateStatus(); |
|
} |
|
|
|
if( m_iTargetEntIndex > 0 ) |
|
{ |
|
C_BaseEntity *pTarget = ClientEntityList().GetEnt( m_iTargetEntIndex ); |
|
m_OverlayPanel.Activate( pTarget, "personal_order", true ); |
|
} |
|
|
|
if ( (updateType == DATA_UPDATE_CREATED) && ( m_nHintID != TF_HINT_UNDEFINED ) ) |
|
{ |
|
// Wait for animation to fly all the way in |
|
SetNextClientThink( gpGlobals->curtime + NEW_ORDER_ANIM_DURATION + 0.25f ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Clean up a removed order |
|
//----------------------------------------------------------------------------- |
|
void C_Order::RemoveOrder( void ) |
|
{ |
|
m_OverlayPanel.RemoveOverlay(); |
|
|
|
DestroyStatus(); |
|
|
|
if ( m_pNameLabel ) |
|
{ |
|
delete m_pNameLabel; |
|
m_pNameLabel = NULL; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get a text description of this order |
|
//----------------------------------------------------------------------------- |
|
void C_Order::GetDescription( char *pDest, int bufferSize ) |
|
{ |
|
char targetDesc[512]; |
|
GetTargetDescription( targetDesc, sizeof( targetDesc ) ); |
|
|
|
switch ( m_iOrderType ) |
|
{ |
|
case ORDER_ATTACK: |
|
Q_snprintf( pDest, bufferSize, "Attack %s", targetDesc ); |
|
break; |
|
|
|
case ORDER_DEFEND: |
|
Q_snprintf( pDest, bufferSize, "Defend %s", targetDesc ); |
|
break; |
|
|
|
case ORDER_CAPTURE: |
|
Q_snprintf( pDest, bufferSize, "Capture %s", targetDesc ); |
|
break; |
|
|
|
default: |
|
Q_snprintf( pDest, bufferSize, "INVALID" ); |
|
break; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get a text description for the target of this order |
|
//----------------------------------------------------------------------------- |
|
void C_Order::GetTargetDescription( char *pDest, int bufferSize ) |
|
{ |
|
pDest[0] = 0; |
|
|
|
if ( !m_iTargetEntIndex ) |
|
return; |
|
|
|
C_BaseEntity *pEnt = cl_entitylist->GetEnt( m_iTargetEntIndex ); |
|
if ( !pEnt ) |
|
return; |
|
|
|
C_ResourceZone *pZone = dynamic_cast<C_ResourceZone*>(pEnt); |
|
if ( pZone ) |
|
{ |
|
Q_strncpy( pDest, pZone->GetTargetDescription(), bufferSize ); |
|
} |
|
else |
|
{ |
|
C_BaseObject *pObj = dynamic_cast<C_BaseObject*>( pEnt ); |
|
if( pObj ) |
|
Q_strncpy( pDest, pObj->GetTargetDescription(), bufferSize ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Create all elements needed in a status panel for this order |
|
//----------------------------------------------------------------------------- |
|
void C_Order::CreateStatus( vgui::Panel *pParent ) |
|
{ |
|
// If we already have our elements, we're just moving. |
|
if ( m_pNameLabel ) |
|
{ |
|
m_pNameLabel->SetParent( pParent ); |
|
} |
|
else |
|
{ |
|
m_pNameLabel = new COrderLabel( pParent, "NameLabel", "Temp" ); |
|
m_pNameLabel->SetBounds( ORDERS_LEFT, ORDERS_TOP, NEW_ORDERS_WIDTH, ORDERS_ELEMENT_HEIGHT ); |
|
m_pNameLabel->SetAutoDelete( false ); |
|
m_pNameLabel->SetPaintBackgroundEnabled( true ); |
|
m_pNameLabel->SetFgColor( Color( 0, 0, 0, 255 ) ); |
|
m_pNameLabel->SetContentAlignment( vgui::Label::a_east ); |
|
m_pNameLabel->SetTextInset( -2, 0 ); |
|
} |
|
|
|
UpdateStatus(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Destroy all elements in the status panel for this order |
|
//----------------------------------------------------------------------------- |
|
void C_Order::DestroyStatus( void ) |
|
{ |
|
if ( m_pNameLabel ) |
|
{ |
|
delete m_pNameLabel; |
|
m_pNameLabel = NULL; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Update all elements in the status panel for this order |
|
//----------------------------------------------------------------------------- |
|
void C_Order::UpdateStatus( void ) |
|
{ |
|
if ( m_pNameLabel ) |
|
{ |
|
char desc[512]; |
|
GetDescription( desc, sizeof( desc ) ); |
|
|
|
m_pNameLabel->SetText( desc ); |
|
m_pNameLabel->m_flAnimCounter = 0; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Return true if this order wants a target reticle created around it's target |
|
//----------------------------------------------------------------------------- |
|
bool C_Order::ShouldDrawReticle( void ) |
|
{ |
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int C_Order::GetPriority( void ) |
|
{ |
|
return m_iPriority; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int C_Order::GetType( void ) |
|
{ |
|
return m_iOrderType; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int C_Order::GetTarget( void ) |
|
{ |
|
return m_iTargetEntIndex; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Return true if this order is a personal one for this player |
|
//----------------------------------------------------------------------------- |
|
bool C_Order::IsPersonalOrder( void ) |
|
{ |
|
return (GetPriority() == 0); |
|
} |
|
|
|
|