Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "cheatcodes.h"
  7. #include "cmd.h"
  8. #include "KeyValues.h"
  9. #include "filesystem.h"
  10. #include "tier2/tier2.h"
  11. #include "inputsystem/iinputsystem.h"
  12. #include "host.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. //=========================================================
  16. // Cheat Codes
  17. //=========================================================
  18. #define CHEAT_NAME_MAX_LEN 32
  19. #define CHEAT_CODE_MAX_LEN 10
  20. #define CHEAT_COMMAND_MAX_LEN 128
  21. static ButtonCode_t s_pKeyLog[CHEAT_CODE_MAX_LEN];
  22. static int s_nKeyLogIndex = 0;
  23. struct CheatCodeData_t
  24. {
  25. char szName[ CHEAT_NAME_MAX_LEN ];
  26. bool bDevOnly;
  27. int iCodeLength;
  28. ButtonCode_t pButtonCodes[ CHEAT_CODE_MAX_LEN ];
  29. char szCommand[ CHEAT_COMMAND_MAX_LEN ];
  30. };
  31. static CUtlVector<CheatCodeData_t> s_CheatCodeCommands;
  32. void ClearCheatCommands( void )
  33. {
  34. s_CheatCodeCommands.RemoveAll();
  35. }
  36. void ReadCheatCommandsFromFile( char *pchFileName )
  37. {
  38. KeyValues *pCheatCodeKeys = new KeyValues( "cheat_codes" );
  39. pCheatCodeKeys->LoadFromFile( g_pFullFileSystem, pchFileName, NULL );
  40. KeyValues *pKey = NULL;
  41. for ( pKey = pCheatCodeKeys->GetFirstTrueSubKey(); pKey; pKey = pKey->GetNextTrueSubKey() )
  42. {
  43. int iCheat = s_CheatCodeCommands.AddToTail();
  44. CheatCodeData_t *pNewCheatCode = &(s_CheatCodeCommands[ iCheat ]);
  45. Q_strncpy( pNewCheatCode->szName, pKey->GetName(), CHEAT_NAME_MAX_LEN ); // Get the name
  46. pNewCheatCode->bDevOnly = ( pKey->GetInt( "dev", 0 ) != 0 ); // Get developer only flag
  47. pNewCheatCode->iCodeLength = 0; // Start at zero code elements
  48. Q_strncpy( pNewCheatCode->szCommand, pKey->GetString( "command", "echo \"Cheat code has no command!\"" ), CHEAT_COMMAND_MAX_LEN );
  49. KeyValues *pSubKey = NULL;
  50. for ( pSubKey = pKey->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey() )
  51. {
  52. const char *pchType = pSubKey->GetName();
  53. if ( Q_strcmp( pchType, "code" ) == 0 )
  54. {
  55. AssertMsg( ( pNewCheatCode->iCodeLength < CHEAT_NAME_MAX_LEN ), "Cheat code elements exceeded max!" );
  56. pNewCheatCode->pButtonCodes[ pNewCheatCode->iCodeLength ] = g_pInputSystem->StringToButtonCode( pSubKey->GetString() );
  57. ++pNewCheatCode->iCodeLength;
  58. }
  59. }
  60. if ( pNewCheatCode->iCodeLength < CHEAT_NAME_MAX_LEN )
  61. {
  62. // If it's activation is a subsequence of another cheat, the longer cheat can't be activated!
  63. DevWarning( "Cheat code \"%s\" has less than %i code elements!", pKey->GetName(), CHEAT_NAME_MAX_LEN );
  64. }
  65. }
  66. }
  67. //---------------------------------------------------------
  68. //---------------------------------------------------------
  69. void ResetKeyLogging()
  70. {
  71. s_nKeyLogIndex = 0;
  72. }
  73. //---------------------------------------------------------
  74. //---------------------------------------------------------
  75. void LogKeyPress( ButtonCode_t code )
  76. {
  77. if ( s_nKeyLogIndex < CHEAT_CODE_MAX_LEN )
  78. {
  79. // Log isn't full, so add it in the next spot
  80. s_pKeyLog[ s_nKeyLogIndex ] = code;
  81. ++s_nKeyLogIndex;
  82. return;
  83. }
  84. // Log is full so shift all data to the previous bucket
  85. int i;
  86. for ( i = 0; i < CHEAT_CODE_MAX_LEN - 1; ++i )
  87. {
  88. s_pKeyLog[ i ] = s_pKeyLog[ i + 1 ];
  89. }
  90. // Log into the last bucket
  91. s_pKeyLog[ i ] = code;
  92. }
  93. //---------------------------------------------------------
  94. //---------------------------------------------------------
  95. void CheckCheatCodes()
  96. {
  97. // Loop through all cheat codes
  98. int iNumCheatCodes = s_CheatCodeCommands.Count();
  99. for ( int iCheatCode = 0; iCheatCode < iNumCheatCodes; ++iCheatCode )
  100. {
  101. CheatCodeData_t *pCheatCode = &(s_CheatCodeCommands[ iCheatCode ]);
  102. if ( pCheatCode->bDevOnly && !developer.GetBool() )
  103. continue; // This cheat is only allowed in developer mode
  104. int iLogIndex = s_nKeyLogIndex - pCheatCode->iCodeLength; // Check code against the back chunk of the log
  105. if ( iLogIndex < 0 )
  106. continue; // There's less codes in the log than we need
  107. int iCode = 0;
  108. while ( iCode < pCheatCode->iCodeLength && pCheatCode->pButtonCodes[ iCode ] == s_pKeyLog[ iLogIndex ] )
  109. {
  110. ++iCode;
  111. ++iLogIndex;
  112. }
  113. if ( iCode == pCheatCode->iCodeLength )
  114. {
  115. // Every part of the code was correct
  116. DevMsg( "Cheat code \"%s\" activated!", pCheatCode->szName );
  117. Cbuf_AddText( "sv_cheats 1\n" );
  118. Cbuf_AddText( pCheatCode->szCommand );
  119. Cbuf_AddText( "\n" );
  120. ResetKeyLogging();
  121. return;
  122. }
  123. }
  124. }