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.

377 lines
10 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "c_slideshow_display.h"
  10. #include "c_te_legacytempents.h"
  11. #include "tempent.h"
  12. #include "engine/IEngineSound.h"
  13. #include "dlight.h"
  14. #include "iefx.h"
  15. #include "SoundEmitterSystem/isoundemittersystembase.h"
  16. #include "filesystem.h"
  17. #include "keyvalues.h"
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. #define SLIDESHOW_LIST_BUFFER_MAX 8192
  21. enum SlideshowCycleTypes
  22. {
  23. SLIDESHOW_CYCLE_RANDOM,
  24. SLIDESHOW_CYCLE_FORWARD,
  25. SLIDESHOW_CYCLE_BACKWARD,
  26. SLIDESHOW_CYCLE_TOTAL
  27. };
  28. CUtlVector< C_SlideshowDisplay* > g_SlideshowDisplays;
  29. IMPLEMENT_CLIENTCLASS_DT(C_SlideshowDisplay, DT_SlideshowDisplay, CSlideshowDisplay)
  30. RecvPropBool( RECVINFO(m_bEnabled) ),
  31. RecvPropString( RECVINFO( m_szDisplayText ) ),
  32. RecvPropString( RECVINFO( m_szSlideshowDirectory ) ),
  33. RecvPropArray3( RECVINFO_ARRAY(m_chCurrentSlideLists), RecvPropInt( RECVINFO(m_chCurrentSlideLists[0]) ) ),
  34. RecvPropFloat( RECVINFO(m_fMinSlideTime) ),
  35. RecvPropFloat( RECVINFO(m_fMaxSlideTime) ),
  36. RecvPropInt( RECVINFO(m_iCycleType) ),
  37. RecvPropBool( RECVINFO(m_bNoListRepeats) ),
  38. END_RECV_TABLE()
  39. C_SlideshowDisplay::C_SlideshowDisplay()
  40. {
  41. g_SlideshowDisplays.AddToTail( this );
  42. }
  43. C_SlideshowDisplay::~C_SlideshowDisplay()
  44. {
  45. g_SlideshowDisplays.FindAndRemove( this );
  46. }
  47. void C_SlideshowDisplay::Spawn( void )
  48. {
  49. BaseClass::Spawn();
  50. m_NextSlideTime = 0;
  51. SetNextClientThink( CLIENT_THINK_ALWAYS );
  52. }
  53. void C_SlideshowDisplay::OnDataChanged( DataUpdateType_t updateType )
  54. {
  55. BaseClass::OnDataChanged( updateType );
  56. if ( updateType == DATA_UPDATE_CREATED )
  57. {
  58. BuildSlideShowImagesList();
  59. }
  60. else if ( updateType == DATA_UPDATE_DATATABLE_CHANGED )
  61. {
  62. m_iCurrentSlideList = 0;
  63. m_iCurrentSlide = 0;
  64. }
  65. }
  66. int C_SlideshowDisplay::GetMaterialIndex( int iSlideIndex )
  67. {
  68. if ( !m_SlideMaterialLists[ 0 ] )
  69. return 0;
  70. return m_SlideMaterialLists[ 0 ]->iSlideMaterials[ iSlideIndex ];
  71. }
  72. int C_SlideshowDisplay::NumMaterials( void )
  73. {
  74. if ( !m_SlideMaterialLists[ 0 ] )
  75. return 0;
  76. return m_SlideMaterialLists[ 0 ]->iSlideMaterials.Count();
  77. }
  78. void C_SlideshowDisplay::ClientThink( void )
  79. {
  80. BaseClass::ClientThink();
  81. if ( !m_bEnabled )
  82. return;
  83. // Check if it's time for the next slide
  84. if ( m_NextSlideTime > gpGlobals->curtime )
  85. return;
  86. // Set the time to cycle to the next slide
  87. m_NextSlideTime = gpGlobals->curtime + RandomFloat( m_fMinSlideTime, m_fMaxSlideTime );
  88. // Get the amount of items to pick from
  89. int iNumCurrentSlideLists;
  90. for ( iNumCurrentSlideLists = 0; iNumCurrentSlideLists < 16; ++iNumCurrentSlideLists )
  91. {
  92. if ( m_chCurrentSlideLists[ iNumCurrentSlideLists ] == (unsigned char)-1 )
  93. break;
  94. }
  95. // Bail if no slide lists are selected
  96. if ( iNumCurrentSlideLists == 0 )
  97. return;
  98. // Cycle the list
  99. switch ( m_iCycleType )
  100. {
  101. case SLIDESHOW_CYCLE_RANDOM:
  102. {
  103. int iOldSlideList = m_iCurrentSlideList;
  104. m_iCurrentSlideList = RandomInt( 0, iNumCurrentSlideLists - 1 );
  105. // Prevent repeats if we don't want them
  106. if ( m_bNoListRepeats && iNumCurrentSlideLists > 1 && m_iCurrentSlideList == iOldSlideList )
  107. {
  108. ++m_iCurrentSlideList;
  109. if ( m_iCurrentSlideList >= iNumCurrentSlideLists )
  110. m_iCurrentSlideList = 0;
  111. }
  112. break;
  113. }
  114. case SLIDESHOW_CYCLE_FORWARD:
  115. if ( m_iCurrentSlideList >= iNumCurrentSlideLists )
  116. m_iCurrentSlideList = 0;
  117. break;
  118. case SLIDESHOW_CYCLE_BACKWARD:
  119. if ( m_iCurrentSlideList < 0 )
  120. m_iCurrentSlideList = iNumCurrentSlideLists - 1;
  121. break;
  122. }
  123. SlideMaterialList_t *pSlideMaterialList = m_SlideMaterialLists[ m_chCurrentSlideLists[ m_iCurrentSlideList ] ];
  124. // Cycle in the list
  125. switch ( m_iCycleType )
  126. {
  127. case SLIDESHOW_CYCLE_RANDOM:
  128. m_iCurrentSlide = RandomInt( 0, pSlideMaterialList->iSlideMaterials.Count() - 1 );
  129. break;
  130. case SLIDESHOW_CYCLE_FORWARD:
  131. ++m_iCurrentSlide;
  132. if ( m_iCurrentSlide >= pSlideMaterialList->iSlideMaterials.Count() )
  133. {
  134. ++m_iCurrentSlideList;
  135. if ( m_iCurrentSlideList >= iNumCurrentSlideLists )
  136. m_iCurrentSlideList = 0;
  137. pSlideMaterialList = m_SlideMaterialLists[ m_chCurrentSlideLists[ m_iCurrentSlideList ] ];
  138. m_iCurrentSlide = 0;
  139. }
  140. break;
  141. case SLIDESHOW_CYCLE_BACKWARD:
  142. --m_iCurrentSlide;
  143. if ( m_iCurrentSlide < 0 )
  144. {
  145. --m_iCurrentSlideList;
  146. if ( m_iCurrentSlideList < 0 )
  147. m_iCurrentSlideList = iNumCurrentSlideLists - 1;
  148. pSlideMaterialList = m_SlideMaterialLists[ m_chCurrentSlideLists[ m_iCurrentSlideList ] ];
  149. m_iCurrentSlide = pSlideMaterialList->iSlideMaterials.Count() - 1;
  150. }
  151. break;
  152. }
  153. // Set the current material to what we've cycled to
  154. m_iCurrentMaterialIndex = pSlideMaterialList->iSlideMaterials[ m_iCurrentSlide ];
  155. m_iCurrentSlideIndex = pSlideMaterialList->iSlideIndex[ m_iCurrentSlide ];
  156. }
  157. void C_SlideshowDisplay::BuildSlideShowImagesList( void )
  158. {
  159. FileFindHandle_t matHandle;
  160. char szDirectory[_MAX_PATH];
  161. char szMatFileName[_MAX_PATH] = {'\0'};
  162. char szFileBuffer[ SLIDESHOW_LIST_BUFFER_MAX ];
  163. char *pchCurrentLine = NULL;
  164. if ( IsGameConsole() )
  165. {
  166. Q_snprintf( szDirectory, sizeof( szDirectory ), "materials/vgui/%s/slides.txt", m_szSlideshowDirectory );
  167. FileHandle_t fh = g_pFullFileSystem->Open( szDirectory, "rt" );
  168. if ( !fh )
  169. {
  170. DevWarning( "Couldn't read slideshow image file %s!", szDirectory );
  171. return;
  172. }
  173. int iFileSize = MIN( g_pFullFileSystem->Size( fh ), SLIDESHOW_LIST_BUFFER_MAX );
  174. int iBytesRead = g_pFullFileSystem->Read( szFileBuffer, iFileSize, fh );
  175. g_pFullFileSystem->Close( fh );
  176. // Ensure we don't write outside of our buffer
  177. if ( iBytesRead > iFileSize )
  178. iBytesRead = iFileSize;
  179. szFileBuffer[ iBytesRead ] = '\0';
  180. pchCurrentLine = szFileBuffer;
  181. // Seek to end of first line
  182. char *pchNextLine = pchCurrentLine;
  183. while ( *pchNextLine != '\0' && *pchNextLine != '\n' && *pchNextLine != ' ' )
  184. ++pchNextLine;
  185. if ( *pchNextLine != '\0' )
  186. {
  187. // Mark end of string
  188. *pchNextLine = '\0';
  189. // Seek to start of next string
  190. ++pchNextLine;
  191. while ( *pchNextLine != '\0' && ( *pchNextLine == '\n' || *pchNextLine == ' ' ) )
  192. ++pchNextLine;
  193. }
  194. Q_strncpy( szMatFileName, pchCurrentLine, sizeof(szMatFileName) );
  195. pchCurrentLine = pchNextLine;
  196. }
  197. else
  198. {
  199. Q_snprintf( szDirectory, sizeof( szDirectory ), "materials/vgui/%s/*.vmt", m_szSlideshowDirectory );
  200. const char *pMatFileName = g_pFullFileSystem->FindFirst( szDirectory, &matHandle );
  201. if ( pMatFileName )
  202. Q_strncpy( szMatFileName, pMatFileName, sizeof(szMatFileName) );
  203. }
  204. int iSlideIndex = 0;
  205. while ( szMatFileName[ 0 ] )
  206. {
  207. char szFileName[_MAX_PATH];
  208. Q_snprintf( szFileName, sizeof( szFileName ), "vgui/%s/%s", m_szSlideshowDirectory, szMatFileName );
  209. szFileName[ Q_strlen( szFileName ) - 4 ] = '\0';
  210. int iMatIndex = ::GetMaterialIndex( szFileName );
  211. // Get material keywords
  212. char szFullFileName[_MAX_PATH];
  213. Q_snprintf( szFullFileName, sizeof( szFullFileName ), "materials/vgui/%s/%s", m_szSlideshowDirectory, szMatFileName );
  214. KeyValues *pMaterialKeys = new KeyValues( "material" );
  215. bool bLoaded = pMaterialKeys->LoadFromFile( g_pFullFileSystem, szFullFileName, NULL );
  216. if ( bLoaded )
  217. {
  218. char szKeywords[ 256 ];
  219. V_strcpy_safe( szKeywords, pMaterialKeys->GetString( "%keywords", "" ) );
  220. char *pchKeyword = szKeywords;
  221. while ( pchKeyword[ 0 ] != '\0' )
  222. {
  223. char *pNextKeyword = pchKeyword;
  224. // Skip commas and spaces
  225. while ( pNextKeyword[ 0 ] != '\0' && pNextKeyword[ 0 ] != ',' )
  226. ++pNextKeyword;
  227. if ( pNextKeyword[ 0 ] != '\0' )
  228. {
  229. pNextKeyword[ 0 ] = '\0';
  230. ++pNextKeyword;
  231. while ( pNextKeyword[ 0 ] != '\0' && ( pNextKeyword[ 0 ] == ',' || pNextKeyword[ 0 ] == ' ' ) )
  232. ++pNextKeyword;
  233. }
  234. // Find the list with the current keyword
  235. int iList;
  236. for ( iList = 0; iList < m_SlideMaterialLists.Count(); ++iList )
  237. {
  238. if ( Q_strcmp( m_SlideMaterialLists[ iList ]->szSlideKeyword, pchKeyword ) == 0 )
  239. break;
  240. }
  241. if ( iList >= m_SlideMaterialLists.Count() )
  242. {
  243. // Couldn't find the list, so create it
  244. iList = m_SlideMaterialLists.AddToTail( new SlideMaterialList_t );
  245. V_strcpy_safe( m_SlideMaterialLists[ iList ]->szSlideKeyword, pchKeyword );
  246. }
  247. // Add material index to this list
  248. m_SlideMaterialLists[ iList ]->iSlideMaterials.AddToTail( iMatIndex );
  249. m_SlideMaterialLists[ iList ]->iSlideIndex.AddToTail( iSlideIndex );
  250. pchKeyword = pNextKeyword;
  251. }
  252. }
  253. pMaterialKeys->deleteThis();
  254. pMaterialKeys = NULL;
  255. // Find the generic list
  256. int iList;
  257. for ( iList = 0; iList < m_SlideMaterialLists.Count(); ++iList )
  258. {
  259. if ( Q_strcmp( m_SlideMaterialLists[ iList ]->szSlideKeyword, "" ) == 0 )
  260. break;
  261. }
  262. if ( iList >= m_SlideMaterialLists.Count() )
  263. {
  264. // Couldn't find the generic list, so create it
  265. iList = m_SlideMaterialLists.AddToHead( new SlideMaterialList_t );
  266. V_strcpy_safe( m_SlideMaterialLists[ iList ]->szSlideKeyword, "" );
  267. }
  268. // Add material index to this list
  269. m_SlideMaterialLists[ iList ]->iSlideMaterials.AddToTail( iMatIndex );
  270. m_SlideMaterialLists[ iList ]->iSlideIndex.AddToTail( iSlideIndex );
  271. if ( IsGameConsole() )
  272. {
  273. // Seek to end of first line
  274. char *pchNextLine = pchCurrentLine;
  275. while ( *pchNextLine != '\0' && *pchNextLine != '\n' && *pchNextLine != ' ' )
  276. ++pchNextLine;
  277. if ( *pchNextLine != '\0' )
  278. {
  279. // Mark end of string
  280. *pchNextLine = '\0';
  281. // Seek to start of next string
  282. ++pchNextLine;
  283. while ( *pchNextLine != '\0' && ( *pchNextLine == '\n' || *pchNextLine == ' ' ) )
  284. ++pchNextLine;
  285. }
  286. Q_strncpy( szMatFileName, pchCurrentLine, sizeof(szMatFileName) );
  287. pchCurrentLine = pchNextLine;
  288. }
  289. else
  290. {
  291. const char *pMatFileName = g_pFullFileSystem->FindNext( matHandle );
  292. if ( pMatFileName )
  293. Q_strncpy( szMatFileName, pMatFileName, sizeof(szMatFileName) );
  294. else
  295. szMatFileName[ 0 ] = '\0';
  296. }
  297. ++iSlideIndex;
  298. }
  299. if ( !IsGameConsole() )
  300. {
  301. g_pFullFileSystem->FindClose( matHandle );
  302. }
  303. }