Advertisement
Guest User

Untitled

a guest
Jun 19th, 2017
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.11 KB | None | 0 0
  1. //========= Copyright © 1996-2005, 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.  
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16.  
  17. // The sound categories found in the weapon classname.txt files
  18. // This needs to match the WeaponSound_t enum in weapon_parse.h
  19. #if !defined(_STATIC_LINKED) || defined(CLIENT_DLL)
  20. const char *pWeaponSoundCategories[ NUM_SHOOT_SOUND_TYPES ] =
  21. {
  22. "empty",
  23. "single_shot",
  24. "single_shot_npc",
  25. "double_shot",
  26. "double_shot_npc",
  27. "burst",
  28. "reload",
  29. "reload_npc",
  30. "melee_miss",
  31. "melee_hit",
  32. "melee_hit_world",
  33. "special1",
  34. "special2",
  35. "special3",
  36. "taunt"
  37. };
  38. #else
  39. extern const char *pWeaponSoundCategories[ NUM_SHOOT_SOUND_TYPES ];
  40. #endif
  41.  
  42. int GetWeaponSoundFromString( const char *pszString )
  43. {
  44. for ( int i = EMPTY; i < NUM_SHOOT_SOUND_TYPES; i++ )
  45. {
  46. if ( !Q_stricmp(pszString,pWeaponSoundCategories[i]) )
  47. return (WeaponSound_t)i;
  48. }
  49. return -1;
  50. }
  51.  
  52.  
  53. // Item flags that we parse out of the file.
  54. typedef struct
  55. {
  56. const char *m_pFlagName;
  57. int m_iFlagValue;
  58. } itemFlags_t;
  59. #if !defined(_STATIC_LINKED) || defined(CLIENT_DLL)
  60. itemFlags_t g_ItemFlags[8] =
  61. {
  62. { "ITEM_FLAG_SELECTONEMPTY", ITEM_FLAG_SELECTONEMPTY },
  63. { "ITEM_FLAG_NOAUTORELOAD", ITEM_FLAG_NOAUTORELOAD },
  64. { "ITEM_FLAG_NOAUTOSWITCHEMPTY", ITEM_FLAG_NOAUTOSWITCHEMPTY },
  65. { "ITEM_FLAG_LIMITINWORLD", ITEM_FLAG_LIMITINWORLD },
  66. { "ITEM_FLAG_EXHAUSTIBLE", ITEM_FLAG_EXHAUSTIBLE },
  67. { "ITEM_FLAG_DOHITLOCATIONDMG", ITEM_FLAG_DOHITLOCATIONDMG },
  68. { "ITEM_FLAG_NOAMMOPICKUPS", ITEM_FLAG_NOAMMOPICKUPS },
  69. { "ITEM_FLAG_NOITEMPICKUP", ITEM_FLAG_NOITEMPICKUP }
  70. };
  71. #else
  72. extern itemFlags_t g_ItemFlags[7];
  73. #endif
  74.  
  75.  
  76. static CUtlDict< FileWeaponInfo_t*, unsigned short > m_WeaponInfoDatabase;
  77.  
  78. #ifdef _DEBUG
  79. // used to track whether or not two weapons have been mistakenly assigned the wrong slot
  80. bool g_bUsedWeaponSlots[MAX_WEAPON_SLOTS][MAX_WEAPON_POSITIONS] = { 0 };
  81.  
  82. #endif
  83.  
  84. //-----------------------------------------------------------------------------
  85. // Purpose:
  86. // Input : *name -
  87. // Output : FileWeaponInfo_t
  88. //-----------------------------------------------------------------------------
  89. static WEAPON_FILE_INFO_HANDLE FindWeaponInfoSlot( const char *name )
  90. {
  91. // Complain about duplicately defined metaclass names...
  92. unsigned short lookup = m_WeaponInfoDatabase.Find( name );
  93. if ( lookup != m_WeaponInfoDatabase.InvalidIndex() )
  94. {
  95. return lookup;
  96. }
  97.  
  98. FileWeaponInfo_t *insert = CreateWeaponInfo();
  99.  
  100. lookup = m_WeaponInfoDatabase.Insert( name, insert );
  101. Assert( lookup != m_WeaponInfoDatabase.InvalidIndex() );
  102. return lookup;
  103. }
  104.  
  105. // Find a weapon slot, assuming the weapon's data has already been loaded.
  106. WEAPON_FILE_INFO_HANDLE LookupWeaponInfoSlot( const char *name )
  107. {
  108. return m_WeaponInfoDatabase.Find( name );
  109. }
  110.  
  111.  
  112.  
  113. // FIXME, handle differently?
  114. static FileWeaponInfo_t gNullWeaponInfo;
  115.  
  116.  
  117. //-----------------------------------------------------------------------------
  118. // Purpose:
  119. // Input : handle -
  120. // Output : FileWeaponInfo_t
  121. //-----------------------------------------------------------------------------
  122. FileWeaponInfo_t *GetFileWeaponInfoFromHandle( WEAPON_FILE_INFO_HANDLE handle )
  123. {
  124. if ( handle < 0 || handle >= m_WeaponInfoDatabase.Count() )
  125. {
  126. return &gNullWeaponInfo;
  127. }
  128.  
  129. if ( handle == m_WeaponInfoDatabase.InvalidIndex() )
  130. {
  131. return &gNullWeaponInfo;
  132. }
  133.  
  134. return m_WeaponInfoDatabase[ handle ];
  135. }
  136.  
  137. //-----------------------------------------------------------------------------
  138. // Purpose:
  139. // Output : WEAPON_FILE_INFO_HANDLE
  140. //-----------------------------------------------------------------------------
  141. WEAPON_FILE_INFO_HANDLE GetInvalidWeaponInfoHandle( void )
  142. {
  143. return (WEAPON_FILE_INFO_HANDLE)m_WeaponInfoDatabase.InvalidIndex();
  144. }
  145.  
  146. #if 0
  147. void ResetFileWeaponInfoDatabase( void )
  148. {
  149. int c = m_WeaponInfoDatabase.Count();
  150. for ( int i = 0; i < c; ++i )
  151. {
  152. delete m_WeaponInfoDatabase[ i ];
  153. }
  154. m_WeaponInfoDatabase.RemoveAll();
  155.  
  156. #ifdef _DEBUG
  157. memset(g_bUsedWeaponSlots, 0, sizeof(g_bUsedWeaponSlots));
  158. #endif
  159. }
  160. #endif
  161.  
  162. void PrecacheFileWeaponInfoDatabase( IFileSystem *filesystem, const unsigned char *pICEKey )
  163. {
  164. if ( m_WeaponInfoDatabase.Count() )
  165. return;
  166.  
  167. KeyValues *manifest = new KeyValues( "weaponscripts" );
  168. if ( manifest->LoadFromFile( filesystem, "scripts/weapon_manifest.txt", "GAME" ) )
  169. {
  170. for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL ; sub = sub->GetNextKey() )
  171. {
  172. if ( !Q_stricmp( sub->GetName(), "file" ) )
  173. {
  174. char fileBase[512];
  175. Q_FileBase( sub->GetString(), fileBase, sizeof(fileBase) );
  176. WEAPON_FILE_INFO_HANDLE tmp;
  177. #ifdef CLIENT_DLL
  178. if ( ReadWeaponDataFromFileForSlot( filesystem, fileBase, &tmp, pICEKey ) )
  179. {
  180. gWR.LoadWeaponSprites( tmp );
  181. }
  182. #else
  183. ReadWeaponDataFromFileForSlot( filesystem, fileBase, &tmp, pICEKey );
  184. #endif
  185. }
  186. else
  187. {
  188. Error( "Expecting 'file', got %s\n", sub->GetName() );
  189. }
  190. }
  191. }
  192. manifest->deleteThis();
  193. }
  194.  
  195. KeyValues* ReadEncryptedKVFile( IFileSystem *filesystem, const char *szFilenameWithoutExtension, const unsigned char *pICEKey )
  196. {
  197. Assert( strchr( szFilenameWithoutExtension, '.' ) == NULL );
  198. char szFullName[512];
  199.  
  200. const char *pSearchPath = "MOD";
  201.  
  202. if ( pICEKey == NULL )
  203. {
  204. pSearchPath = "GAME";
  205. }
  206.  
  207. // Open the weapon data file, and abort if we can't
  208. KeyValues *pKV = new KeyValues( "WeaponDatafile" );
  209.  
  210. Q_snprintf(szFullName,sizeof(szFullName), "%s.txt", szFilenameWithoutExtension);
  211.  
  212. if ( !pKV->LoadFromFile( filesystem, szFullName, pSearchPath ) ) // try to load the normal .txt file first
  213. {
  214. #ifndef _XBOX
  215. if ( pICEKey )
  216. {
  217. Q_snprintf(szFullName,sizeof(szFullName), "%s.ctx", szFilenameWithoutExtension); // fall back to the .ctx file
  218.  
  219. FileHandle_t f = filesystem->Open( szFullName, "rb", pSearchPath );
  220.  
  221. if (!f)
  222. {
  223. pKV->deleteThis();
  224. return NULL;
  225. }
  226. // load file into a null-terminated buffer
  227. int fileSize = filesystem->Size(f);
  228. char *buffer = (char*)MemAllocScratch(fileSize + 1);
  229.  
  230. Assert(buffer);
  231.  
  232. filesystem->Read(buffer, fileSize, f); // read into local buffer
  233. buffer[fileSize] = 0; // null terminate file as EOF
  234. filesystem->Close( f ); // close file after reading
  235.  
  236. UTIL_DecodeICE( (unsigned char*)buffer, fileSize, pICEKey );
  237.  
  238. bool retOK = pKV->LoadFromBuffer( szFullName, buffer, filesystem );
  239.  
  240. MemFreeScratch();
  241.  
  242. if ( !retOK )
  243. {
  244. pKV->deleteThis();
  245. return NULL;
  246. }
  247. }
  248. else
  249. {
  250. pKV->deleteThis();
  251. return NULL;
  252. }
  253. #else
  254. pKV->deleteThis();
  255. return NULL;
  256. #endif
  257. }
  258.  
  259. return pKV;
  260. }
  261.  
  262.  
  263. //-----------------------------------------------------------------------------
  264. // Purpose: Read data on weapon from script file
  265. // Output: true - if data2 successfully read
  266. // false - if data load fails
  267. //-----------------------------------------------------------------------------
  268.  
  269. bool ReadWeaponDataFromFileForSlot( IFileSystem* filesystem, const char *szWeaponName, WEAPON_FILE_INFO_HANDLE *phandle, const unsigned char *pICEKey )
  270. {
  271. if ( !phandle )
  272. {
  273. Assert( 0 );
  274. return false;
  275. }
  276.  
  277. *phandle = FindWeaponInfoSlot( szWeaponName );
  278. FileWeaponInfo_t *pFileInfo = GetFileWeaponInfoFromHandle( *phandle );
  279. Assert( pFileInfo );
  280.  
  281. if ( pFileInfo->bParsedScript )
  282. return true;
  283.  
  284. char sz[128];
  285. Q_snprintf( sz, sizeof( sz ), "scripts/%s", szWeaponName );
  286. KeyValues *pKV = ReadEncryptedKVFile( filesystem, sz, pICEKey );
  287. if ( !pKV )
  288. return false;
  289.  
  290. pFileInfo->Parse( pKV, szWeaponName );
  291.  
  292. pKV->deleteThis();
  293.  
  294. return true;
  295. }
  296.  
  297.  
  298. //-----------------------------------------------------------------------------
  299. // FileWeaponInfo_t implementation.
  300. //-----------------------------------------------------------------------------
  301.  
  302. FileWeaponInfo_t::FileWeaponInfo_t()
  303. {
  304. bParsedScript = false;
  305. bLoadedHudElements = false;
  306. szClassName[0] = 0;
  307. szPrintName[0] = 0;
  308.  
  309. szViewModel[0] = 0;
  310. szWorldModel[0] = 0;
  311. szAnimationPrefix[0] = 0;
  312. iSlot = 0;
  313. iPosition = 0;
  314. iMaxClip1 = 0;
  315. iMaxClip2 = 0;
  316. iDefaultClip1 = 0;
  317. iDefaultClip2 = 0;
  318. iWeight = 0;
  319. iRumbleEffect = -1;
  320. bAutoSwitchTo = false;
  321. bAutoSwitchFrom = false;
  322. iFlags = 0;
  323. szAmmo1[0] = 0;
  324. szAmmo2[0] = 0;
  325. memset( aShootSounds, 0, sizeof( aShootSounds ) );
  326. iAmmoType = 0;
  327. iAmmo2Type = 0;
  328. m_bMeleeWeapon = false;
  329. iSpriteCount = 0;
  330. iconActive = 0;
  331. iconInactive = 0;
  332. iconAmmo = 0;
  333. iconAmmo2 = 0;
  334. iconCrosshair = 0;
  335. iconAutoaim = 0;
  336. iconZoomedCrosshair = 0;
  337. iconZoomedAutoaim = 0;
  338. bShowUsageHint = false;
  339. m_bAllowFlipping = true;
  340. m_bBuiltRightHanded = false;
  341. iWeaponCategory = 0;
  342. }
  343.  
  344. #ifdef CLIENT_DLL
  345. extern ConVar hud_fastswitch;
  346. #endif
  347.  
  348. void FileWeaponInfo_t::Parse( KeyValues *pKeyValuesData, const char *szWeaponName )
  349. {
  350. KeyValues *pSights = pKeyValuesData->FindKey( "IronSight" );
  351. if (pSights)
  352. {
  353. vecIronsightPosOffset.x = pSights->GetFloat( "forward", 0.0f );
  354. vecIronsightPosOffset.y = pSights->GetFloat( "right", 0.0f );
  355. vecIronsightPosOffset.z = pSights->GetFloat( "up", 0.0f );
  356.  
  357. angIronsightAngOffset[PITCH] = pSights->GetFloat( "pitch", 0.0f );
  358. angIronsightAngOffset[YAW] = pSights->GetFloat( "yaw", 0.0f );
  359. angIronsightAngOffset[ROLL] = pSights->GetFloat( "roll", 0.0f );
  360.  
  361. flIronsightFOVOffset = pSights->GetFloat( "fov", 0.0f );
  362. }
  363. else
  364. {
  365. //note: you can set a bool here if you'd like to disable ironsights for weapons with no IronSight-key
  366. vecIronsightPosOffset = vec3_origin;
  367. angIronsightAngOffset.Init();
  368. flIronsightFOVOffset = 0.0f;
  369. }
  370. // Okay, we tried at least once to look this up...
  371. bParsedScript = true;
  372.  
  373. // Classname
  374. Q_strncpy( szClassName, szWeaponName, MAX_WEAPON_STRING );
  375. // Printable name
  376. Q_strncpy( szPrintName, pKeyValuesData->GetString( "printname", WEAPON_PRINTNAME_MISSING ), MAX_WEAPON_STRING );
  377. // View model & world model
  378. Q_strncpy( szViewModel, pKeyValuesData->GetString( "viewmodel" ), MAX_WEAPON_STRING );
  379. Q_strncpy( szWorldModel, pKeyValuesData->GetString( "playermodel" ), MAX_WEAPON_STRING );
  380. Q_strncpy( szAnimationPrefix, pKeyValuesData->GetString( "anim_prefix" ), MAX_WEAPON_PREFIX );
  381. iSlot = pKeyValuesData->GetInt( "bucket", 0 );
  382. iPosition = pKeyValuesData->GetInt( "bucket_position", 0 );
  383.  
  384. // Use the console (X360) buckets if hud_fastswitch is set to 2.
  385. #ifdef CLIENT_DLL
  386. if ( hud_fastswitch.GetInt() == 2 )
  387. #else
  388. if ( IsX360() )
  389. #endif
  390. {
  391. iSlot = pKeyValuesData->GetInt( "bucket_360", iSlot );
  392. iPosition = pKeyValuesData->GetInt( "bucket_position_360", iPosition );
  393. }
  394. iMaxClip1 = pKeyValuesData->GetInt( "clip_size", WEAPON_NOCLIP ); // Max primary clips gun can hold (assume they don't use clips by default)
  395. iMaxClip2 = pKeyValuesData->GetInt( "clip2_size", WEAPON_NOCLIP ); // Max secondary clips gun can hold (assume they don't use clips by default)
  396. iDefaultClip1 = pKeyValuesData->GetInt( "default_clip", iMaxClip1 ); // amount of primary ammo placed in the primary clip when it's picked up
  397. iDefaultClip2 = pKeyValuesData->GetInt( "default_clip2", iMaxClip2 ); // amount of secondary ammo placed in the secondary clip when it's picked up
  398. iWeight = pKeyValuesData->GetInt( "weight", 0 );
  399.  
  400. iRumbleEffect = pKeyValuesData->GetInt( "rumble", -1 );
  401.  
  402. // LAME old way to specify item flags.
  403. // Weapon scripts should use the flag names.
  404. iFlags = pKeyValuesData->GetInt( "item_flags", ITEM_FLAG_LIMITINWORLD );
  405.  
  406. for ( int i=0; i < ARRAYSIZE( g_ItemFlags ); i++ )
  407. {
  408. int iVal = pKeyValuesData->GetInt( g_ItemFlags[i].m_pFlagName, -1 );
  409. if ( iVal == 0 )
  410. {
  411. iFlags &= ~g_ItemFlags[i].m_iFlagValue;
  412. }
  413. else if ( iVal == 1 )
  414. {
  415. iFlags |= g_ItemFlags[i].m_iFlagValue;
  416. }
  417. }
  418.  
  419.  
  420. bShowUsageHint = ( pKeyValuesData->GetInt( "showusagehint", 0 ) != 0 ) ? true : false;
  421. bAutoSwitchTo = ( pKeyValuesData->GetInt( "autoswitchto", 1 ) != 0 ) ? true : false;
  422. bAutoSwitchFrom = ( pKeyValuesData->GetInt( "autoswitchfrom", 1 ) != 0 ) ? true : false;
  423. m_bBuiltRightHanded = ( pKeyValuesData->GetInt( "BuiltRightHanded", 1 ) != 0 ) ? true : false;
  424. m_bAllowFlipping = ( pKeyValuesData->GetInt( "AllowFlipping", 1 ) != 0 ) ? true : false;
  425. m_bMeleeWeapon = ( pKeyValuesData->GetInt( "MeleeWeapon", 0 ) != 0 ) ? true : false;
  426.  
  427. #if defined(_DEBUG) && defined(HL2_CLIENT_DLL)
  428. // make sure two weapons aren't in the same slot & position
  429. if ( iSlot >= MAX_WEAPON_SLOTS ||
  430. iPosition >= MAX_WEAPON_POSITIONS )
  431. {
  432. Warning( "Invalid weapon slot or position [slot %d/%d max], pos[%d/%d max]\n",
  433. iSlot, MAX_WEAPON_SLOTS - 1, iPosition, MAX_WEAPON_POSITIONS - 1 );
  434. }
  435. else
  436. {
  437. if (g_bUsedWeaponSlots[iSlot][iPosition])
  438. {
  439. Warning( "Duplicately assigned weapon slots in selection hud: %s (%d, %d)\n", szPrintName, iSlot, iPosition );
  440. }
  441. g_bUsedWeaponSlots[iSlot][iPosition] = true;
  442. }
  443. #endif
  444.  
  445. // Primary ammo used
  446. const char *pAmmo = pKeyValuesData->GetString( "primary_ammo", "None" );
  447. if ( strcmp("None", pAmmo) == 0 )
  448. Q_strncpy( szAmmo1, "", sizeof( szAmmo1 ) );
  449. else
  450. Q_strncpy( szAmmo1, pAmmo, sizeof( szAmmo1 ) );
  451. iAmmoType = GetAmmoDef()->Index( szAmmo1 );
  452.  
  453. // Secondary ammo used
  454. pAmmo = pKeyValuesData->GetString( "secondary_ammo", "None" );
  455. if ( strcmp("None", pAmmo) == 0)
  456. Q_strncpy( szAmmo2, "", sizeof( szAmmo2 ) );
  457. else
  458. Q_strncpy( szAmmo2, pAmmo, sizeof( szAmmo2 ) );
  459. iAmmo2Type = GetAmmoDef()->Index( szAmmo2 );
  460.  
  461. // Now read the weapon sounds
  462. memset( aShootSounds, 0, sizeof( aShootSounds ) );
  463. KeyValues *pSoundData = pKeyValuesData->FindKey( "SoundData" );
  464. if ( pSoundData )
  465. {
  466. for ( int i = EMPTY; i < NUM_SHOOT_SOUND_TYPES; i++ )
  467. {
  468. const char *soundname = pSoundData->GetString( pWeaponSoundCategories[i] );
  469. if ( soundname && soundname[0] )
  470. {
  471. Q_strncpy( aShootSounds[i], soundname, MAX_WEAPON_STRING );
  472. }
  473. }
  474. }
  475. iWeaponCategory = pKeyValuesData->GetInt( "weapon_category", 0 );
  476. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement