mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-10 10:49:35 +00:00
1
This commit is contained in:
@@ -0,0 +1,427 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "c_tf_hintmanager.h"
|
||||
#include "c_tf_basehint.h"
|
||||
#include <KeyValues.h>
|
||||
#include "filesystem.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
// Global off switch for hint system
|
||||
static ConVar tf2_hintsystem( "tf2_hintsystem", "0", 0, "Enable interface hints in TF2." );
|
||||
static C_TFHintManager *g_pHintManager = NULL;
|
||||
|
||||
#define HINT_DISPLAY_STATS_FILE "scripts/hintdisplaystats.txt"
|
||||
|
||||
static float g_flLastEscapeKeyTime = -1.0f;
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Helper to create panel in center and then shift toward right edge of screen
|
||||
// Input : *panel -
|
||||
// Output : static void
|
||||
//-----------------------------------------------------------------------------
|
||||
static void PositionPanel( C_TFBaseHint *panel )
|
||||
{
|
||||
int w, h;
|
||||
panel->GetSize( w, h );
|
||||
|
||||
int x = ( ScreenWidth() - w ) / 2;
|
||||
int y = ( ScreenHeight() - h ) / 2;
|
||||
|
||||
panel->SetPos( x, y );
|
||||
|
||||
panel->SetDesiredPosition( ScreenWidth() - w - 10, y - 75 );
|
||||
}
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT_NOBASE(C_TFHintManager, DT_TFHintManager, CTFHintManager)
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_TFHintManager::C_TFHintManager( void )
|
||||
{
|
||||
g_pHintManager = this;
|
||||
|
||||
m_pkvHintSystem = new KeyValues( "HintSystem" );
|
||||
if ( m_pkvHintSystem )
|
||||
{
|
||||
bool valid = m_pkvHintSystem->LoadFromFile( filesystem, "scripts//hintsystem.txt" );
|
||||
if ( !valid )
|
||||
{
|
||||
m_pkvHintSystem->deleteThis();
|
||||
m_pkvHintSystem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
m_pkvHintDisplayStats = new KeyValues( "HintDisplayStats" );
|
||||
if ( m_pkvHintDisplayStats )
|
||||
{
|
||||
m_pkvHintDisplayStats->LoadFromFile( filesystem, HINT_DISPLAY_STATS_FILE );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : KeyValues
|
||||
//-----------------------------------------------------------------------------
|
||||
KeyValues *C_TFHintManager::GetHintKeyValues( void )
|
||||
{
|
||||
return m_pkvHintSystem;
|
||||
}
|
||||
|
||||
KeyValues *C_TFHintManager::GetHintDisplayStats( void )
|
||||
{
|
||||
return m_pkvHintDisplayStats;
|
||||
}
|
||||
|
||||
void C_TFHintManager::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
// Think right away
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
SetNextClientThink( 0.0f );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Remove complete hints, and activate next highest priority hint
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_TFHintManager::ClientThink( void )
|
||||
{
|
||||
SetNextClientThink( gpGlobals->curtime + 1.0 );
|
||||
|
||||
int i;
|
||||
int highestPriority = -1;
|
||||
C_TFBaseHint *best = NULL;
|
||||
bool anyVisible = false;
|
||||
|
||||
// See if any of the hints are completed, otherwise, store off the highest priority one
|
||||
for ( i = m_aHints.Size() - 1; i >= 0; i-- )
|
||||
{
|
||||
C_TFBaseHint *hint = m_aHints[ i ];
|
||||
|
||||
// See if it should just be deleted
|
||||
if ( hint && hint->GetCompleted() )
|
||||
{
|
||||
m_aHints.Remove( i );
|
||||
delete hint;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( hint->IsVisible() )
|
||||
{
|
||||
anyVisible = true;
|
||||
}
|
||||
|
||||
if ( !best || ( hint->GetPriority() > highestPriority ) )
|
||||
{
|
||||
highestPriority = hint->GetPriority();
|
||||
best = hint;
|
||||
}
|
||||
}
|
||||
|
||||
// Last hint finished, show next best one
|
||||
if ( !anyVisible )
|
||||
{
|
||||
// Now hide all but best one
|
||||
for ( i = 0; i < m_aHints.Size(); i++ )
|
||||
{
|
||||
C_TFBaseHint *hint = m_aHints[ i ];
|
||||
hint->SetVisible( hint == best );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : playerIndex -
|
||||
// hintID -
|
||||
// priority -
|
||||
// entityIndex -
|
||||
//-----------------------------------------------------------------------------
|
||||
C_TFBaseHint *C_TFHintManager::AddHint( int hintID, const char *subsection, int entityIndex, int maxduplicates )
|
||||
{
|
||||
if ( !tf2_hintsystem.GetBool() )
|
||||
return NULL;
|
||||
|
||||
// Don't add the same hint more than once unless maxduplicates >= 1 has been specifically requested
|
||||
int count = CountInstancesOfHintID( hintID );
|
||||
if ( count > maxduplicates )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
C_TFBaseHint *hint = C_TFBaseHint::CreateHint( hintID, subsection, entityIndex );
|
||||
if ( hint )
|
||||
{
|
||||
// Force it to compute it's exact size
|
||||
hint->PerformLayout();
|
||||
|
||||
PositionPanel( hint );
|
||||
|
||||
m_aHints.AddToTail( hint );
|
||||
}
|
||||
|
||||
return hint;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_TFHintManager::ClearHints( void )
|
||||
{
|
||||
for ( int i = 0; i < m_aHints.Size(); i++ )
|
||||
{
|
||||
C_TFBaseHint *hint = m_aHints[ i ];
|
||||
delete hint;
|
||||
}
|
||||
|
||||
m_aHints.RemoveAll();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : playerIndex -
|
||||
// hintID -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_TFHintManager::CompleteHint( int hintID, bool visibleOnly )
|
||||
{
|
||||
for ( int i = m_aHints.Size() - 1; i >= 0; i-- )
|
||||
{
|
||||
C_TFBaseHint *hint = m_aHints[ i ];
|
||||
if ( !hint )
|
||||
continue;
|
||||
|
||||
if ( hint->GetID() != hintID )
|
||||
continue;
|
||||
|
||||
if ( visibleOnly && !hint->IsVisible() )
|
||||
continue;
|
||||
|
||||
delete hint;
|
||||
m_aHints.Remove( i );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : playerIndex -
|
||||
// hintID -
|
||||
// Output : Number of instances in list
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_TFHintManager::CountInstancesOfHintID( int hintID )
|
||||
{
|
||||
int c = 0;
|
||||
for ( int i = m_aHints.Size() - 1; i >= 0; i-- )
|
||||
{
|
||||
C_TFBaseHint *hint = m_aHints[ i ];
|
||||
if ( hint && hint->GetID() == hintID )
|
||||
{
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : playerIndex -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_TFHintManager::GetCurrentHintID( void )
|
||||
{
|
||||
for ( int i = m_aHints.Size() - 1; i >= 0; i-- )
|
||||
{
|
||||
C_TFBaseHint *hint = m_aHints[ i ];
|
||||
if ( hint && hint->IsVisible() )
|
||||
{
|
||||
return hint->GetID();
|
||||
}
|
||||
}
|
||||
|
||||
return TF_HINT_UNDEFINED;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_TFHintManager::ResetDisplayStats( void )
|
||||
{
|
||||
if ( !m_pkvHintDisplayStats )
|
||||
{
|
||||
Assert( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
KeyValues *kv = m_pkvHintDisplayStats->GetFirstSubKey();
|
||||
while ( kv )
|
||||
{
|
||||
KeyValues *subKey = kv->GetFirstSubKey();
|
||||
if ( subKey && stricmp( subKey->GetName(), "times_shown") )
|
||||
{
|
||||
while ( subKey )
|
||||
{
|
||||
subKey->SetString( "times_shown", "0" );
|
||||
subKey = subKey->GetNextKey();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kv->SetString( "times_shown", "0" );
|
||||
}
|
||||
|
||||
kv = kv->GetNextKey();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : hintid -
|
||||
// 100 -
|
||||
// 1 -
|
||||
// -1 -
|
||||
//-----------------------------------------------------------------------------
|
||||
C_TFBaseHint *CreateGlobalHint( int hintid, const char *subsection /*=NULL*/, int entity /*= -1*/, int maxduplicates /*=0*/ )
|
||||
{
|
||||
if ( !g_pHintManager )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_pHintManager->AddHint( hintid, subsection, entity, maxduplicates );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : hintid -
|
||||
// 100 -
|
||||
// 1 -
|
||||
// -1 -
|
||||
//-----------------------------------------------------------------------------
|
||||
C_TFBaseHint *CreateGlobalHint_Panel( vgui::Panel *targetPanel, int hintid, const char *subsection /*=NULL*/, int entity /*= -1*/, int maxduplicates /*=0*/ )
|
||||
{
|
||||
C_TFBaseHint *hint = CreateGlobalHint( hintid, subsection, entity, maxduplicates );
|
||||
if ( hint )
|
||||
{
|
||||
// Find an appropriate position near the panel
|
||||
hint->SetHintTarget( targetPanel );
|
||||
}
|
||||
return hint;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Trap the escape key when a hint is showing
|
||||
// Output : Returns true if the escape key was swallowed by the hint system
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Hitting escape twice withing this amount of seconds will clear all hints pending
|
||||
#define ENTER_DOUBLETAP_TIME 1.0f
|
||||
|
||||
bool HintSystemEscapeKey( void )
|
||||
{
|
||||
if ( !g_pHintManager )
|
||||
return false;
|
||||
|
||||
int hintID = g_pHintManager->GetCurrentHintID();
|
||||
if ( hintID != TF_HINT_UNDEFINED )
|
||||
{
|
||||
bool killall = false;
|
||||
|
||||
float curtime = gpGlobals->curtime;
|
||||
float dt = curtime - g_flLastEscapeKeyTime;
|
||||
|
||||
if ( dt < ENTER_DOUBLETAP_TIME )
|
||||
{
|
||||
killall = true;
|
||||
}
|
||||
|
||||
g_flLastEscapeKeyTime = curtime;
|
||||
|
||||
if ( killall )
|
||||
{
|
||||
g_pHintManager->ClearHints();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pHintManager->CompleteHint( hintID, true );
|
||||
}
|
||||
// Swallow the escape key
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : hindid -
|
||||
//-----------------------------------------------------------------------------
|
||||
void DestroyGlobalHint( int hintid )
|
||||
{
|
||||
if ( !g_pHintManager )
|
||||
return;
|
||||
|
||||
g_pHintManager->CompleteHint( hintid, false );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : KeyValues
|
||||
//-----------------------------------------------------------------------------
|
||||
KeyValues *GetHintKeyValues( void )
|
||||
{
|
||||
if ( !g_pHintManager )
|
||||
return NULL;
|
||||
|
||||
return g_pHintManager->GetHintKeyValues();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : KeyValues
|
||||
//-----------------------------------------------------------------------------
|
||||
KeyValues *GetHintDisplayStats( void )
|
||||
{
|
||||
if ( !g_pHintManager )
|
||||
return NULL;
|
||||
|
||||
return g_pHintManager->GetHintDisplayStats();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void ResetDisplayStats( void )
|
||||
{
|
||||
if ( g_pHintManager )
|
||||
{
|
||||
g_pHintManager->ResetDisplayStats();
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand tf2_hintreset( "tf2_hintreset", ResetDisplayStats, 0, FCVAR_CHEAT );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_TFHintManager::~C_TFHintManager( void )
|
||||
{
|
||||
ClearHints();
|
||||
g_pHintManager = NULL;
|
||||
m_pkvHintSystem->deleteThis();
|
||||
if ( m_pkvHintDisplayStats )
|
||||
{
|
||||
m_pkvHintDisplayStats->SaveToFile( filesystem, HINT_DISPLAY_STATS_FILE );
|
||||
}
|
||||
m_pkvHintDisplayStats->deleteThis();
|
||||
}
|
||||
Reference in New Issue
Block a user