Counter Strike : Global Offensive Source Code
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.

629 lines
16 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implements the big scary boom-boom machine Antlions fear.
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "EnvMessage.h"
  8. #include "fmtstr.h"
  9. #include "vguiscreen.h"
  10. #include "filesystem.h"
  11. // NOTE: This has to be the last file included!
  12. #include "tier0/memdbgon.h"
  13. #define SLIDESHOW_LIST_BUFFER_MAX 8192
  14. struct SlideKeywordList_t
  15. {
  16. char szSlideKeyword[64];
  17. };
  18. class CSlideshowDisplay : public CBaseEntity
  19. {
  20. public:
  21. DECLARE_CLASS( CSlideshowDisplay, CBaseEntity );
  22. DECLARE_DATADESC();
  23. DECLARE_SERVERCLASS();
  24. virtual ~CSlideshowDisplay();
  25. virtual bool KeyValue( const char *szKeyName, const char *szValue );
  26. virtual int UpdateTransmitState();
  27. virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways );
  28. virtual void Spawn( void );
  29. virtual void Precache( void );
  30. virtual void OnRestore( void );
  31. void ScreenVisible( bool bVisible );
  32. void Disable( void );
  33. void Enable( void );
  34. void InputDisable( inputdata_t &inputdata );
  35. void InputEnable( inputdata_t &inputdata );
  36. void InputSetDisplayText( inputdata_t &inputdata );
  37. void InputRemoveAllSlides( inputdata_t &inputdata );
  38. void InputAddSlides( inputdata_t &inputdata );
  39. void InputSetMinSlideTime( inputdata_t &inputdata );
  40. void InputSetMaxSlideTime( inputdata_t &inputdata );
  41. void InputSetCycleType( inputdata_t &inputdata );
  42. void InputSetNoListRepeats( inputdata_t &inputdata );
  43. private:
  44. // Control panel
  45. void GetControlPanelInfo( int nPanelIndex, const char *&pPanelName );
  46. void GetControlPanelClassName( int nPanelIndex, const char *&pPanelName );
  47. void SpawnControlPanels( void );
  48. void RestoreControlPanels( void );
  49. void BuildSlideShowImagesList( void );
  50. private:
  51. CNetworkVar( bool, m_bEnabled );
  52. CNetworkString( m_szDisplayText, 128 );
  53. CNetworkString( m_szSlideshowDirectory, 128 );
  54. string_t m_String_tSlideshowDirectory;
  55. CUtlVector<SlideKeywordList_t*> m_SlideKeywordList;
  56. CNetworkArray( unsigned char, m_chCurrentSlideLists, 16 );
  57. CNetworkVar( float, m_fMinSlideTime );
  58. CNetworkVar( float, m_fMaxSlideTime );
  59. CNetworkVar( int, m_iCycleType );
  60. CNetworkVar( bool, m_bNoListRepeats );
  61. int m_iScreenWidth;
  62. int m_iScreenHeight;
  63. bool m_bDoFullTransmit;
  64. typedef CHandle<CVGuiScreen> ScreenHandle_t;
  65. CUtlVector<ScreenHandle_t> m_hScreens;
  66. };
  67. LINK_ENTITY_TO_CLASS( vgui_slideshow_display, CSlideshowDisplay );
  68. //-----------------------------------------------------------------------------
  69. // Save/load
  70. //-----------------------------------------------------------------------------
  71. BEGIN_DATADESC( CSlideshowDisplay )
  72. DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ),
  73. DEFINE_AUTO_ARRAY_KEYFIELD( m_szDisplayText, FIELD_CHARACTER, "displaytext" ),
  74. DEFINE_AUTO_ARRAY( m_szSlideshowDirectory, FIELD_CHARACTER ),
  75. DEFINE_KEYFIELD( m_String_tSlideshowDirectory, FIELD_STRING, "directory" ),
  76. // DEFINE_FIELD( m_SlideKeywordList, CUtlVector < SlideKeywordList_t* > ),
  77. DEFINE_AUTO_ARRAY( m_chCurrentSlideLists, FIELD_CHARACTER ),
  78. DEFINE_KEYFIELD( m_fMinSlideTime, FIELD_FLOAT, "minslidetime" ),
  79. DEFINE_KEYFIELD( m_fMaxSlideTime, FIELD_FLOAT, "maxslidetime" ),
  80. DEFINE_KEYFIELD( m_iCycleType, FIELD_INTEGER, "cycletype" ),
  81. DEFINE_KEYFIELD( m_bNoListRepeats, FIELD_BOOLEAN, "nolistrepeats" ),
  82. DEFINE_KEYFIELD( m_iScreenWidth, FIELD_INTEGER, "width" ),
  83. DEFINE_KEYFIELD( m_iScreenHeight, FIELD_INTEGER, "height" ),
  84. //DEFINE_FIELD( m_bDoFullTransmit, FIELD_BOOLEAN ),
  85. //DEFINE_UTLVECTOR( m_hScreens, FIELD_EHANDLE ),
  86. DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
  87. DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
  88. DEFINE_INPUTFUNC( FIELD_STRING, "SetDisplayText", InputSetDisplayText ),
  89. DEFINE_INPUTFUNC( FIELD_VOID, "RemoveAllSlides", InputRemoveAllSlides ),
  90. DEFINE_INPUTFUNC( FIELD_STRING, "AddSlides", InputAddSlides ),
  91. DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMinSlideTime", InputSetMinSlideTime ),
  92. DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMaxSlideTime", InputSetMaxSlideTime ),
  93. DEFINE_INPUTFUNC( FIELD_INTEGER, "SetCycleType", InputSetCycleType ),
  94. DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetNoListRepeats", InputSetNoListRepeats ),
  95. END_DATADESC()
  96. IMPLEMENT_SERVERCLASS_ST( CSlideshowDisplay, DT_SlideshowDisplay )
  97. SendPropBool( SENDINFO(m_bEnabled) ),
  98. SendPropString( SENDINFO( m_szDisplayText ) ),
  99. SendPropString( SENDINFO( m_szSlideshowDirectory ) ),
  100. SendPropArray3( SENDINFO_ARRAY3(m_chCurrentSlideLists), SendPropInt( SENDINFO_ARRAY(m_chCurrentSlideLists), 8, SPROP_UNSIGNED ) ),
  101. SendPropFloat( SENDINFO(m_fMinSlideTime), 11, 0, 0.0f, 20.0f ),
  102. SendPropFloat( SENDINFO(m_fMaxSlideTime), 11, 0, 0.0f, 20.0f ),
  103. SendPropInt( SENDINFO(m_iCycleType), 2, SPROP_UNSIGNED ),
  104. SendPropBool( SENDINFO(m_bNoListRepeats) ),
  105. END_SEND_TABLE()
  106. CSlideshowDisplay::~CSlideshowDisplay()
  107. {
  108. int i;
  109. // Kill the control panels
  110. for ( i = m_hScreens.Count(); --i >= 0; )
  111. {
  112. DestroyVGuiScreen( m_hScreens[i].Get() );
  113. }
  114. m_hScreens.RemoveAll();
  115. }
  116. //-----------------------------------------------------------------------------
  117. // Read in worldcraft data...
  118. //-----------------------------------------------------------------------------
  119. bool CSlideshowDisplay::KeyValue( const char *szKeyName, const char *szValue )
  120. {
  121. //!! temp hack, until worldcraft is fixed
  122. // strip the # tokens from (duplicate) key names
  123. char *s = (char *)strchr( szKeyName, '#' );
  124. if ( s )
  125. {
  126. *s = '\0';
  127. }
  128. // NOTE: Have to do these separate because they set two values instead of one
  129. if( FStrEq( szKeyName, "angles" ) )
  130. {
  131. Assert( GetMoveParent() == NULL );
  132. QAngle angles;
  133. UTIL_StringToVector( angles.Base(), szValue );
  134. // Because the vgui screen basis is strange (z is front, y is up, x is right)
  135. // we need to rotate the typical basis before applying it
  136. VMatrix mat, rotation, tmp;
  137. MatrixFromAngles( angles, mat );
  138. MatrixBuildRotationAboutAxis( rotation, Vector( 0, 1, 0 ), 90 );
  139. MatrixMultiply( mat, rotation, tmp );
  140. MatrixBuildRotateZ( rotation, 90 );
  141. MatrixMultiply( tmp, rotation, mat );
  142. MatrixToAngles( mat, angles );
  143. SetAbsAngles( angles );
  144. return true;
  145. }
  146. return BaseClass::KeyValue( szKeyName, szValue );
  147. }
  148. int CSlideshowDisplay::UpdateTransmitState()
  149. {
  150. if ( m_bDoFullTransmit )
  151. {
  152. m_bDoFullTransmit = false;
  153. return SetTransmitState( FL_EDICT_ALWAYS );
  154. }
  155. return SetTransmitState( FL_EDICT_FULLCHECK );
  156. }
  157. void CSlideshowDisplay::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways )
  158. {
  159. // Are we already marked for transmission?
  160. if ( pInfo->m_pTransmitEdict->Get( entindex() ) )
  161. return;
  162. BaseClass::SetTransmit( pInfo, bAlways );
  163. // Force our screens to be sent too.
  164. for ( int i=0; i < m_hScreens.Count(); i++ )
  165. {
  166. CVGuiScreen *pScreen = m_hScreens[i].Get();
  167. pScreen->SetTransmit( pInfo, bAlways );
  168. }
  169. }
  170. void CSlideshowDisplay::Spawn( void )
  171. {
  172. Q_strcpy( m_szSlideshowDirectory.GetForModify(), m_String_tSlideshowDirectory.ToCStr() );
  173. Precache();
  174. BaseClass::Spawn();
  175. m_bEnabled = false;
  176. // Clear out selected list
  177. m_chCurrentSlideLists.GetForModify( 0 ) = 0; // Select all slides to begin with
  178. for ( int i = 1; i < 16; ++i )
  179. m_chCurrentSlideLists.GetForModify( i ) = (unsigned char)-1;
  180. SpawnControlPanels();
  181. ScreenVisible( m_bEnabled );
  182. m_bDoFullTransmit = true;
  183. }
  184. void CSlideshowDisplay::Precache( void )
  185. {
  186. BaseClass::Precache();
  187. BuildSlideShowImagesList();
  188. PrecacheVGuiScreen( "slideshow_display_screen" );
  189. }
  190. void CSlideshowDisplay::OnRestore( void )
  191. {
  192. BaseClass::OnRestore();
  193. BuildSlideShowImagesList();
  194. RestoreControlPanels();
  195. ScreenVisible( m_bEnabled );
  196. }
  197. void CSlideshowDisplay::ScreenVisible( bool bVisible )
  198. {
  199. for ( int iScreen = 0; iScreen < m_hScreens.Count(); ++iScreen )
  200. {
  201. CVGuiScreen *pScreen = m_hScreens[ iScreen ].Get();
  202. if ( bVisible )
  203. pScreen->RemoveEffects( EF_NODRAW );
  204. else
  205. pScreen->AddEffects( EF_NODRAW );
  206. }
  207. }
  208. void CSlideshowDisplay::Disable( void )
  209. {
  210. if ( !m_bEnabled )
  211. return;
  212. m_bEnabled = false;
  213. ScreenVisible( false );
  214. }
  215. void CSlideshowDisplay::Enable( void )
  216. {
  217. if ( m_bEnabled )
  218. return;
  219. m_bEnabled = true;
  220. ScreenVisible( true );
  221. }
  222. void CSlideshowDisplay::InputDisable( inputdata_t &inputdata )
  223. {
  224. Disable();
  225. }
  226. void CSlideshowDisplay::InputEnable( inputdata_t &inputdata )
  227. {
  228. Enable();
  229. }
  230. void CSlideshowDisplay::InputSetDisplayText( inputdata_t &inputdata )
  231. {
  232. Q_strcpy( m_szDisplayText.GetForModify(), inputdata.value.String() );
  233. }
  234. void CSlideshowDisplay::InputRemoveAllSlides( inputdata_t &inputdata )
  235. {
  236. // Clear out selected list
  237. for ( int i = 0; i < 16; ++i )
  238. m_chCurrentSlideLists.GetForModify( i ) = (unsigned char)-1;
  239. }
  240. void CSlideshowDisplay::InputAddSlides( inputdata_t &inputdata )
  241. {
  242. // Find the list with the current keyword
  243. int iList;
  244. for ( iList = 0; iList < m_SlideKeywordList.Count(); ++iList )
  245. {
  246. if ( Q_strcmp( m_SlideKeywordList[ iList ]->szSlideKeyword, inputdata.value.String() ) == 0 )
  247. break;
  248. }
  249. if ( iList < m_SlideKeywordList.Count() )
  250. {
  251. // Found the keyword list, so add this index to the selected lists
  252. int iNumCurrentSlideLists;
  253. for ( iNumCurrentSlideLists = 0; iNumCurrentSlideLists < 16; ++iNumCurrentSlideLists )
  254. {
  255. if ( m_chCurrentSlideLists[ iNumCurrentSlideLists ] == (unsigned char)-1 )
  256. break;
  257. }
  258. if ( iNumCurrentSlideLists >= 16 )
  259. return;
  260. m_chCurrentSlideLists.GetForModify( iNumCurrentSlideLists ) = iList;
  261. }
  262. }
  263. void CSlideshowDisplay::InputSetMinSlideTime( inputdata_t &inputdata )
  264. {
  265. m_fMinSlideTime = inputdata.value.Float();
  266. }
  267. void CSlideshowDisplay::InputSetMaxSlideTime( inputdata_t &inputdata )
  268. {
  269. m_fMaxSlideTime = inputdata.value.Float();
  270. }
  271. void CSlideshowDisplay::InputSetCycleType( inputdata_t &inputdata )
  272. {
  273. m_iCycleType = inputdata.value.Int();
  274. }
  275. void CSlideshowDisplay::InputSetNoListRepeats( inputdata_t &inputdata )
  276. {
  277. m_bNoListRepeats = inputdata.value.Bool();
  278. }
  279. void CSlideshowDisplay::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName )
  280. {
  281. pPanelName = "slideshow_display_screen";
  282. }
  283. void CSlideshowDisplay::GetControlPanelClassName( int nPanelIndex, const char *&pPanelName )
  284. {
  285. pPanelName = "vgui_screen";
  286. }
  287. //-----------------------------------------------------------------------------
  288. // This is called by the base object when it's time to spawn the control panels
  289. //-----------------------------------------------------------------------------
  290. void CSlideshowDisplay::SpawnControlPanels()
  291. {
  292. int nPanel;
  293. for ( nPanel = 0; true; ++nPanel )
  294. {
  295. const char *pScreenName;
  296. GetControlPanelInfo( nPanel, pScreenName );
  297. if (!pScreenName)
  298. continue;
  299. const char *pScreenClassname;
  300. GetControlPanelClassName( nPanel, pScreenClassname );
  301. if ( !pScreenClassname )
  302. continue;
  303. float flWidth = m_iScreenWidth;
  304. float flHeight = m_iScreenHeight;
  305. CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, this, this, 0 );
  306. pScreen->ChangeTeam( GetTeamNumber() );
  307. pScreen->SetActualSize( flWidth, flHeight );
  308. pScreen->SetActive( true );
  309. pScreen->MakeVisibleOnlyToTeammates( false );
  310. pScreen->SetTransparency( true );
  311. int nScreen = m_hScreens.AddToTail( );
  312. m_hScreens[nScreen].Set( pScreen );
  313. return;
  314. }
  315. }
  316. void CSlideshowDisplay::RestoreControlPanels( void )
  317. {
  318. int nPanel;
  319. for ( nPanel = 0; true; ++nPanel )
  320. {
  321. const char *pScreenName;
  322. GetControlPanelInfo( nPanel, pScreenName );
  323. if (!pScreenName)
  324. continue;
  325. const char *pScreenClassname;
  326. GetControlPanelClassName( nPanel, pScreenClassname );
  327. if ( !pScreenClassname )
  328. continue;
  329. CVGuiScreen *pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( NULL, pScreenClassname );
  330. while ( ( pScreen && pScreen->GetOwnerEntity() != this ) || Q_strcmp( pScreen->GetPanelName(), pScreenName ) != 0 )
  331. {
  332. pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( pScreen, pScreenClassname );
  333. }
  334. if ( pScreen )
  335. {
  336. int nScreen = m_hScreens.AddToTail( );
  337. m_hScreens[nScreen].Set( pScreen );
  338. pScreen->SetActive( true );
  339. }
  340. return;
  341. }
  342. }
  343. void CSlideshowDisplay::BuildSlideShowImagesList( void )
  344. {
  345. FileFindHandle_t matHandle;
  346. char szDirectory[_MAX_PATH];
  347. char szMatFileName[_MAX_PATH] = {'\0'};
  348. char szFileBuffer[ SLIDESHOW_LIST_BUFFER_MAX ];
  349. char *pchCurrentLine = NULL;
  350. if ( IsGameConsole() )
  351. {
  352. Q_snprintf( szDirectory, sizeof( szDirectory ), "materials/vgui/%s/slides.txt", m_szSlideshowDirectory.Get() );
  353. FileHandle_t fh = g_pFullFileSystem->Open( szDirectory, "rt" );
  354. if ( !fh )
  355. {
  356. DevWarning( "Couldn't read slideshow image file %s!", szDirectory );
  357. return;
  358. }
  359. int iFileSize = MIN( g_pFullFileSystem->Size( fh ), SLIDESHOW_LIST_BUFFER_MAX );
  360. int iBytesRead = g_pFullFileSystem->Read( szFileBuffer, iFileSize, fh );
  361. g_pFullFileSystem->Close( fh );
  362. // Ensure we don't write outside of our buffer
  363. if ( iBytesRead > iFileSize )
  364. iBytesRead = iFileSize;
  365. szFileBuffer[ iBytesRead ] = '\0';
  366. pchCurrentLine = szFileBuffer;
  367. // Seek to end of first line
  368. char *pchNextLine = pchCurrentLine;
  369. while ( *pchNextLine != '\0' && *pchNextLine != '\n' && *pchNextLine != ' ' )
  370. ++pchNextLine;
  371. if ( *pchNextLine != '\0' )
  372. {
  373. // Mark end of string
  374. *pchNextLine = '\0';
  375. // Seek to start of next string
  376. ++pchNextLine;
  377. while ( *pchNextLine != '\0' && ( *pchNextLine == '\n' || *pchNextLine == ' ' ) )
  378. ++pchNextLine;
  379. }
  380. Q_strncpy( szMatFileName, pchCurrentLine, sizeof(szMatFileName) );
  381. pchCurrentLine = pchNextLine;
  382. }
  383. else
  384. {
  385. Q_snprintf( szDirectory, sizeof( szDirectory ), "materials/vgui/%s/*.vmt", m_szSlideshowDirectory.Get() );
  386. const char *pMatFileName = g_pFullFileSystem->FindFirst( szDirectory, &matHandle );
  387. if ( pMatFileName )
  388. Q_strncpy( szMatFileName, pMatFileName, sizeof(szMatFileName) );
  389. }
  390. int iSlideIndex = 0;
  391. while ( szMatFileName[ 0 ] )
  392. {
  393. char szFileName[_MAX_PATH];
  394. Q_snprintf( szFileName, sizeof( szFileName ), "vgui/%s/%s", m_szSlideshowDirectory.Get(), szMatFileName );
  395. szFileName[ Q_strlen( szFileName ) - 4 ] = '\0';
  396. PrecacheMaterial( szFileName );
  397. // Get material keywords
  398. char szFullFileName[_MAX_PATH];
  399. Q_snprintf( szFullFileName, sizeof( szFullFileName ), "materials/vgui/%s/%s", m_szSlideshowDirectory.Get(), szMatFileName );
  400. KeyValues *pMaterialKeys = new KeyValues( "material" );
  401. bool bLoaded = pMaterialKeys->LoadFromFile( g_pFullFileSystem, szFullFileName, NULL );
  402. if ( bLoaded )
  403. {
  404. char szKeywords[ 256 ];
  405. Q_strcpy( szKeywords, pMaterialKeys->GetString( "%keywords", "" ) );
  406. char *pchKeyword = szKeywords;
  407. while ( pchKeyword[ 0 ] != '\0' )
  408. {
  409. char *pNextKeyword = pchKeyword;
  410. // Skip commas and spaces
  411. while ( pNextKeyword[ 0 ] != '\0' && pNextKeyword[ 0 ] != ',' )
  412. ++pNextKeyword;
  413. if ( pNextKeyword[ 0 ] != '\0' )
  414. {
  415. pNextKeyword[ 0 ] = '\0';
  416. ++pNextKeyword;
  417. while ( pNextKeyword[ 0 ] != '\0' && ( pNextKeyword[ 0 ] == ',' || pNextKeyword[ 0 ] == ' ' ) )
  418. ++pNextKeyword;
  419. }
  420. // Find the list with the current keyword
  421. int iList;
  422. for ( iList = 0; iList < m_SlideKeywordList.Count(); ++iList )
  423. {
  424. if ( Q_strcmp( m_SlideKeywordList[ iList ]->szSlideKeyword, pchKeyword ) == 0 )
  425. break;
  426. }
  427. if ( iList >= m_SlideKeywordList.Count() )
  428. {
  429. // Couldn't find the list, so create it
  430. iList = m_SlideKeywordList.AddToTail( new SlideKeywordList_t );
  431. Q_strcpy( m_SlideKeywordList[ iList ]->szSlideKeyword, pchKeyword );
  432. }
  433. pchKeyword = pNextKeyword;
  434. }
  435. }
  436. pMaterialKeys->deleteThis();
  437. pMaterialKeys = NULL;
  438. // Find the generic list
  439. int iList;
  440. for ( iList = 0; iList < m_SlideKeywordList.Count(); ++iList )
  441. {
  442. if ( Q_strcmp( m_SlideKeywordList[ iList ]->szSlideKeyword, "" ) == 0 )
  443. break;
  444. }
  445. if ( iList >= m_SlideKeywordList.Count() )
  446. {
  447. // Couldn't find the generic list, so create it
  448. iList = m_SlideKeywordList.AddToHead( new SlideKeywordList_t );
  449. Q_strcpy( m_SlideKeywordList[ iList ]->szSlideKeyword, "" );
  450. }
  451. if ( IsGameConsole() )
  452. {
  453. // Seek to end of first line
  454. char *pchNextLine = pchCurrentLine;
  455. while ( *pchNextLine != '\0' && *pchNextLine != '\n' && *pchNextLine != ' ' )
  456. ++pchNextLine;
  457. if ( *pchNextLine != '\0' )
  458. {
  459. // Mark end of string
  460. *pchNextLine = '\0';
  461. // Seek to start of next string
  462. ++pchNextLine;
  463. while ( *pchNextLine != '\0' && ( *pchNextLine == '\n' || *pchNextLine == ' ' ) )
  464. ++pchNextLine;
  465. }
  466. Q_strncpy( szMatFileName, pchCurrentLine, sizeof(szMatFileName) );
  467. pchCurrentLine = pchNextLine;
  468. }
  469. else
  470. {
  471. const char *pMatFileName = g_pFullFileSystem->FindNext( matHandle );
  472. if ( pMatFileName )
  473. Q_strncpy( szMatFileName, pMatFileName, sizeof(szMatFileName) );
  474. else
  475. szMatFileName[ 0 ] = '\0';
  476. }
  477. ++iSlideIndex;
  478. }
  479. if ( !IsGameConsole() )
  480. {
  481. g_pFullFileSystem->FindClose( matHandle );
  482. }
  483. }