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.

989 lines
20 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. // CScriptObject and CDescription class definitions
  9. //
  10. #include "ScriptObject.h"
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include "EngineInterface.h"
  14. #include <vgui_controls/Label.h>
  15. #include "FileSystem.h"
  16. #include "tier1/convar.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. using namespace vgui;
  20. static char token[ 1024 ];
  21. void StripFloatTrailingZeros(char *str)
  22. {
  23. // scan for a '.'
  24. char *period = strchr(str, '.');
  25. if (!period)
  26. return;
  27. // start at the end and scan back to the period
  28. char *end = 0;
  29. for ( end = str + strlen(str) - 1; end > period; --end )
  30. {
  31. if (*end == '0')
  32. {
  33. *end = '\0';
  34. }
  35. else
  36. {
  37. // we've hit a real value, stop truncating
  38. break;
  39. }
  40. }
  41. // if we've made it up to the period, kill that to
  42. if ( *end == '.' )
  43. {
  44. *end = '\0';
  45. }
  46. }
  47. /////////////////////
  48. objtypedesc_t objtypes[] =
  49. {
  50. { O_BOOL , "BOOL" },
  51. { O_NUMBER, "NUMBER" },
  52. { O_LIST , "LIST" },
  53. { O_STRING, "STRING" },
  54. { O_OBSOLETE , "OBSOLETE" },
  55. };
  56. mpcontrol_t::mpcontrol_t( Panel *parent, char const *panelName )
  57. : Panel( parent, panelName )
  58. {
  59. type = O_BADTYPE;
  60. pControl = NULL;
  61. pPrompt = NULL;
  62. pScrObj = NULL;
  63. next = NULL;
  64. SetPaintBackgroundEnabled( false );
  65. }
  66. void mpcontrol_t::OnSizeChanged( int wide, int tall )
  67. {
  68. int inset = 4;
  69. if ( pPrompt )
  70. {
  71. int w = wide / 2;
  72. if ( pControl )
  73. {
  74. pControl->SetBounds( w + 20, inset, w - 20, tall - 2 * inset );
  75. }
  76. pPrompt->SetBounds( 0, inset, w + 20, tall - 2 * inset );
  77. }
  78. else
  79. {
  80. if ( pControl )
  81. {
  82. pControl->SetBounds( 0, inset, wide, tall - 2 * inset );
  83. }
  84. }
  85. }
  86. CScriptListItem::CScriptListItem()
  87. {
  88. pNext = NULL;
  89. memset( szItemText, 0, 128 );
  90. memset( szValue, 0, 256 );
  91. }
  92. CScriptListItem::CScriptListItem( char const *strItem, char const *strValue )
  93. {
  94. pNext = NULL;
  95. Q_strncpy( szItemText, strItem, sizeof( szItemText ) );
  96. Q_strncpy( szValue , strValue, sizeof( szValue ) );
  97. }
  98. CScriptObject::CScriptObject( void )
  99. {
  100. type = O_BOOL;
  101. bSetInfo = false; // Prepend "Setinfo" to keyvalue pair in config?
  102. pNext = NULL;
  103. pListItems = NULL;
  104. }
  105. CScriptObject::~CScriptObject()
  106. {
  107. CScriptListItem *p, *n;
  108. p = pListItems;
  109. while ( p )
  110. {
  111. n = p->pNext;
  112. delete p;
  113. p = n;
  114. }
  115. pListItems = NULL;
  116. }
  117. void CScriptObject::SetCurValue( char const *strValue )
  118. {
  119. Q_strncpy( curValue, strValue, sizeof( curValue ) );
  120. fcurValue = (float)atof( curValue );
  121. if ( type == O_NUMBER || type == O_BOOL )
  122. {
  123. StripFloatTrailingZeros( curValue );
  124. }
  125. }
  126. void CScriptObject::AddItem( CScriptListItem *pItem )
  127. {
  128. // Link it into the end of the list;
  129. CScriptListItem *p;
  130. p = pListItems;
  131. if ( !p )
  132. {
  133. pListItems = pItem;
  134. pItem->pNext = NULL;
  135. return;
  136. }
  137. while ( p )
  138. {
  139. if ( !p->pNext )
  140. {
  141. p->pNext = pItem;
  142. pItem->pNext = NULL;
  143. return;
  144. }
  145. p = p->pNext;
  146. }
  147. }
  148. /*
  149. ===================
  150. UTIL_StripInvalidCharacters
  151. Removes any possible formatting codes and double quote characters from the input string
  152. ===================
  153. */
  154. void UTIL_StripInvalidCharacters( char *pszInput, int maxlen )
  155. {
  156. char szOutput[4096];
  157. char *pIn, *pOut;
  158. pIn = pszInput;
  159. pOut = szOutput;
  160. *pOut = '\0';
  161. while ( *pIn )
  162. {
  163. if ( ( *pIn != '"' ) &&
  164. ( *pIn != '%' ) )
  165. {
  166. *pOut++ = *pIn;
  167. }
  168. pIn++;
  169. }
  170. *pOut = '\0';
  171. // Copy back over, in place
  172. Q_strncpy( pszInput, szOutput, maxlen );
  173. }
  174. void FixupString( char *inString, int maxlen )
  175. {
  176. char szBuffer[ 4096 ];
  177. Q_strncpy( szBuffer, inString, sizeof( szBuffer ) );
  178. UTIL_StripInvalidCharacters( szBuffer, sizeof( szBuffer ) );
  179. Q_strncpy( inString, szBuffer, maxlen );
  180. }
  181. /*
  182. ===================
  183. CleanFloat
  184. Removes any ".000" from the end of floats
  185. ===================
  186. */
  187. char * CleanFloat( float val )
  188. {
  189. static int curstring = 0;
  190. static char string[2][32];
  191. curstring = ( curstring + 1 ) % 2;
  192. Q_snprintf( string[curstring], sizeof( string[curstring] ), "%f", val );
  193. char * str = string[curstring];
  194. char * tmp = str;
  195. if ( !str || !*str || !strchr( str, '.' ) )
  196. return str;
  197. while ( *tmp )
  198. ++tmp;
  199. --tmp;
  200. while ( *tmp == '0' && tmp > str )
  201. {
  202. *tmp = 0;
  203. --tmp;
  204. }
  205. if ( *tmp == '.' )
  206. {
  207. *tmp = 0;
  208. }
  209. return str;
  210. }
  211. void CScriptObject::WriteToScriptFile( FileHandle_t fp )
  212. {
  213. if ( type == O_OBSOLETE )
  214. return;
  215. FixupString( cvarname, sizeof( cvarname ) );
  216. g_pFullFileSystem->FPrintf( fp, "\t\"%s\"\r\n", cvarname );
  217. g_pFullFileSystem->FPrintf( fp, "\t{\r\n" );
  218. CScriptListItem *pItem;
  219. FixupString( prompt, sizeof( prompt ) );
  220. switch ( type )
  221. {
  222. case O_BOOL:
  223. g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
  224. g_pFullFileSystem->FPrintf( fp, "\t\t{ BOOL }\r\n" );
  225. g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%i\" }\r\n", (int)fcurValue ? 1 : 0 );
  226. break;
  227. case O_NUMBER:
  228. g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
  229. g_pFullFileSystem->FPrintf( fp, "\t\t{ NUMBER %s %s }\r\n", CleanFloat(fMin), CleanFloat(fMax) );
  230. g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", CleanFloat(fcurValue) );
  231. break;
  232. case O_STRING:
  233. g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
  234. g_pFullFileSystem->FPrintf( fp, "\t\t{ STRING }\r\n" );
  235. FixupString( curValue, sizeof( curValue ) );
  236. g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", curValue );
  237. break;
  238. case O_LIST:
  239. g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt );
  240. g_pFullFileSystem->FPrintf( fp, "\t\t{\r\n\t\t\tLIST\r\n" );
  241. pItem = pListItems;
  242. while ( pItem )
  243. {
  244. UTIL_StripInvalidCharacters( pItem->szItemText, sizeof( pItem->szItemText ) );
  245. UTIL_StripInvalidCharacters( pItem->szValue, sizeof( pItem->szValue ) );
  246. g_pFullFileSystem->FPrintf( fp, "\t\t\t\"%s\" \"%s\"\r\n",
  247. pItem->szItemText, pItem->szValue );
  248. pItem = pItem->pNext;
  249. }
  250. g_pFullFileSystem->FPrintf( fp, "\t\t}\r\n");
  251. g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", CleanFloat(fcurValue) );
  252. break;
  253. }
  254. if ( bSetInfo )
  255. g_pFullFileSystem->FPrintf( fp, "\t\tSetInfo\r\n" );
  256. g_pFullFileSystem->FPrintf( fp, "\t}\r\n\r\n" );
  257. }
  258. void CScriptObject::WriteToFile( FileHandle_t fp )
  259. {
  260. if ( type == O_OBSOLETE )
  261. return;
  262. FixupString( cvarname, sizeof( cvarname ) );
  263. g_pFullFileSystem->FPrintf( fp, "\"%s\"\t\t", cvarname );
  264. CScriptListItem *pItem;
  265. int n, i;
  266. float fVal;
  267. switch ( type )
  268. {
  269. case O_BOOL:
  270. g_pFullFileSystem->FPrintf( fp, "\"%s\"\r\n", fcurValue != 0.0 ? "1" : "0" );
  271. break;
  272. case O_NUMBER:
  273. fVal = fcurValue;
  274. if ( fMin != -1.0 )
  275. fVal = MAX( fVal, fMin );
  276. if ( fMax != -1.0 )
  277. fVal = MIN( fVal, fMax );
  278. g_pFullFileSystem->FPrintf( fp, "\"%f\"\r\n", fVal );
  279. break;
  280. case O_STRING:
  281. FixupString( curValue, sizeof( curValue ) );
  282. g_pFullFileSystem->FPrintf( fp, "\"%s\"\r\n", curValue );
  283. break;
  284. case O_LIST:
  285. pItem = pListItems;
  286. n = (int)fcurValue;
  287. i = 0;
  288. while ( (i < n) && pItem )
  289. {
  290. i++;
  291. pItem = pItem->pNext;
  292. }
  293. if ( pItem )
  294. {
  295. UTIL_StripInvalidCharacters( pItem->szValue, sizeof( pItem->szValue ) );
  296. g_pFullFileSystem->FPrintf( fp, "\"%s\"\r\n", pItem->szValue );
  297. }
  298. else //Couln't find index
  299. {
  300. g_pFullFileSystem->FPrintf( fp, "\"0.0\"\r\n" );
  301. }
  302. break;
  303. }
  304. }
  305. void CScriptObject::WriteToConfig( void )
  306. {
  307. if ( type == O_OBSOLETE )
  308. return;
  309. char *pszKey;
  310. char szValue[2048];
  311. pszKey = ( char * )cvarname;
  312. CScriptListItem *pItem;
  313. int n, i;
  314. float fVal;
  315. switch ( type )
  316. {
  317. case O_BOOL:
  318. Q_snprintf( szValue, sizeof( szValue ), "%s", fcurValue != 0.0 ? "1" : "0" );
  319. break;
  320. case O_NUMBER:
  321. fVal = fcurValue;
  322. if ( fMin != -1.0 )
  323. fVal = MAX( fVal, fMin );
  324. if ( fMax != -1.0 )
  325. fVal = MIN( fVal, fMax );
  326. Q_snprintf( szValue, sizeof( szValue ), "%f", fVal );
  327. break;
  328. case O_STRING:
  329. Q_snprintf( szValue, sizeof( szValue ), "\"%s\"", (char *)curValue );
  330. UTIL_StripInvalidCharacters( szValue, sizeof( szValue ) );
  331. break;
  332. case O_LIST:
  333. pItem = pListItems;
  334. n = (int)fcurValue;
  335. i = 0;
  336. while ( (i < n) && pItem )
  337. {
  338. i++;
  339. pItem = pItem->pNext;
  340. }
  341. if ( pItem )
  342. {
  343. Q_snprintf( szValue, sizeof( szValue ), "%s", pItem->szValue );
  344. UTIL_StripInvalidCharacters( szValue, sizeof( szValue ) );
  345. }
  346. else //Couln't find index
  347. {
  348. Q_strncpy( szValue, "0.0", sizeof( szValue ) );
  349. }
  350. break;
  351. }
  352. char command[ 256 ];
  353. if ( bSetInfo )
  354. {
  355. Q_snprintf( command, sizeof(command), "setinfo %s \"%s\"\n", pszKey, szValue );
  356. }
  357. else
  358. {
  359. Q_snprintf( command, sizeof(command), "%s \"%s\"\n", pszKey, szValue );
  360. }
  361. engine->ClientCmd_Unrestricted( command );
  362. // CFG_SetKey( g_szCurrentConfigFile, pszKey, szValue, bSetInfo );
  363. }
  364. objtype_t CScriptObject::GetType( char *pszType )
  365. {
  366. int i;
  367. int nTypes;
  368. nTypes = sizeof( objtypes ) / sizeof( objtypedesc_t);
  369. for ( i = 0; i < nTypes; i++ )
  370. {
  371. if ( !stricmp( objtypes[i].szDescription, pszType ) )
  372. return objtypes[i].type;
  373. }
  374. return O_BADTYPE;
  375. }
  376. bool CScriptObject::ReadFromBuffer( const char **pBuffer, bool isNewObject )
  377. {
  378. // Get the first token.
  379. // The cvar we are setting
  380. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  381. if ( strlen( token ) <= 0 )
  382. return false;
  383. if ( isNewObject )
  384. {
  385. Q_strncpy( cvarname, token, sizeof( cvarname ) );
  386. }
  387. // Parse the {
  388. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  389. if ( strlen( token ) <= 0 )
  390. return false;
  391. if ( strcmp( token, "{" ) )
  392. {
  393. Msg( "Expecting '{', got '%s'", token );
  394. return false;
  395. }
  396. // Parse the Prompt
  397. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  398. if ( strlen( token ) <= 0 )
  399. return false;
  400. if ( isNewObject )
  401. {
  402. Q_strncpy( prompt, token, sizeof( prompt ) );
  403. }
  404. // Parse the next {
  405. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  406. if ( strlen( token ) <= 0 )
  407. return false;
  408. if ( strcmp( token, "{" ) )
  409. {
  410. Msg( "Expecting '{', got '%s'", token );
  411. return false;
  412. }
  413. // Now parse the type:
  414. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  415. if ( strlen( token ) <= 0 )
  416. return false;
  417. objtype_t newType = GetType( token );
  418. if ( isNewObject )
  419. {
  420. type = newType;
  421. }
  422. if ( newType == O_BADTYPE )
  423. {
  424. Msg( "Type '%s' unknown", token );
  425. return false;
  426. }
  427. switch ( newType )
  428. {
  429. case O_OBSOLETE:
  430. case O_BOOL:
  431. // Parse the next {
  432. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  433. if ( strlen( token ) <= 0 )
  434. return false;
  435. if ( strcmp( token, "}" ) )
  436. {
  437. Msg( "Expecting '{', got '%s'", token );
  438. return false;
  439. }
  440. break;
  441. case O_NUMBER:
  442. // Parse the Min
  443. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  444. if ( strlen( token ) <= 0 )
  445. return false;
  446. if ( isNewObject )
  447. {
  448. fMin = (float)atof( token );
  449. }
  450. // Parse the Min
  451. *pBuffer = engine->ParseFile( *pBuffer, token , sizeof( token ));
  452. if ( strlen( token ) <= 0 )
  453. return false;
  454. if ( isNewObject )
  455. {
  456. fMax = (float)atof( token );
  457. }
  458. // Parse the next {
  459. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  460. if ( strlen( token ) <= 0 )
  461. return false;
  462. if ( strcmp( token, "}" ) )
  463. {
  464. Msg( "Expecting '{', got '%s'", token );
  465. return false;
  466. }
  467. break;
  468. case O_STRING:
  469. // Parse the next {
  470. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  471. if ( strlen( token ) <= 0 )
  472. return false;
  473. if ( strcmp( token, "}" ) )
  474. {
  475. Msg( "Expecting '{', got '%s'", token );
  476. return false;
  477. }
  478. break;
  479. case O_LIST:
  480. // Parse items until we get the }
  481. while ( 1 )
  482. {
  483. // Parse the next {
  484. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  485. if ( strlen( token ) <= 0 )
  486. return false;
  487. // Done?
  488. if ( !strcmp( token, "}" ) )
  489. break;
  490. //
  491. // Add the item to a list somewhere
  492. // AddItem( token )
  493. char strItem[ 128 ];
  494. char strValue[128];
  495. Q_strncpy( strItem, token, sizeof( strItem ) );
  496. // Parse the value
  497. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  498. if ( strlen( token ) <= 0 )
  499. return false;
  500. Q_strncpy( strValue, token, sizeof( strValue ) );
  501. if ( isNewObject )
  502. {
  503. CScriptListItem *pItem;
  504. pItem = new CScriptListItem( strItem, strValue );
  505. AddItem( pItem );
  506. }
  507. }
  508. break;
  509. }
  510. //
  511. // Now read in the default value
  512. // Parse the {
  513. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  514. if ( strlen( token ) <= 0 )
  515. return false;
  516. if ( strcmp( token, "{" ) )
  517. {
  518. Msg( "Expecting '{', got '%s'", token );
  519. return false;
  520. }
  521. // Parse the default
  522. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  523. //if ( strlen( token ) <= 0 )
  524. // return false;
  525. // Set the values
  526. Q_strncpy( defValue, token, sizeof( defValue ) );
  527. fdefValue = (float)atof( token );
  528. if (type == O_NUMBER)
  529. {
  530. StripFloatTrailingZeros( defValue );
  531. }
  532. SetCurValue( defValue );
  533. // Parse the }
  534. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  535. if ( strlen( token ) <= 0 )
  536. return false;
  537. if ( strcmp( token, "}" ) )
  538. {
  539. Msg( "Expecting '{', got '%s'", token );
  540. return false;
  541. }
  542. // Parse the final }
  543. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  544. if ( strlen( token ) <= 0 )
  545. return false;
  546. if ( !stricmp( token, "SetInfo" ) )
  547. {
  548. bSetInfo = true;
  549. // Parse the final }
  550. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  551. if ( strlen( token ) <= 0 )
  552. return false;
  553. }
  554. if ( strcmp( token, "}" ) )
  555. {
  556. Msg( "Expecting '{', got '%s'", token );
  557. return false;
  558. }
  559. return true;
  560. }
  561. /////////////////////////
  562. CDescription::CDescription( CPanelListPanel *panel )
  563. {
  564. pObjList = NULL;
  565. m_pListPanel = panel;
  566. }
  567. CDescription::~CDescription()
  568. {
  569. CScriptObject *p, *n;
  570. p = pObjList;
  571. while ( p )
  572. {
  573. n = p->pNext;
  574. p->pNext = NULL;
  575. p->MarkForDeletion();
  576. //delete p;
  577. p = n;
  578. }
  579. pObjList = NULL;
  580. if ( m_pszHintText )
  581. free( m_pszHintText );
  582. if ( m_pszDescriptionType )
  583. free( m_pszDescriptionType );
  584. }
  585. CScriptObject * CDescription::FindObject( const char *pszObjectName )
  586. {
  587. if ( !pszObjectName )
  588. return NULL;
  589. CScriptObject *p;
  590. p = pObjList;
  591. while ( p )
  592. {
  593. if ( !stricmp( pszObjectName, p->cvarname ) )
  594. return p;
  595. p = p->pNext;
  596. }
  597. return NULL;
  598. }
  599. void CDescription::AddObject( CScriptObject *pObj )
  600. {
  601. CScriptObject *p;
  602. p = pObjList;
  603. if ( !p )
  604. {
  605. pObjList = pObj;
  606. pObj->pNext = NULL;
  607. return;
  608. }
  609. while ( p )
  610. {
  611. if ( !p->pNext )
  612. {
  613. p->pNext = pObj;
  614. pObj->pNext = NULL;
  615. return;
  616. }
  617. p = p->pNext;
  618. }
  619. }
  620. bool CDescription::ReadFromBuffer( const char **pBuffer )
  621. {
  622. // Get the first token.
  623. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  624. if ( strlen( token ) <= 0 )
  625. return false;
  626. // Read VERSION #
  627. if ( stricmp ( token, "VERSION" ) )
  628. {
  629. Msg( "Expecting 'VERSION', got '%s'", token );
  630. return false;
  631. }
  632. // Parse in the version #
  633. // Get the first token.
  634. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  635. if ( strlen( token ) <= 0 )
  636. {
  637. Msg( "Expecting version #" );
  638. return false;
  639. }
  640. float fVer;
  641. fVer = (float)atof( token );
  642. if ( fVer != SCRIPT_VERSION )
  643. {
  644. Msg( "Version mismatch, expecting %f, got %f", SCRIPT_VERSION, fVer );
  645. return false;
  646. }
  647. // Get the "DESCRIPTION"
  648. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  649. if ( strlen( token ) <= 0 )
  650. return false;
  651. // Read DESCRIPTION
  652. if ( stricmp ( token, "DESCRIPTION" ) )
  653. {
  654. Msg( "Expecting 'DESCRIPTION', got '%s'", token );
  655. return false;
  656. }
  657. // Parse in the description type
  658. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  659. if ( strlen( token ) <= 0 )
  660. {
  661. Msg( "Expecting '%s'", m_pszDescriptionType );
  662. return false;
  663. }
  664. if ( stricmp ( token, m_pszDescriptionType ) )
  665. {
  666. Msg( "Expecting %s, got %s", m_pszDescriptionType, token );
  667. return false;
  668. }
  669. // Parse the {
  670. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  671. if ( strlen( token ) <= 0 )
  672. return false;
  673. if ( strcmp( token, "{" ) )
  674. {
  675. Msg( "Expecting '{', got '%s'", token );
  676. return false;
  677. }
  678. const char *pStart;
  679. CScriptObject *pObj;
  680. // Now read in the objects and link them in
  681. while ( 1 )
  682. {
  683. pStart = *pBuffer;
  684. // Get the first token.
  685. *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) );
  686. if ( strlen( token ) <= 0 )
  687. return false;
  688. // Read "cvar name" or } when done
  689. if ( !stricmp ( token, "}" ) )
  690. break;
  691. // Unget the token
  692. *pBuffer = pStart;
  693. // Create a new object
  694. bool mustAdd = true;
  695. pObj = FindObject( token );
  696. if ( pObj )
  697. {
  698. pObj->ReadFromBuffer( &pStart, false );
  699. mustAdd = false; // already in list
  700. }
  701. else
  702. {
  703. pObj = new CScriptObject();
  704. if ( !pObj )
  705. {
  706. Msg( "Couldn't create script object" );
  707. return false;
  708. }
  709. if ( !pObj->ReadFromBuffer( &pStart, true ) )
  710. {
  711. delete pObj;
  712. return false;
  713. }
  714. }
  715. *pBuffer = pStart;
  716. // Add to list
  717. // Fixme, move to end of list first
  718. if ( mustAdd )
  719. {
  720. AddObject( pObj );
  721. }
  722. }
  723. return true;
  724. }
  725. bool CDescription::InitFromFile( char *pszFileName )
  726. {
  727. // Load file into memory
  728. FileHandle_t file = g_pFullFileSystem->Open( pszFileName, "rb" );
  729. if ( !file )
  730. return false;
  731. int len =g_pFullFileSystem->Size( file );
  732. // read the file
  733. byte *buffer = new unsigned char[ len ];
  734. Assert( buffer );
  735. g_pFullFileSystem->Read( buffer, len, file );
  736. g_pFullFileSystem->Close( file );
  737. const char *pBuffer = (const char*)buffer;
  738. ReadFromBuffer( &pBuffer );
  739. delete[] buffer;
  740. return true;
  741. }
  742. void CDescription::WriteToFile( FileHandle_t fp )
  743. {
  744. CScriptObject *pObj;
  745. WriteFileHeader( fp );
  746. pObj = pObjList;
  747. while ( pObj )
  748. {
  749. pObj->WriteToFile( fp );
  750. pObj = pObj->pNext;
  751. }
  752. }
  753. void CDescription::WriteToConfig( void )
  754. {
  755. CScriptObject *pObj;
  756. pObj = pObjList;
  757. while ( pObj )
  758. {
  759. pObj->WriteToConfig();
  760. pObj = pObj->pNext;
  761. }
  762. }
  763. void CDescription::WriteToScriptFile( FileHandle_t fp )
  764. {
  765. CScriptObject *pObj;
  766. WriteScriptHeader( fp );
  767. pObj = pObjList;
  768. while ( pObj )
  769. {
  770. pObj->WriteToScriptFile( fp );
  771. pObj = pObj->pNext;
  772. }
  773. g_pFullFileSystem->FPrintf( fp, "}\r\n" );
  774. }
  775. void CDescription::TransferCurrentValues( const char *pszConfigFile )
  776. {
  777. char szValue[ 1024 ];
  778. CScriptObject *pObj;
  779. pObj = pObjList;
  780. while ( pObj )
  781. {
  782. /*
  783. TODO: if/when prefixed keys are implemented
  784. const char *value;
  785. if ( pObj->bSetInfo )
  786. {
  787. value = engine->LocalPlayerInfo_ValueForKey( pObj->cvarname ); // use LocalPlayerInfo because PlayerInfo strips keys prefixed with "_"
  788. }
  789. else
  790. {
  791. value = engine->pfnGetCvarString( pObj->cvarname );
  792. }
  793. */
  794. ConVarRef var( pObj->cvarname );
  795. if ( !var.IsValid() )
  796. {
  797. DevMsg( "Could not find '%s'\n", pObj->cvarname );
  798. pObj = pObj->pNext;
  799. continue;
  800. }
  801. const char *value = var.GetString();
  802. if ( value && value[ 0 ] )
  803. //if ( CFG_GetValue( pszConfigFile, pObj->cvarname, szValue ) )
  804. {
  805. Q_strncpy( szValue, value, sizeof( szValue ) );
  806. // Fill in better default value
  807. //
  808. Q_strncpy( pObj->curValue, szValue, sizeof( pObj->curValue ) );
  809. pObj->fcurValue = (float)atof( szValue );
  810. Q_strncpy( pObj->defValue, szValue, sizeof( pObj->defValue ) );
  811. pObj->fdefValue = (float)atof( szValue );
  812. }
  813. pObj = pObj->pNext;
  814. }
  815. }
  816. void CDescription::setDescription( const char *pszDesc )
  817. {
  818. m_pszDescriptionType = strdup( pszDesc );
  819. }
  820. void CDescription::setHint( const char *pszHint )
  821. {
  822. m_pszHintText = strdup( pszHint );
  823. }