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.

454 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "buy_preset_debug.h"
  8. #include "buy_presets.h"
  9. #include "weapon_csbase.h"
  10. #include "game/client/iviewport.h"
  11. #include "filesystem.h"
  12. #include <vgui/ILocalize.h>
  13. #include <vgui_controls/Controls.h>
  14. #include "c_cs_player.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. BuyPresetManager *TheBuyPresets = NULL;
  18. #if USE_BUY_PRESETS
  19. //--------------------------------------------------------------------------------------------------------------
  20. ConVar cl_buy_favorite_quiet( "cl_buy_favorite_quiet", "0", FCVAR_ARCHIVE | FCVAR_CLIENTCMD_CAN_EXECUTE, "Skips the prompt when saving a buy favorite in the buy menu" );
  21. ConVar cl_buy_favorite_nowarn( "cl_buy_favorite_nowarn", "0", FCVAR_ARCHIVE | FCVAR_CLIENTCMD_CAN_EXECUTE, "Skips the error prompt when saving an invalid buy favorite" );
  22. //--------------------------------------------------------------------------------------------------------------
  23. static void PrintBuyPresetUsage( void )
  24. {
  25. if ( TheBuyPresets->GetNumPresets() )
  26. {
  27. Msg( "usage: cl_buy_favorite <1...%d>\n", TheBuyPresets->GetNumPresets() );
  28. for ( int i=0; i<TheBuyPresets->GetNumPresets(); ++i )
  29. {
  30. const BuyPreset *preset = TheBuyPresets->GetPreset( i );
  31. if ( preset && preset->GetName() && preset->GetName()[0] )
  32. {
  33. char buffer[64];
  34. g_pVGuiLocalize->ConvertUnicodeToANSI( preset->GetName(), buffer, sizeof( buffer ) );
  35. Msg( " %d. %s\n", i+1, buffer );
  36. }
  37. }
  38. }
  39. else
  40. {
  41. Msg( "cl_buy_favorite: no favorites are defined\n" );
  42. }
  43. }
  44. //--------------------------------------------------------------------------------------------------------------
  45. /**
  46. * Callback function for handling the "cl_buy_favorite" command
  47. */
  48. CON_COMMAND_F( cl_buy_favorite, "Purchase a favorite weapon/equipment loadout", FCVAR_CLIENTCMD_CAN_EXECUTE )
  49. {
  50. if ( !engine->IsConnected() )
  51. return;
  52. if ( !TheBuyPresets )
  53. TheBuyPresets = new BuyPresetManager();
  54. if ( args.ArgC() != 2 )
  55. {
  56. PRESET_DEBUG( "cl_buy_favorite: no favorite specified\n" );
  57. PrintBuyPresetUsage();
  58. return;
  59. }
  60. int presetIndex = atoi( args[1] ) - 1;
  61. if ( presetIndex < 0 || presetIndex >= TheBuyPresets->GetNumPresets() )
  62. {
  63. PRESET_DEBUG( "cl_buy_favorite: favorite %d doesn't exist\n", presetIndex );
  64. PrintBuyPresetUsage();
  65. return;
  66. }
  67. TheBuyPresets->PurchasePreset( presetIndex );
  68. }
  69. //--------------------------------------------------------------------------------------------------------------
  70. /**
  71. * Callback function for handling the "cl_buy_favorite_set" command
  72. */
  73. CON_COMMAND_F( cl_buy_favorite_set, "Saves the current loadout as a favorite", FCVAR_CLIENTCMD_CAN_EXECUTE )
  74. {
  75. if ( !engine->IsConnected() )
  76. return;
  77. if ( !TheBuyPresets )
  78. TheBuyPresets = new BuyPresetManager();
  79. if ( args.ArgC() != 2 )
  80. {
  81. PRESET_DEBUG( "cl_buy_favorite_set: no favorite specified\n" );
  82. PrintBuyPresetUsage();
  83. return;
  84. }
  85. int presetIndex = atoi( args[ 1 ] ) - 1;
  86. if ( presetIndex < 0 || presetIndex >= TheBuyPresets->GetNumPresets() )
  87. {
  88. PRESET_DEBUG( "cl_buy_favorite_set: favorite %d doesn't exist\n", presetIndex );
  89. PrintBuyPresetUsage();
  90. return;
  91. }
  92. const BuyPreset *preset = TheBuyPresets->GetPreset( presetIndex );
  93. if ( !preset )
  94. {
  95. return;
  96. }
  97. WeaponSet ws;
  98. TheBuyPresets->GetCurrentLoadout( &ws );
  99. BuyPreset newPreset( *preset );
  100. newPreset.ReplaceSet( 0, ws );
  101. TheBuyPresets->SetPreset( presetIndex, &newPreset );
  102. TheBuyPresets->Save();
  103. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  104. if ( pPlayer )
  105. {
  106. pPlayer->EmitSound( "BuyPreset.Updated" );
  107. }
  108. }
  109. //--------------------------------------------------------------------------------------------------------------
  110. /**
  111. * Callback function for handling the "cl_buy_favorite_reset" command
  112. */
  113. void __CmdFunc_BuyPresetsReset(void)
  114. {
  115. if ( !engine->IsConnected() )
  116. return;
  117. if ( !TheBuyPresets )
  118. TheBuyPresets = new BuyPresetManager();
  119. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  120. if ( !pPlayer || ( pPlayer->GetTeamNumber() != TEAM_CT && pPlayer->GetTeamNumber() != TEAM_TERRORIST ) )
  121. {
  122. return;
  123. }
  124. TheBuyPresets->ResetEditToDefaults();
  125. TheBuyPresets->SetPresets( TheBuyPresets->GetEditPresets() );
  126. TheBuyPresets->Save();
  127. }
  128. ConCommand cl_buy_favorite_reset( "cl_buy_favorite_reset", __CmdFunc_BuyPresetsReset, "Reset favorite loadouts to the default", FCVAR_CLIENTCMD_CAN_EXECUTE );
  129. #endif // USE_BUY_PRESETS
  130. //--------------------------------------------------------------------------------------------------------------
  131. //--------------------------------------------------------------------------------------------------------------
  132. /**
  133. * Creates the BuyPresetManager singleton
  134. */
  135. BuyPresetManager::BuyPresetManager()
  136. {
  137. m_loadedTeam = TEAM_UNASSIGNED;
  138. }
  139. //--------------------------------------------------------------------------------------------------------------
  140. /**
  141. * Resets the BuyPresetManager, loading BuyPresets from disk. If no presets are defined, it loads the
  142. * default presets instead.
  143. */
  144. void BuyPresetManager::VerifyLoadedTeam( void )
  145. {
  146. #if USE_BUY_PRESETS
  147. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  148. if ( !pPlayer )
  149. return;
  150. int playerTeam = pPlayer->GetTeamNumber();
  151. if ( playerTeam == m_loadedTeam )
  152. return;
  153. if ( playerTeam != TEAM_CT && playerTeam != TEAM_TERRORIST )
  154. return;
  155. m_presets.RemoveAll();
  156. const char *filename = "cfg/BuyPresets_TER.vdf";
  157. if ( playerTeam == TEAM_CT )
  158. {
  159. filename = "cfg/BuyPresets_CT.vdf";
  160. }
  161. KeyValues *data;
  162. KeyValues *presetKey;
  163. data = new KeyValues( "Presets" );
  164. bool fileExists = data->LoadFromFile( filesystem, filename, NULL );
  165. presetKey = data->GetFirstSubKey();
  166. while ( presetKey )
  167. {
  168. BuyPreset preset;
  169. preset.Parse( presetKey );
  170. m_presets.AddToTail(preset);
  171. presetKey = presetKey->GetNextKey();
  172. }
  173. if ( !m_presets.Count() )
  174. {
  175. const char *filename = "cfg/BuyPresetsDefault_TER.vdf";
  176. if ( playerTeam == TEAM_CT )
  177. {
  178. filename = "cfg/BuyPresetsDefault_CT.vdf";
  179. }
  180. KeyValues *data;
  181. KeyValues *presetKey;
  182. data = new KeyValues( "Presets" );
  183. data->LoadFromFile( filesystem, filename, NULL );
  184. presetKey = data->GetFirstSubKey();
  185. while ( presetKey )
  186. {
  187. BuyPreset preset;
  188. preset.Parse( presetKey );
  189. m_presets.AddToTail(preset);
  190. presetKey = presetKey->GetNextKey();
  191. }
  192. data->deleteThis();
  193. }
  194. // Guarantee we have at least this many presets, even if they are blank
  195. while ( m_presets.Count() < NUM_PRESETS )
  196. {
  197. BuyPreset preset;
  198. m_presets.AddToTail(preset);
  199. }
  200. data->deleteThis();
  201. m_editPresets = m_presets;
  202. if ( !fileExists )
  203. Save();
  204. #endif // USE_BUY_PRESETS
  205. }
  206. //--------------------------------------------------------------------------------------------------------------
  207. /**
  208. * Loads the default presets into the editing presets (e.g. when hitting the "Use Defaults" button)
  209. */
  210. void BuyPresetManager::ResetEditToDefaults( void )
  211. {
  212. #if USE_BUY_PRESETS
  213. VerifyLoadedTeam();
  214. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  215. if ( !pPlayer )
  216. return;
  217. int playerTeam = pPlayer->GetTeamNumber();
  218. if ( playerTeam != TEAM_CT && playerTeam != TEAM_TERRORIST )
  219. return;
  220. m_editPresets.RemoveAll();
  221. const char *filename = "cfg/BuyPresetsDefault_TER.vdf";
  222. if ( playerTeam == TEAM_CT )
  223. {
  224. filename = "cfg/BuyPresetsDefault_CT.vdf";
  225. }
  226. KeyValues *data;
  227. KeyValues *presetKey;
  228. data = new KeyValues( "Presets" );
  229. data->LoadFromFile( filesystem, filename, NULL );
  230. presetKey = data->GetFirstSubKey();
  231. while ( presetKey )
  232. {
  233. BuyPreset preset;
  234. preset.Parse( presetKey );
  235. m_editPresets.AddToTail(preset);
  236. presetKey = presetKey->GetNextKey();
  237. }
  238. data->deleteThis();
  239. #endif // USE_BUY_PRESETS
  240. }
  241. //--------------------------------------------------------------------------------------------------------------
  242. /**
  243. * Saves the current BuyPresets to disk
  244. */
  245. void BuyPresetManager::Save()
  246. {
  247. #if USE_BUY_PRESETS
  248. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  249. if ( !pPlayer )
  250. return;
  251. const char *filename = "cfg/BuyPresets_TER.vdf";
  252. switch ( pPlayer->GetTeamNumber() )
  253. {
  254. case TEAM_CT:
  255. filename = "cfg/BuyPresets_CT.vdf";
  256. break;
  257. case TEAM_TERRORIST:
  258. filename = "cfg/BuyPresets_TER.vdf";
  259. break;
  260. default:
  261. return; // don't bother saving presets unless we're on a team
  262. }
  263. KeyValues *data = new KeyValues( "Presets" );
  264. for( int i=0; i<m_presets.Count(); ++i )
  265. {
  266. m_presets[i].Save( data );
  267. }
  268. data->SaveToFile( filesystem, filename, NULL );
  269. data->deleteThis();
  270. #endif // USE_BUY_PRESETS
  271. }
  272. //--------------------------------------------------------------------------------------------------------------
  273. /**
  274. * Returns the specified "live" preset, or NULL if it doesn't exist
  275. */
  276. const BuyPreset * BuyPresetManager::GetPreset( int index ) const
  277. {
  278. if ( index < 0 || index >= m_presets.Count() )
  279. {
  280. return NULL;
  281. }
  282. return &(m_presets[index]);
  283. }
  284. //--------------------------------------------------------------------------------------------------------------
  285. void BuyPresetManager::SetPreset( int index, const BuyPreset *preset )
  286. {
  287. if ( index < 0 || index >= m_presets.Count() || !preset )
  288. {
  289. return;
  290. }
  291. m_presets[index] = *preset;
  292. }
  293. //--------------------------------------------------------------------------------------------------------------
  294. /**
  295. * Returns the specified editing preset, or NULL if it doesn't exist
  296. */
  297. BuyPreset * BuyPresetManager::GetEditPreset( int index )
  298. {
  299. if ( index < 0 || index >= m_editPresets.Count() )
  300. {
  301. return NULL;
  302. }
  303. return &(m_editPresets[index]);
  304. }
  305. //--------------------------------------------------------------------------------------------------------------
  306. /**
  307. * Generates and sends buy commands to buy a specific preset
  308. */
  309. void BuyPresetManager::PurchasePreset( int presetIndex )
  310. {
  311. if ( presetIndex >= 0 && presetIndex < m_presets.Count() )
  312. {
  313. const BuyPreset *preset = &(m_presets[presetIndex]);
  314. int setIndex;
  315. for ( setIndex = 0; setIndex < preset->GetNumSets(); ++setIndex )
  316. {
  317. // Try to buy this weapon set.
  318. const WeaponSet *itemSet = preset->GetSet( setIndex );
  319. if ( itemSet )
  320. {
  321. int currentCost;
  322. WeaponSet currentSet;
  323. itemSet->GetCurrent( currentCost, currentSet );
  324. if ( currentCost > 0 )
  325. {
  326. PRESET_DEBUG( "cl_buy_favorite: buying %ls for a total of $%d.\n",
  327. preset->GetName(),
  328. currentCost );
  329. char buf[BUY_PRESET_COMMAND_LEN];
  330. currentSet.GenerateBuyCommands( buf );
  331. // Send completed string
  332. PRESET_DEBUG( "%s\n", buf );
  333. engine->ClientCmd( buf );
  334. return;
  335. }
  336. else if ( currentCost == 0 )
  337. {
  338. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  339. if ( pPlayer )
  340. {
  341. pPlayer->EmitSound( "BuyPreset.AlreadyBought" );
  342. }
  343. // We have everything already. Let the player know.
  344. if ( setIndex == 0 )
  345. {
  346. PRESET_DEBUG( "cl_buy_favorite: already have a complete %ls set.\n", preset->GetName() );
  347. }
  348. else
  349. {
  350. PRESET_DEBUG( "cl_buy_favorite: can't afford anything better from %ls.\n", preset->GetName() );
  351. }
  352. return;
  353. }
  354. }
  355. }
  356. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  357. if ( pPlayer )
  358. {
  359. pPlayer->EmitSound( "BuyPreset.CantBuy" );
  360. }
  361. PRESET_DEBUG( "cl_buy_favorite: can't afford anything better from %ls.\n", preset->GetName() );
  362. return;
  363. }
  364. // We failed to buy anything. Let the player know.
  365. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  366. if ( pPlayer )
  367. {
  368. pPlayer->EmitSound( "BuyPreset.CantBuy" );
  369. }
  370. PRESET_DEBUG( "cl_buy_favorite: preset %d doesn't exist.\n", presetIndex );
  371. }
  372. //--------------------------------------------------------------------------------------------------------------