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.

247 lines
6.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Weapon data file parsing, shared by game & client dlls.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include <KeyValues.h>
  9. #include <tier0/mem.h>
  10. #include "filesystem.h"
  11. #include "utldict.h"
  12. #include "ammodef.h"
  13. #include "playerclass_info_parse.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. static CUtlDict< FilePlayerClassInfo_t*, unsigned short > m_PlayerClassInfoDatabase;
  17. #define MAX_PLAYERCLASSES 32
  18. #ifdef _DEBUG
  19. // used to track whether or not two player classes have been mistakenly assigned the same slot
  20. bool g_bUsedPlayerClassSlots[MAX_PLAYERCLASSES] = { 0 };
  21. #endif
  22. #ifdef DEBUG
  23. void CC_ReloadPlayerClasses_f (void)
  24. {
  25. //ResetFilePlayerClassInfoDatabase();
  26. }
  27. static ConCommand dod_reloadplayerclasses("dod_reloadplayerclasses", CC_ReloadPlayerClasses_f, "Reset player class info cache" );
  28. #endif
  29. //-----------------------------------------------------------------------------
  30. // Purpose:
  31. // Input : *name -
  32. // Output : FilePlayerClassInfo_t
  33. //-----------------------------------------------------------------------------
  34. static PLAYERCLASS_FILE_INFO_HANDLE FindPlayerClassInfoSlot( const char *name )
  35. {
  36. // Complain about duplicately defined metaclass names...
  37. unsigned short lookup = m_PlayerClassInfoDatabase.Find( name );
  38. if ( lookup != m_PlayerClassInfoDatabase.InvalidIndex() )
  39. {
  40. return lookup;
  41. }
  42. FilePlayerClassInfo_t *insert = CreatePlayerClassInfo();
  43. lookup = m_PlayerClassInfoDatabase.Insert( name, insert );
  44. Assert( lookup != m_PlayerClassInfoDatabase.InvalidIndex() );
  45. return lookup;
  46. }
  47. // Find a class slot, assuming the weapon's data has already been loaded.
  48. PLAYERCLASS_FILE_INFO_HANDLE LookupPlayerClassInfoSlot( const char *name )
  49. {
  50. return m_PlayerClassInfoDatabase.Find( name );
  51. }
  52. // FIXME, handle differently?
  53. static FilePlayerClassInfo_t gNullPlayerClassInfo;
  54. //-----------------------------------------------------------------------------
  55. // Purpose:
  56. // Input : handle -
  57. // Output : FilePlayerClassInfo_t
  58. //-----------------------------------------------------------------------------
  59. FilePlayerClassInfo_t *GetFilePlayerClassInfoFromHandle( PLAYERCLASS_FILE_INFO_HANDLE handle )
  60. {
  61. if ( handle == GetInvalidPlayerClassInfoHandle() )
  62. {
  63. Assert( !"bad index into playerclass info UtlDict" );
  64. return &gNullPlayerClassInfo;
  65. }
  66. return m_PlayerClassInfoDatabase[ handle ];
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose:
  70. // Output : PLAYERCLASS_FILE_INFO_HANDLE
  71. //-----------------------------------------------------------------------------
  72. PLAYERCLASS_FILE_INFO_HANDLE GetInvalidPlayerClassInfoHandle( void )
  73. {
  74. return (PLAYERCLASS_FILE_INFO_HANDLE)m_PlayerClassInfoDatabase.InvalidIndex();
  75. }
  76. void ResetFilePlayerClassInfoDatabase( void )
  77. {
  78. m_PlayerClassInfoDatabase.PurgeAndDeleteElements();
  79. #ifdef _DEBUG
  80. memset(g_bUsedPlayerClassSlots, 0, sizeof(g_bUsedPlayerClassSlots));
  81. #endif
  82. }
  83. #ifndef _XBOX
  84. KeyValues* ReadEncryptedKVPlayerClassFile( IFileSystem *pFilesystem, const char *szFilenameWithoutExtension, const unsigned char *pICEKey )
  85. {
  86. Assert( strchr( szFilenameWithoutExtension, '.' ) == NULL );
  87. char szFullName[512];
  88. // Open the weapon data file, and abort if we can't
  89. KeyValues *pKV = new KeyValues( "PlayerClassDatafile" );
  90. Q_snprintf(szFullName,sizeof(szFullName), "%s.txt", szFilenameWithoutExtension);
  91. if ( !pKV->LoadFromFile( pFilesystem, szFullName, "GAME" ) ) // try to load the normal .txt file first
  92. {
  93. if ( pICEKey )
  94. {
  95. Q_snprintf(szFullName,sizeof(szFullName), "%s.ctx", szFilenameWithoutExtension); // fall back to the .ctx file
  96. FileHandle_t f = pFilesystem->Open( szFullName, "rb", "GAME");
  97. if (!f)
  98. {
  99. pKV->deleteThis();
  100. return NULL;
  101. }
  102. // load file into a null-terminated buffer
  103. int fileSize = pFilesystem->Size(f);
  104. char *buffer = (char*)MemAllocScratch(fileSize + 1);
  105. Assert(buffer);
  106. pFilesystem->Read(buffer, fileSize, f); // read into local buffer
  107. buffer[fileSize] = 0; // null terminate file as EOF
  108. pFilesystem->Close( f ); // close file after reading
  109. UTIL_DecodeICE( (unsigned char*)buffer, fileSize, pICEKey );
  110. bool retOK = pKV->LoadFromBuffer( szFullName, buffer, pFilesystem );
  111. MemFreeScratch();
  112. if ( !retOK )
  113. {
  114. pKV->deleteThis();
  115. return NULL;
  116. }
  117. }
  118. else
  119. {
  120. pKV->deleteThis();
  121. return NULL;
  122. }
  123. }
  124. return pKV;
  125. }
  126. #endif
  127. //-----------------------------------------------------------------------------
  128. // Purpose: Read data on weapon from script file
  129. // Output: true - if data2 successfully read
  130. // false - if data load fails
  131. //-----------------------------------------------------------------------------
  132. bool ReadPlayerClassDataFromFileForSlot( IFileSystem* pFilesystem, const char *szPlayerClassName, PLAYERCLASS_FILE_INFO_HANDLE *phandle, const unsigned char *pICEKey )
  133. {
  134. if ( !phandle )
  135. {
  136. Assert( 0 );
  137. return false;
  138. }
  139. *phandle = FindPlayerClassInfoSlot( szPlayerClassName );
  140. FilePlayerClassInfo_t *pFileInfo = GetFilePlayerClassInfoFromHandle( *phandle );
  141. Assert( pFileInfo );
  142. if ( pFileInfo->m_bParsedScript )
  143. return true;
  144. char sz[128];
  145. Q_snprintf( sz, sizeof( sz ), "scripts/playerclass_%s", szPlayerClassName );
  146. KeyValues *pKV = ReadEncryptedKVFile( pFilesystem, sz, pICEKey );
  147. if ( !pKV )
  148. return false;
  149. pFileInfo->Parse( pKV, szPlayerClassName );
  150. pKV->deleteThis();
  151. return true;
  152. }
  153. //-----------------------------------------------------------------------------
  154. // FilePlayerClassInfo_t implementation.
  155. //-----------------------------------------------------------------------------
  156. FilePlayerClassInfo_t::FilePlayerClassInfo_t()
  157. {
  158. m_bParsedScript = false;
  159. m_szPlayerClassName[0] = 0;
  160. m_szPrintName[0] = 0;
  161. m_szPlayerModel[0] = 0;
  162. m_szSelectCmd[0] = 0;
  163. }
  164. void FilePlayerClassInfo_t::Parse( KeyValues *pKeyValuesData, const char *szPlayerClassName )
  165. {
  166. // Okay, we tried at least once to look this up...
  167. m_bParsedScript = true;
  168. // Classname
  169. Q_strncpy( m_szPlayerClassName, szPlayerClassName, MAX_WEAPON_STRING );
  170. // Printable name
  171. Q_strncpy( m_szPrintName, pKeyValuesData->GetString( "printname", "!! Missing printname on Player Class" ), MAX_PLAYERCLASS_NAME_LENGTH );
  172. // Player Model
  173. Q_strncpy( m_szPlayerModel, pKeyValuesData->GetString( "playermodel", "!! Missing playermodel on Player Class" ), MAX_PLAYERCLASS_NAME_LENGTH );
  174. // Select command
  175. Q_strncpy( m_szSelectCmd, pKeyValuesData->GetString( "selectcmd", "!! Missing selectcmd on Player Class" ), 32 );
  176. #if defined(_DEBUG) && defined(HL2_CLIENT_DLL)
  177. // Use this for class select keys
  178. /*
  179. // make sure two weapons aren't in the same slot & position
  180. if (g_bUsedPlayerClassSlots[iSlot])
  181. {
  182. Msg( "Weapon slot info: %s (%d, %d)\n", szPrintName, iSlot, iPosition );
  183. Warning( "Duplicately assigned weapon to slots in selection hud\n" );
  184. }
  185. g_bUsedPlayerClassSlots[iSlot][iPosition] = true;
  186. */
  187. #endif
  188. }