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.
156 lines
4.4 KiB
156 lines
4.4 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//===========================================================================// |
|
|
|
#include "cheatcodes.h" |
|
#include "cmd.h" |
|
#include "KeyValues.h" |
|
#include "filesystem.h" |
|
#include "tier2/tier2.h" |
|
#include "inputsystem/iinputsystem.h" |
|
#include "host.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
|
|
//========================================================= |
|
// Cheat Codes |
|
//========================================================= |
|
#define CHEAT_NAME_MAX_LEN 32 |
|
#define CHEAT_CODE_MAX_LEN 10 |
|
#define CHEAT_COMMAND_MAX_LEN 128 |
|
static ButtonCode_t s_pKeyLog[CHEAT_CODE_MAX_LEN]; |
|
static int s_nKeyLogIndex = 0; |
|
|
|
|
|
struct CheatCodeData_t |
|
{ |
|
char szName[ CHEAT_NAME_MAX_LEN ]; |
|
|
|
bool bDevOnly; |
|
|
|
int iCodeLength; |
|
ButtonCode_t pButtonCodes[ CHEAT_CODE_MAX_LEN ]; |
|
|
|
char szCommand[ CHEAT_COMMAND_MAX_LEN ]; |
|
}; |
|
|
|
|
|
static CUtlVector<CheatCodeData_t> s_CheatCodeCommands; |
|
|
|
|
|
void ClearCheatCommands( void ) |
|
{ |
|
s_CheatCodeCommands.RemoveAll(); |
|
} |
|
|
|
void ReadCheatCommandsFromFile( char *pchFileName ) |
|
{ |
|
KeyValues *pCheatCodeKeys = new KeyValues( "cheat_codes" ); |
|
pCheatCodeKeys->LoadFromFile( g_pFullFileSystem, pchFileName, NULL ); |
|
|
|
KeyValues *pKey = NULL; |
|
for ( pKey = pCheatCodeKeys->GetFirstTrueSubKey(); pKey; pKey = pKey->GetNextTrueSubKey() ) |
|
{ |
|
int iCheat = s_CheatCodeCommands.AddToTail(); |
|
CheatCodeData_t *pNewCheatCode = &(s_CheatCodeCommands[ iCheat ]); |
|
|
|
Q_strncpy( pNewCheatCode->szName, pKey->GetName(), CHEAT_NAME_MAX_LEN ); // Get the name |
|
pNewCheatCode->bDevOnly = ( pKey->GetInt( "dev", 0 ) != 0 ); // Get developer only flag |
|
pNewCheatCode->iCodeLength = 0; // Start at zero code elements |
|
Q_strncpy( pNewCheatCode->szCommand, pKey->GetString( "command", "echo \"Cheat code has no command!\"" ), CHEAT_COMMAND_MAX_LEN ); |
|
|
|
KeyValues *pSubKey = NULL; |
|
for ( pSubKey = pKey->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey() ) |
|
{ |
|
const char *pchType = pSubKey->GetName(); |
|
if ( Q_strcmp( pchType, "code" ) == 0 ) |
|
{ |
|
AssertMsg( ( pNewCheatCode->iCodeLength < CHEAT_NAME_MAX_LEN ), "Cheat code elements exceeded max!" ); |
|
|
|
pNewCheatCode->pButtonCodes[ pNewCheatCode->iCodeLength ] = g_pInputSystem->StringToButtonCode( pSubKey->GetString() ); |
|
++pNewCheatCode->iCodeLength; |
|
} |
|
} |
|
|
|
if ( pNewCheatCode->iCodeLength < CHEAT_NAME_MAX_LEN ) |
|
{ |
|
// If it's activation is a subsequence of another cheat, the longer cheat can't be activated! |
|
DevWarning( "Cheat code \"%s\" has less than %i code elements!", pKey->GetName(), CHEAT_NAME_MAX_LEN ); |
|
} |
|
} |
|
} |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
void ResetKeyLogging() |
|
{ |
|
s_nKeyLogIndex = 0; |
|
} |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
void LogKeyPress( ButtonCode_t code ) |
|
{ |
|
if ( s_nKeyLogIndex < CHEAT_CODE_MAX_LEN ) |
|
{ |
|
// Log isn't full, so add it in the next spot |
|
s_pKeyLog[ s_nKeyLogIndex ] = code; |
|
++s_nKeyLogIndex; |
|
return; |
|
} |
|
|
|
// Log is full so shift all data to the previous bucket |
|
int i; |
|
for ( i = 0; i < CHEAT_CODE_MAX_LEN - 1; ++i ) |
|
{ |
|
s_pKeyLog[ i ] = s_pKeyLog[ i + 1 ]; |
|
} |
|
|
|
// Log into the last bucket |
|
s_pKeyLog[ i ] = code; |
|
} |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
void CheckCheatCodes() |
|
{ |
|
// Loop through all cheat codes |
|
int iNumCheatCodes = s_CheatCodeCommands.Count(); |
|
for ( int iCheatCode = 0; iCheatCode < iNumCheatCodes; ++iCheatCode ) |
|
{ |
|
CheatCodeData_t *pCheatCode = &(s_CheatCodeCommands[ iCheatCode ]); |
|
|
|
if ( pCheatCode->bDevOnly && !developer.GetBool() ) |
|
continue; // This cheat is only allowed in developer mode |
|
|
|
int iLogIndex = s_nKeyLogIndex - pCheatCode->iCodeLength; // Check code against the back chunk of the log |
|
|
|
if ( iLogIndex < 0 ) |
|
continue; // There's less codes in the log than we need |
|
|
|
int iCode = 0; |
|
|
|
while ( iCode < pCheatCode->iCodeLength && pCheatCode->pButtonCodes[ iCode ] == s_pKeyLog[ iLogIndex ] ) |
|
{ |
|
++iCode; |
|
++iLogIndex; |
|
} |
|
|
|
if ( iCode == pCheatCode->iCodeLength ) |
|
{ |
|
// Every part of the code was correct |
|
DevMsg( "Cheat code \"%s\" activated!", pCheatCode->szName ); |
|
|
|
Cbuf_AddText( "sv_cheats 1\n" ); |
|
Cbuf_AddText( pCheatCode->szCommand ); |
|
Cbuf_AddText( "\n" ); |
|
|
|
ResetKeyLogging(); |
|
return; |
|
} |
|
} |
|
}
|
|
|