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.

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