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.

931 lines
29 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include <vgui/ILocalize.h>
  8. #include "vgui_controls/TextEntry.h"
  9. #include "vgui_controls/ComboBox.h"
  10. #include "vgui_controls/CheckButton.h"
  11. #include "testitem_root.h"
  12. #include "tf_controls.h"
  13. #include "c_playerresource.h"
  14. #include "gcsdk/gcmsg.h"
  15. #include "tf_gcmessages.h"
  16. #include "econ_item_inventory.h"
  17. #include "econ_gcmessages.h"
  18. #include "ienginevgui.h"
  19. #include "econ_item_system.h"
  20. #include "vgui_controls/FileOpenDialog.h"
  21. #include <filesystem.h>
  22. #include "ai_activity.h"
  23. #include "tf_gamerules.h"
  24. #include "vgui_controls/Slider.h"
  25. // memdbgon must be the last include file in a .cpp file!!!
  26. #include <tier0/memdbgon.h>
  27. ConVar tf_testitem_recent( "tf_testitem_recent", "", FCVAR_ARCHIVE );
  28. KeyValues *g_pRootItemTestingKV = NULL;
  29. // Bot animations
  30. const char *g_pszBotAnimStrings[TI_BOTANIM_COUNT] =
  31. {
  32. "#IT_BotAnim_Idle", // TI_BOTANIM_IDLE,
  33. "#IT_BotAnim_Crouch_Idle", // TI_BOTANIM_CROUCH,
  34. "#IT_BotAnim_Run", // TI_BOTANIM_RUN,
  35. "#IT_BotAnim_Crouch_Walk", // TI_BOTANIM_CROUCH_WALK
  36. "#IT_BotAnim_Jump", // TI_BOTANIM_JUMP
  37. };
  38. void UpdateItemTestKVs( void )
  39. {
  40. KeyValues *pTmpCopy = g_pRootItemTestingKV->MakeCopy();
  41. engine->ServerCmdKeyValues( pTmpCopy );
  42. // Setup any clientside variables to match what we're sending to the server
  43. TFGameRules()->ItemTesting_SetupFromKV( g_pRootItemTestingKV );
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Purpose:
  47. //-----------------------------------------------------------------------------
  48. CTestItemRoot::CTestItemRoot( vgui::Panel *parent ) : vgui::EditablePanel( parent, "TestItemRoot" )
  49. {
  50. // Need to use the clientscheme (we're not parented to a clientscheme'd panel)
  51. vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
  52. SetScheme(scheme);
  53. SetProportional( true );
  54. ListenForGameEvent( "gameui_hidden" );
  55. m_hEditItemDialog = NULL;
  56. m_iClassUsage = 0;
  57. m_pClassUsagePanel = NULL;
  58. m_pTestingPanel = NULL;
  59. m_hImportExportDialog = NULL;
  60. m_bExporting = false;
  61. memset( m_pItemTestButtons, 0, sizeof(m_pItemTestButtons) );
  62. memset( m_pItemRemoveButtons, 0, sizeof(m_pItemRemoveButtons) );
  63. memset( m_pClassCheckButtons, NULL, sizeof(m_pClassCheckButtons) );
  64. memset( m_pItemTestKVs, 0, sizeof(m_pItemTestKVs) );
  65. m_pBotAdditionPanel = new vgui::EditablePanel( this, "BotAdditionPanel" );
  66. m_pBotSelectionComboBox = new vgui::ComboBox( m_pBotAdditionPanel, "BotSelectionComboBox", 9, false );
  67. m_pBotSelectionComboBox->AddActionSignalTarget( this );
  68. m_pAutoAddBotsCheckBox = new vgui::CheckButton( m_pBotAdditionPanel, "AutoAddBotsCheckBox", "" );
  69. m_pAutoAddBotsCheckBox->AddActionSignalTarget( this );
  70. m_pAutoAddBotsCheckBox->SetSelected( true );
  71. m_pBotsOnBlueTeamCheckBox = new vgui::CheckButton( m_pBotAdditionPanel, "BotsOnBlueTeamCheckBox", "" );
  72. m_pBotsOnBlueTeamCheckBox->AddActionSignalTarget( this );
  73. m_pBotsOnBlueTeamCheckBox->SetSelected( true );
  74. m_pAddBotButton = NULL;
  75. m_pBotControlPanel = new CTestItemBotControls( this );
  76. m_pBotControlPanel->SetEmbedded( true );
  77. SetupComboBoxes();
  78. if ( !g_pRootItemTestingKV )
  79. {
  80. g_pRootItemTestingKV = new KeyValues( "TestItems" );
  81. }
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose:
  85. //-----------------------------------------------------------------------------
  86. CTestItemRoot::~CTestItemRoot( void )
  87. {
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Purpose:
  91. //-----------------------------------------------------------------------------
  92. void CTestItemRoot::SetupComboBoxes( void )
  93. {
  94. // Setup our Bot Selection combo box
  95. KeyValues *pKeyValues;
  96. for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass <= TF_LAST_NORMAL_CLASS; iClass++ )
  97. {
  98. if ( iClass == TF_CLASS_CIVILIAN )
  99. continue;
  100. pKeyValues = new KeyValues( "data" );
  101. pKeyValues->SetInt( "class", iClass );
  102. m_pBotSelectionComboBox->AddItem( g_aPlayerClassNames[iClass], pKeyValues );
  103. }
  104. m_pBotSelectionComboBox->SilentActivateItemByRow( 0 );
  105. m_pBotControlPanel->SetupComboBoxes();
  106. }
  107. //-----------------------------------------------------------------------------
  108. // Purpose:
  109. //-----------------------------------------------------------------------------
  110. void CTestItemRoot::ApplySchemeSettings( vgui::IScheme *pScheme )
  111. {
  112. BaseClass::ApplySchemeSettings( pScheme );
  113. LoadControlSettings( "resource/ui/TestItemRoot.res" );
  114. m_pTestingPanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName( "TestingPanel" ) );
  115. if ( m_pTestingPanel )
  116. {
  117. for ( int i = 0; i < TI_TYPE_COUNT; i++ )
  118. {
  119. m_pItemTestButtons[i] = dynamic_cast<CExButton*>( m_pTestingPanel->FindChildByName( VarArgs("TestItemButton%d",i) ) );
  120. m_pItemTestButtons[i]->AddActionSignalTarget( this );
  121. m_pItemRemoveButtons[i] = dynamic_cast<CExButton*>( m_pTestingPanel->FindChildByName( VarArgs("RemoveItemButton%d",i) ) );
  122. m_pItemRemoveButtons[i]->AddActionSignalTarget( this );
  123. m_pItemTestLabels[i] = dynamic_cast<CExLabel*>( m_pTestingPanel->FindChildByName( VarArgs("TestItemEntry%d",i) ) );
  124. }
  125. }
  126. m_pClassUsagePanel = dynamic_cast<vgui::EditablePanel*>( FindChildByName( "ClassUsagePanel" ) );
  127. if ( m_pClassUsagePanel )
  128. {
  129. for ( int i = 0; i < TF_LAST_NORMAL_CLASS; i++ )
  130. {
  131. m_pClassCheckButtons[i] = dynamic_cast<vgui::CheckButton*>( m_pClassUsagePanel->FindChildByName( VarArgs("ClassCheckBox%d",i)) );
  132. m_pClassCheckButtons[i]->AddActionSignalTarget( this );
  133. }
  134. }
  135. m_pAddBotButton = dynamic_cast<CExButton*>( m_pBotAdditionPanel->FindChildByName( "AddBotButton" ) );
  136. if ( m_pAddBotButton )
  137. {
  138. m_pAddBotButton->AddActionSignalTarget( this );
  139. }
  140. CExButton *pKickAllBotsButton = dynamic_cast<CExButton*>( m_pBotAdditionPanel->FindChildByName( "KickAllBotsButton" ) );
  141. if ( pKickAllBotsButton )
  142. {
  143. pKickAllBotsButton->AddActionSignalTarget( this );
  144. }
  145. AddChildActionSignalTarget( this, "SteamWorkshopButtonSubButton", this, true );
  146. UpdateTestItems();
  147. }
  148. //-----------------------------------------------------------------------------
  149. // Purpose:
  150. //-----------------------------------------------------------------------------
  151. void CTestItemRoot::PerformLayout( void )
  152. {
  153. BaseClass::PerformLayout();
  154. }
  155. //-----------------------------------------------------------------------------
  156. // Purpose:
  157. //-----------------------------------------------------------------------------
  158. void CTestItemRoot::FireGameEvent( IGameEvent *event )
  159. {
  160. const char *type = event->GetName();
  161. if ( Q_strcmp(type, "gameui_hidden") == 0 )
  162. {
  163. Close();
  164. }
  165. }
  166. //-----------------------------------------------------------------------------
  167. // Purpose:
  168. //-----------------------------------------------------------------------------
  169. void CTestItemRoot::Close( void )
  170. {
  171. TFModalStack()->PopModal( this );
  172. SetVisible( false );
  173. MarkForDeletion();
  174. }
  175. //-----------------------------------------------------------------------------
  176. // Purpose:
  177. //-----------------------------------------------------------------------------
  178. void CTestItemRoot::OnSetTestItemKVs( KeyValues *pKV )
  179. {
  180. if ( !pKV )
  181. return;
  182. testitem_itemtypes_t iItemType = (testitem_itemtypes_t)pKV->GetInt("item_type");
  183. if ( iItemType <= TI_TYPE_UNKNOWN || iItemType > TI_TYPE_COUNT )
  184. return;
  185. // If we already have KVs for that slot, nuke them
  186. if ( m_pItemTestKVs[iItemType] )
  187. {
  188. g_pRootItemTestingKV->RemoveSubKey( m_pItemTestKVs[iItemType] );
  189. m_pItemTestKVs[iItemType]->deleteThis();
  190. }
  191. // Make our copy, and store it in the root KVs
  192. m_pItemTestKVs[iItemType] = pKV->MakeCopy();
  193. m_pItemTestKVs[iItemType]->SetName( VarArgs("Item%d",iItemType) );
  194. g_pRootItemTestingKV->AddSubKey( m_pItemTestKVs[iItemType] );
  195. UpdateTestItems();
  196. }
  197. //-----------------------------------------------------------------------------
  198. // Purpose:
  199. //-----------------------------------------------------------------------------
  200. void CTestItemRoot::OnButtonChecked( KeyValues *pData )
  201. {
  202. Panel *pPanel = reinterpret_cast<vgui::Panel *>( pData->GetPtr("panel") );
  203. if ( pPanel == m_pAutoAddBotsCheckBox )
  204. {
  205. if ( m_pAutoAddBotsCheckBox->IsSelected() )
  206. {
  207. m_pAddBotButton->SetEnabled( false );
  208. m_pBotSelectionComboBox->SetEnabled( false );
  209. }
  210. else
  211. {
  212. m_pAddBotButton->SetEnabled( true );
  213. m_pBotSelectionComboBox->SetEnabled( true );
  214. }
  215. return;
  216. }
  217. // If they hit all classes, disable everything else.
  218. if ( pPanel == m_pClassCheckButtons[0] )
  219. {
  220. bool bAllClass = m_pClassCheckButtons[0]->IsSelected();
  221. for ( int i = 1; i < TF_LAST_NORMAL_CLASS; i++ )
  222. {
  223. m_pClassCheckButtons[i]->SetEnabled( !bAllClass );
  224. if ( bAllClass )
  225. {
  226. m_pClassCheckButtons[i]->SetSelected( false );
  227. }
  228. }
  229. }
  230. else
  231. {
  232. // If they've individually checked all boxes, switch to all-classes being checked
  233. bool bAllChecked = true;
  234. for ( int i = 1; i < TF_LAST_NORMAL_CLASS; i++ )
  235. {
  236. if ( !m_pClassCheckButtons[i]->IsSelected() )
  237. {
  238. bAllChecked = false;
  239. break;
  240. }
  241. }
  242. if ( bAllChecked )
  243. {
  244. m_pClassCheckButtons[0]->SetSelected( true );
  245. }
  246. }
  247. m_iClassUsage = 0;
  248. for ( int i = 0; i < TF_LAST_NORMAL_CLASS; i++ )
  249. {
  250. if ( m_pClassCheckButtons[i]->IsSelected() )
  251. {
  252. m_iClassUsage |= (1 << i);
  253. }
  254. }
  255. UpdateTestItems();
  256. }
  257. //-----------------------------------------------------------------------------
  258. // Purpose:
  259. //-----------------------------------------------------------------------------
  260. void CTestItemRoot::CommitSettingsToKV( void )
  261. {
  262. g_pRootItemTestingKV->SetInt( "class_usage", m_iClassUsage );
  263. g_pRootItemTestingKV->SetInt( "auto_add_bots", m_pAutoAddBotsCheckBox->IsSelected() );
  264. g_pRootItemTestingKV->SetInt( "bots_on_blue_team", m_pBotsOnBlueTeamCheckBox->IsSelected() );
  265. m_pBotControlPanel->CommitSettingsToKV();
  266. }
  267. //-----------------------------------------------------------------------------
  268. // Purpose:
  269. //-----------------------------------------------------------------------------
  270. void CTestItemRoot::OnFileSelected(const char *fullpath)
  271. {
  272. if ( m_bExporting )
  273. {
  274. ExportTestSetup( fullpath );
  275. }
  276. else
  277. {
  278. ImportTestSetup( fullpath );
  279. }
  280. // Nuke the file open dialog
  281. m_hImportExportDialog->MarkForDeletion();
  282. m_hImportExportDialog = NULL;
  283. }
  284. //-----------------------------------------------------------------------------
  285. // Purpose:
  286. //-----------------------------------------------------------------------------
  287. void CTestItemRoot::ExportTestSetup( const char *pFilename )
  288. {
  289. if ( !pFilename || !pFilename[0] )
  290. return;
  291. CommitSettingsToKV();
  292. g_pRootItemTestingKV->SaveToFile( g_pFullFileSystem, pFilename );
  293. tf_testitem_recent.SetValue( pFilename );
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Purpose:
  297. //-----------------------------------------------------------------------------
  298. void CTestItemRoot::ImportTestSetup( KeyValues *pKV )
  299. {
  300. // Setup the class usage checkboxes
  301. m_iClassUsage = pKV->GetInt( "class_usage", 0 );
  302. for ( int i = 0; i < TF_LAST_NORMAL_CLASS; i++ )
  303. {
  304. m_pClassCheckButtons[i]->SetSelected( (m_iClassUsage & (1<<i)) );
  305. }
  306. // Pull out the item KV blocks
  307. for ( int i = 0; i < TI_TYPE_COUNT; i++ )
  308. {
  309. m_pItemTestKVs[i] = pKV->FindKey( VarArgs("Item%d",i) );
  310. }
  311. bool bAutoAdd = pKV->GetInt( "auto_add_bots", 1 );
  312. m_pAutoAddBotsCheckBox->SetSelected(bAutoAdd);
  313. bool bBlueTeamBots = pKV->GetInt( "bots_on_blue_team", 0 );
  314. m_pBotsOnBlueTeamCheckBox->SetSelected(bBlueTeamBots);
  315. m_pBotControlPanel->ImportTestSetup( pKV );
  316. UpdateTestItems();
  317. }
  318. //-----------------------------------------------------------------------------
  319. // Purpose:
  320. //-----------------------------------------------------------------------------
  321. void CTestItemRoot::ImportTestSetup( const char *pFilename )
  322. {
  323. if ( !pFilename || !pFilename[0] )
  324. return;
  325. g_pRootItemTestingKV->deleteThis();
  326. g_pRootItemTestingKV = new KeyValues( "TestItems" );
  327. if ( g_pRootItemTestingKV->LoadFromFile( g_pFullFileSystem, pFilename ) )
  328. {
  329. ImportTestSetup( g_pRootItemTestingKV );
  330. }
  331. else
  332. {
  333. m_iClassUsage = 0;
  334. memset( m_pItemTestKVs, 0, sizeof(m_pItemTestKVs) );
  335. g_pRootItemTestingKV->deleteThis();
  336. g_pRootItemTestingKV = new KeyValues( "TestItems" );
  337. UpdateTestItems();
  338. }
  339. }
  340. //-----------------------------------------------------------------------------
  341. // Purpose:
  342. //-----------------------------------------------------------------------------
  343. int CTestItemRoot::FindReplaceableItemsForSelectedClass( CUtlVector<item_definition_index_t> *pItemDefs, bool bWeapons )
  344. {
  345. // Build our list of checked classes
  346. bool bClasses[TF_LAST_NORMAL_CLASS];
  347. for ( int i = 0; i < TF_LAST_NORMAL_CLASS; i++ )
  348. {
  349. bClasses[i] = m_iClassUsage & (1 << i);
  350. }
  351. int iReplaceableItems = 0;
  352. // Find all the weapons that can be used by the combination of classes we've checked
  353. const CEconItemSchema::SortedItemDefinitionMap_t& mapItemDefs = ItemSystem()->GetItemSchema()->GetSortedItemDefinitionMap();
  354. FOR_EACH_MAP( mapItemDefs, i )
  355. {
  356. const CTFItemDefinition *pDef = dynamic_cast<const CTFItemDefinition *>( mapItemDefs[i] );
  357. // Never show:
  358. // - Hidden items
  359. // - Items that don't have fixed qualities
  360. if ( !pDef || pDef->IsHidden() || pDef->GetQuality() == k_unItemQuality_Any )
  361. continue;
  362. // Only show in staging (internal dev branch):
  363. // - Normal quality items
  364. // - Items that haven't asked to be shown in the armory
  365. static const bool bIsStaging = ( engine->GetAppID() == 810 );
  366. if ( !bIsStaging )
  367. {
  368. if ( pDef->GetQuality() == AE_NORMAL || !pDef->ShouldShowInArmory() )
  369. continue;
  370. }
  371. // Make sure it's the right type of item
  372. int iDefSlot = pDef->GetDefaultLoadoutSlot();
  373. bool bValidSlot = false;
  374. if ( bWeapons )
  375. {
  376. bValidSlot = (iDefSlot == LOADOUT_POSITION_PRIMARY || iDefSlot == LOADOUT_POSITION_SECONDARY || iDefSlot == LOADOUT_POSITION_MELEE );
  377. if ( !bValidSlot )
  378. {
  379. bValidSlot = pDef->CanBePlacedInSlot(LOADOUT_POSITION_PRIMARY) || pDef->CanBePlacedInSlot(LOADOUT_POSITION_SECONDARY) || pDef->CanBePlacedInSlot(LOADOUT_POSITION_MELEE);
  380. }
  381. }
  382. else
  383. {
  384. bValidSlot = (iDefSlot == LOADOUT_POSITION_HEAD || iDefSlot == LOADOUT_POSITION_MISC );
  385. if ( !bValidSlot )
  386. {
  387. bValidSlot = pDef->CanBePlacedInSlot(LOADOUT_POSITION_HEAD) || pDef->CanBePlacedInSlot(LOADOUT_POSITION_MISC);
  388. }
  389. }
  390. if ( !bValidSlot )
  391. continue;
  392. // Make sure it's used by all the checked classes
  393. bool bUsable = false;
  394. if ( bClasses[0] )
  395. {
  396. bUsable = pDef->CanBeUsedByAllClasses();
  397. }
  398. else
  399. {
  400. bUsable = true;
  401. for ( int iClass = TF_FIRST_NORMAL_CLASS; iClass < TF_LAST_NORMAL_CLASS; iClass++ )
  402. {
  403. if ( bClasses[iClass] && !pDef->CanBeUsedByClass(iClass) )
  404. {
  405. bUsable = false;
  406. break;
  407. }
  408. }
  409. }
  410. if ( !bUsable )
  411. continue;
  412. if ( pItemDefs )
  413. {
  414. pItemDefs->AddToTail( pDef->GetDefinitionIndex() );
  415. }
  416. iReplaceableItems++;
  417. }
  418. return iReplaceableItems;
  419. }
  420. //-----------------------------------------------------------------------------
  421. // Purpose:
  422. //-----------------------------------------------------------------------------
  423. void CTestItemRoot::UpdateTestItems( void )
  424. {
  425. for ( int i = 0; i < TI_TYPE_COUNT; i++ )
  426. {
  427. // Weapon is handled specially, because it's tied to the class usage
  428. if ( i == TI_TYPE_WEAPON )
  429. {
  430. int iValidWeapons = FindReplaceableItemsForSelectedClass( NULL, true );
  431. m_pItemTestButtons[0]->SetEnabled( iValidWeapons );
  432. if ( !iValidWeapons )
  433. {
  434. m_pItemTestLabels[0]->SetText( g_pVGuiLocalize->Find("#IT_ItemReplaced_Invalid") );
  435. continue;
  436. }
  437. }
  438. if ( m_pItemTestKVs[i] )
  439. {
  440. m_pItemTestButtons[i]->SetText( "#IT_Item_Edit" );
  441. item_definition_index_t iExistingDef = m_pItemTestKVs[i]->GetInt( "existing_itemdef", INVALID_ITEM_DEF_INDEX );
  442. if ( iExistingDef != INVALID_ITEM_DEF_INDEX )
  443. {
  444. CEconItemDefinition *pDef = ItemSystem()->GetItemSchema()->GetItemDefinition(iExistingDef);
  445. if ( pDef )
  446. {
  447. m_pItemTestLabels[i]->SetText( g_pVGuiLocalize->Find( pDef->GetItemBaseName() ) );
  448. }
  449. else
  450. {
  451. m_pItemTestLabels[i]->SetText( "#IT_TestingSlot_Empty" );
  452. }
  453. }
  454. else
  455. {
  456. const char *pszModel = m_pItemTestKVs[i]->GetString("model_player", "#IT_TestingSlot_Empty");
  457. char szModel[MAX_PATH+1]="";
  458. Q_FileBase( pszModel, szModel, ARRAYSIZE( szModel ) );
  459. m_pItemTestLabels[i]->SetText( szModel );
  460. }
  461. m_pItemRemoveButtons[i]->SetEnabled( true );
  462. }
  463. else
  464. {
  465. m_pItemTestButtons[i]->SetText( "#IT_Item_Add" );
  466. m_pItemTestLabels[i]->SetText( "#IT_TestingSlot_Empty" );
  467. m_pItemRemoveButtons[i]->SetEnabled( false );
  468. }
  469. }
  470. // Hide the testing panel if we don't have any classes selected
  471. if ( m_pTestingPanel )
  472. {
  473. m_pTestingPanel->SetVisible( m_iClassUsage != 0 );
  474. }
  475. }
  476. //-----------------------------------------------------------------------------
  477. // Purpose:
  478. //-----------------------------------------------------------------------------
  479. void CTestItemRoot::CloseAndTestItem( void )
  480. {
  481. // Go through and update the schema definitions before we send them off to the server
  482. for ( int i = 0; i < TI_TYPE_COUNT; i++ )
  483. {
  484. if ( !m_pItemTestKVs[i] )
  485. continue;
  486. item_definition_index_t iNewDef = TESTITEM_DEFINITIONS_BEGIN_AT + i;
  487. item_definition_index_t iItemDef = m_pItemTestKVs[i]->GetInt( "item_replace", INVALID_ITEM_DEF_INDEX );
  488. ItemSystem()->GetItemSchema()->ItemTesting_CreateTestDefinition( iItemDef, iNewDef, m_pItemTestKVs[i] );
  489. m_pItemTestKVs[i]->SetInt( "item_def", iNewDef );
  490. }
  491. // Not connected to a game?
  492. if ( !TFGameRules() )
  493. return;
  494. CommitSettingsToKV();
  495. g_pRootItemTestingKV->SetName("TestItems");
  496. UpdateItemTestKVs();
  497. Close();
  498. }
  499. //-----------------------------------------------------------------------------
  500. // Purpose:
  501. //-----------------------------------------------------------------------------
  502. void CTestItemRoot::OnCommand( const char *command )
  503. {
  504. if ( !Q_stricmp( command, "cancel" ) )
  505. {
  506. Close();
  507. return;
  508. }
  509. else if ( !Q_stricmp( command, "ok" ) )
  510. {
  511. CloseAndTestItem();
  512. return;
  513. }
  514. else if ( !Q_stricmp( command, "steamworkshop" ) )
  515. {
  516. Close();
  517. engine->ClientCmd_Unrestricted( "OpenSteamWorkshopDialog;" );
  518. }
  519. else if ( !Q_stricmp( command, "reloadscheme" ) )
  520. {
  521. InvalidateLayout( false, true );
  522. return;
  523. }
  524. else if ( !Q_strnicmp( command, "item_test", 9 ) )
  525. {
  526. int iItemType = atoi( command+9 );
  527. if ( iItemType >= 0 && iItemType < TI_TYPE_COUNT )
  528. {
  529. if (!m_hEditItemDialog.Get())
  530. {
  531. m_hEditItemDialog = vgui::SETUP_PANEL( new CTestItemDialog( this, (testitem_itemtypes_t)iItemType, m_iClassUsage, m_pItemTestKVs[iItemType] ) );
  532. }
  533. m_hEditItemDialog->InvalidateLayout( false, true );
  534. m_hEditItemDialog->SetVisible( true );
  535. m_hEditItemDialog->MoveToFront();
  536. m_hEditItemDialog->SetKeyBoardInputEnabled(true);
  537. m_hEditItemDialog->SetMouseInputEnabled(true);
  538. TFModalStack()->PushModal( m_hEditItemDialog );
  539. }
  540. return;
  541. }
  542. else if ( !Q_strnicmp( command, "item_remove", 11 ) )
  543. {
  544. int iItemType = atoi( command+11 );
  545. if ( iItemType >= 0 && iItemType < TI_TYPE_COUNT )
  546. {
  547. if ( m_pItemTestKVs[iItemType] )
  548. {
  549. g_pRootItemTestingKV->RemoveSubKey( m_pItemTestKVs[iItemType] );
  550. m_pItemTestKVs[iItemType]->deleteThis();
  551. m_pItemTestKVs[iItemType] = NULL;
  552. }
  553. UpdateTestItems();
  554. }
  555. return;
  556. }
  557. else if ( !Q_stricmp( command, "export" ) || !Q_stricmp( command, "import" ) )
  558. {
  559. m_bExporting = ( command[0] == 'e' );
  560. if (m_hImportExportDialog == NULL)
  561. {
  562. m_hImportExportDialog = new vgui::FileOpenDialog( NULL, "#ToolCustomizeTextureTitle", m_bExporting ? vgui::FOD_SAVE : vgui::FOD_OPEN, NULL );
  563. m_hImportExportDialog->AddFilter( "*.itf", "#IT_TestingFiles", true );
  564. m_hImportExportDialog->AddActionSignalTarget( this );
  565. char szModelsDir[MAX_PATH];
  566. m_hImportExportDialog->SetStartDirectory( g_pFullFileSystem->RelativePathToFullPath( "cfg", "MOD", szModelsDir, sizeof(szModelsDir) ) );
  567. }
  568. m_hImportExportDialog->DoModal( false );
  569. m_hImportExportDialog->Activate();
  570. return;
  571. }
  572. else if ( !Q_stricmp( command, "importrecent" ) )
  573. {
  574. ImportTestSetup( tf_testitem_recent.GetString() );
  575. return;
  576. }
  577. else if ( !Q_stricmp( command, "bot_add" ) )
  578. {
  579. KeyValues *pKV = m_pBotSelectionComboBox->GetActiveItemUserData();
  580. int iClass = pKV->GetInt( "class", TF_CLASS_UNDEFINED );
  581. if ( iClass >= TF_FIRST_NORMAL_CLASS && iClass < TF_LAST_NORMAL_CLASS )
  582. {
  583. bool bBlueTeam = m_pBotsOnBlueTeamCheckBox->IsSelected();
  584. engine->ClientCmd_Unrestricted( VarArgs( "bot -team %s -class %s\n", bBlueTeam ? "blue" : "red", g_aPlayerClassNames_NonLocalized[iClass] ) );
  585. }
  586. return;
  587. }
  588. else if ( !Q_stricmp( command, "bot_removeall" ) )
  589. {
  590. // Kick everyone above the first player
  591. for ( int i = 2; i <= gpGlobals->maxClients; i++ )
  592. {
  593. C_BasePlayer *pPlayer = UTIL_PlayerByIndex( i );
  594. if ( pPlayer )
  595. {
  596. engine->ClientCmd_Unrestricted( VarArgs( "kickid %d\n", pPlayer->GetUserID() ) );
  597. }
  598. }
  599. return;
  600. }
  601. BaseClass::OnCommand( command );
  602. }
  603. static vgui::DHANDLE<CTestItemRoot> g_hTestItemRoot;
  604. //-----------------------------------------------------------------------------
  605. // Purpose:
  606. //-----------------------------------------------------------------------------
  607. void OpenTestItemRoot( void )
  608. {
  609. if (!g_hTestItemRoot.Get())
  610. {
  611. g_hTestItemRoot = vgui::SETUP_PANEL( new CTestItemRoot( NULL ) );
  612. }
  613. g_hTestItemRoot->SetVisible( true );
  614. g_hTestItemRoot->MakePopup();
  615. g_hTestItemRoot->MoveToFront();
  616. g_hTestItemRoot->SetKeyBoardInputEnabled(true);
  617. g_hTestItemRoot->SetMouseInputEnabled(true);
  618. TFModalStack()->PushModal( g_hTestItemRoot );
  619. g_hTestItemRoot->MakeReadyForUse();
  620. if ( g_pRootItemTestingKV )
  621. {
  622. g_hTestItemRoot->ImportTestSetup( g_pRootItemTestingKV );
  623. }
  624. }
  625. ConCommand testitem( "itemtest", OpenTestItemRoot, "Open the item testing panel.", FCVAR_NONE );
  626. //========================================================================================================================================
  627. // BOT CONTROLS PANEL
  628. //========================================================================================================================================
  629. static vgui::DHANDLE<CTestItemBotControls> g_hTestItemBotControls;
  630. //-----------------------------------------------------------------------------
  631. // Purpose:
  632. //-----------------------------------------------------------------------------
  633. CTestItemBotControls::CTestItemBotControls( vgui::Panel *parent ) : vgui::EditablePanel( parent, "TestItemBotControls" )
  634. {
  635. // Need to use the clientscheme (we're not parented to a clientscheme'd panel)
  636. vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
  637. SetScheme(scheme);
  638. SetProportional( true );
  639. ListenForGameEvent( "gameui_hidden" );
  640. m_pBotAnimationComboBox = new vgui::ComboBox( this, "BotAnimationComboBox", 9, false );
  641. m_pBotAnimationComboBox->AddActionSignalTarget( this );
  642. m_pBotForceFireCheckBox = new vgui::CheckButton( this, "BotForceFireCheckBox", "" );
  643. m_pBotForceFireCheckBox->AddActionSignalTarget( this );
  644. m_pBotTurntableCheckBox = new vgui::CheckButton( this, "BotTurntableCheckBox", "" );
  645. m_pBotTurntableCheckBox->AddActionSignalTarget( this );
  646. m_pBotViewScanCheckBox = new vgui::CheckButton( this, "BotViewScanCheckBox", "" );
  647. m_pBotViewScanCheckBox->AddActionSignalTarget( this );
  648. m_pBotAnimationSpeedSlider = new vgui::Slider( this, "BotAnimationSpeedSlider" );
  649. m_pBotAnimationSpeedSlider->SetRange( 0, 100 );
  650. m_pBotAnimationSpeedSlider->SetNumTicks( 10 );
  651. m_pBotAnimationSpeedSlider->AddActionSignalTarget( this );
  652. m_bEmbedded = false;
  653. SetupComboBoxes();
  654. if ( !g_pRootItemTestingKV )
  655. {
  656. g_pRootItemTestingKV = new KeyValues( "TestItems" );
  657. }
  658. }
  659. //-----------------------------------------------------------------------------
  660. // Purpose:
  661. //-----------------------------------------------------------------------------
  662. CTestItemBotControls::~CTestItemBotControls( void )
  663. {
  664. }
  665. //-----------------------------------------------------------------------------
  666. // Purpose:
  667. //-----------------------------------------------------------------------------
  668. void CTestItemBotControls::SetupComboBoxes( void )
  669. {
  670. KeyValues *pKeyValues;
  671. // Setup our bot animation combo box
  672. for ( int i = 0; i < TI_BOTANIM_COUNT; i++ )
  673. {
  674. pKeyValues = new KeyValues( "data" );
  675. pKeyValues->SetInt( "anim", i );
  676. m_pBotAnimationComboBox->AddItem( g_pszBotAnimStrings[i], pKeyValues );
  677. }
  678. m_pBotAnimationComboBox->SilentActivateItemByRow( 0 );
  679. }
  680. //-----------------------------------------------------------------------------
  681. // Purpose:
  682. //-----------------------------------------------------------------------------
  683. void CTestItemBotControls::FireGameEvent( IGameEvent *event )
  684. {
  685. const char *type = event->GetName();
  686. if ( Q_strcmp(type, "gameui_hidden") == 0 )
  687. {
  688. Close();
  689. }
  690. }
  691. //-----------------------------------------------------------------------------
  692. // Purpose:
  693. //-----------------------------------------------------------------------------
  694. void CTestItemBotControls::Close( void )
  695. {
  696. TFModalStack()->PopModal( this );
  697. SetVisible( false );
  698. MarkForDeletion();
  699. }
  700. //-----------------------------------------------------------------------------
  701. // Purpose:
  702. //-----------------------------------------------------------------------------
  703. void CTestItemBotControls::ImportTestSetup( KeyValues *pKV )
  704. {
  705. bool bForceFire = pKV->GetInt( "bot_force_fire", 0 );
  706. m_pBotForceFireCheckBox->SetSelected(bForceFire);
  707. bool bViewScan = pKV->GetInt( "bot_view_scan", 0 );
  708. m_pBotViewScanCheckBox->SetSelected(bViewScan);
  709. bool bTurnTable = pKV->GetInt( "bot_turntable", 0 );
  710. m_pBotTurntableCheckBox->SetSelected(bTurnTable);
  711. int iAnim = g_pRootItemTestingKV->GetInt( "bot_anim", TI_BOTANIM_IDLE );
  712. m_pBotAnimationComboBox->SilentActivateItemByRow( iAnim );
  713. int iAnimSpeed = g_pRootItemTestingKV->GetInt( "bot_animspeed", 100 );
  714. m_pBotAnimationSpeedSlider->SetValue( iAnimSpeed, false );
  715. }
  716. //-----------------------------------------------------------------------------
  717. // Purpose:
  718. //-----------------------------------------------------------------------------
  719. void CTestItemBotControls::ApplySchemeSettings( vgui::IScheme *pScheme )
  720. {
  721. BaseClass::ApplySchemeSettings( pScheme );
  722. LoadControlSettings( "resource/ui/TestItemBotControls.res" );
  723. // Dumb, but the slider needs to have its scheme forcibly loaded to make it create the left/right text
  724. m_pBotAnimationSpeedSlider->InvalidateLayout( true, true );
  725. }
  726. //-----------------------------------------------------------------------------
  727. // Purpose:
  728. //-----------------------------------------------------------------------------
  729. void CTestItemBotControls::PerformLayout( void )
  730. {
  731. BaseClass::PerformLayout();
  732. CExButton *pButton = dynamic_cast<CExButton*>( FindChildByName( "OkButton" ) );
  733. if ( pButton )
  734. {
  735. pButton->SetVisible( !m_bEmbedded );
  736. }
  737. pButton = dynamic_cast<CExButton*>( FindChildByName( "CloseButton" ) );
  738. if ( pButton )
  739. {
  740. pButton->SetVisible( !m_bEmbedded );
  741. }
  742. }
  743. //-----------------------------------------------------------------------------
  744. // Purpose:
  745. //-----------------------------------------------------------------------------
  746. void CTestItemBotControls::OnCommand( const char *command )
  747. {
  748. if ( !Q_stricmp( command, "cancel" ) )
  749. {
  750. Close();
  751. return;
  752. }
  753. else if ( !Q_stricmp( command, "ok" ) )
  754. {
  755. UpdateBots();
  756. return;
  757. }
  758. else if ( !Q_stricmp( command, "reloadscheme" ) )
  759. {
  760. InvalidateLayout( false, true );
  761. return;
  762. }
  763. BaseClass::OnCommand( command );
  764. }
  765. //-----------------------------------------------------------------------------
  766. // Purpose:
  767. //-----------------------------------------------------------------------------
  768. void CTestItemBotControls::UpdateBots( void )
  769. {
  770. // Not connected to a game?
  771. if ( !TFGameRules() )
  772. return;
  773. CommitSettingsToKV();
  774. g_pRootItemTestingKV->SetName("TestItemsBotUpdate");
  775. UpdateItemTestKVs();
  776. }
  777. //-----------------------------------------------------------------------------
  778. // Purpose:
  779. //-----------------------------------------------------------------------------
  780. void CTestItemBotControls::CommitSettingsToKV( void )
  781. {
  782. g_pRootItemTestingKV->SetInt( "bot_force_fire", m_pBotForceFireCheckBox->IsSelected() );
  783. g_pRootItemTestingKV->SetInt( "bot_view_scan", m_pBotViewScanCheckBox->IsSelected() );
  784. g_pRootItemTestingKV->SetInt( "bot_turntable", m_pBotTurntableCheckBox->IsSelected() );
  785. KeyValues *pKV = m_pBotAnimationComboBox->GetActiveItemUserData();
  786. int iAnim = pKV->GetInt( "anim", TI_BOTANIM_IDLE );
  787. g_pRootItemTestingKV->SetInt( "bot_anim", iAnim );
  788. int iAnimSpeed = clamp( m_pBotAnimationSpeedSlider->GetValue(), 0, 100 );
  789. g_pRootItemTestingKV->SetInt( "bot_animspeed", iAnimSpeed );
  790. }
  791. //-----------------------------------------------------------------------------
  792. // Purpose:
  793. //-----------------------------------------------------------------------------
  794. void OpenTestItemBotControls( void )
  795. {
  796. if (!g_hTestItemBotControls.Get())
  797. {
  798. g_hTestItemBotControls = vgui::SETUP_PANEL( new CTestItemBotControls( NULL ) );
  799. }
  800. g_hTestItemBotControls->SetVisible( true );
  801. g_hTestItemBotControls->MakePopup();
  802. g_hTestItemBotControls->MoveToFront();
  803. g_hTestItemBotControls->SetKeyBoardInputEnabled(true);
  804. g_hTestItemBotControls->SetMouseInputEnabled(true);
  805. TFModalStack()->PushModal( g_hTestItemBotControls );
  806. g_hTestItemBotControls->MakeReadyForUse();
  807. if ( g_pRootItemTestingKV )
  808. {
  809. g_hTestItemBotControls->ImportTestSetup( g_pRootItemTestingKV );
  810. g_hTestItemBotControls->SetEmbedded( false );
  811. }
  812. }
  813. ConCommand testitem_botcontrols( "itemtest_botcontrols", OpenTestItemBotControls, "Open the item testing bot control panel.", FCVAR_NONE );