daily pastebin goal
22%
SHARE
TWEET

Untitled

a guest Jun 19th, 2017 49 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data
Top