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.
427 lines
11 KiB
427 lines
11 KiB
//========= 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(); |
|
} |