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.

940 lines
20 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "vcollide_parse_private.h"
  10. #include "tier1/strtools.h"
  11. #include "vphysics/constraints.h"
  12. #include "vphysics/vehicles.h"
  13. #include "filesystem_helpers.h"
  14. #include "bspfile.h"
  15. #include "utlbuffer.h"
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. static void ReadVector( const char *pString, Vector& out )
  19. {
  20. float x, y, z;
  21. sscanf( pString, "%f %f %f", &x, &y, &z );
  22. out[0] = x;
  23. out[1] = y;
  24. out[2] = z;
  25. }
  26. static void ReadAngles( const char *pString, QAngle& out )
  27. {
  28. float x, y, z;
  29. sscanf( pString, "%f %f %f", &x, &y, &z );
  30. out[0] = x;
  31. out[1] = y;
  32. out[2] = z;
  33. }
  34. static void ReadVector4D( const char *pString, Vector4D& out )
  35. {
  36. float x, y, z, w;
  37. sscanf( pString, "%f %f %f %f", &x, &y, &z, &w );
  38. out[0] = x;
  39. out[1] = y;
  40. out[2] = z;
  41. out[3] = w;
  42. }
  43. class CVPhysicsParse : public IVPhysicsKeyParser
  44. {
  45. public:
  46. ~CVPhysicsParse() {}
  47. CVPhysicsParse( const char *pKeyData );
  48. void NextBlock( void );
  49. const char *GetCurrentBlockName( void );
  50. bool Finished( void );
  51. void ParseSolid( solid_t *pSolid, IVPhysicsKeyHandler *unknownKeyHandler );
  52. void ParseFluid( fluid_t *pFluid, IVPhysicsKeyHandler *unknownKeyHandler );
  53. void ParseRagdollConstraint( constraint_ragdollparams_t *pConstraint, IVPhysicsKeyHandler *unknownKeyHandler );
  54. void ParseSurfaceTable( int *table, IVPhysicsKeyHandler *unknownKeyHandler );
  55. void ParseSurfaceTablePacked( CUtlVector<char> &out );
  56. void ParseVehicle( vehicleparams_t *pVehicle, IVPhysicsKeyHandler *unknownKeyHandler );
  57. void ParseCustom( void *pCustom, IVPhysicsKeyHandler *unknownKeyHandler );
  58. void SkipBlock( void ) { ParseCustom(NULL, NULL); }
  59. private:
  60. void ParseVehicleAxle( vehicle_axleparams_t &axle );
  61. void ParseVehicleWheel( vehicle_wheelparams_t &wheel );
  62. void ParseVehicleSuspension( vehicle_suspensionparams_t &suspension );
  63. void ParseVehicleBody( vehicle_bodyparams_t &body );
  64. void ParseVehicleEngine( vehicle_engineparams_t &engine );
  65. void ParseVehicleEngineBoost( vehicle_engineparams_t &engine );
  66. void ParseVehicleSteering( vehicle_steeringparams_t &steering );
  67. const char *m_pText;
  68. char m_blockName[MAX_KEYVALUE];
  69. };
  70. CVPhysicsParse::CVPhysicsParse( const char *pKeyData )
  71. {
  72. m_pText = pKeyData;
  73. NextBlock();
  74. }
  75. void CVPhysicsParse::NextBlock( void )
  76. {
  77. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  78. while ( m_pText )
  79. {
  80. m_pText = ParseKeyvalue( m_pText, key, value );
  81. if ( !Q_strcmp(value, "{") )
  82. {
  83. V_strcpy_safe( m_blockName, key );
  84. return;
  85. }
  86. }
  87. // Make sure m_blockName is initialized -- should this be done?
  88. m_blockName[ 0 ] = 0;
  89. }
  90. const char *CVPhysicsParse::GetCurrentBlockName( void )
  91. {
  92. if ( m_pText )
  93. return m_blockName;
  94. return NULL;
  95. }
  96. bool CVPhysicsParse::Finished( void )
  97. {
  98. if ( m_pText )
  99. return false;
  100. return true;
  101. }
  102. void CVPhysicsParse::ParseSolid( solid_t *pSolid, IVPhysicsKeyHandler *unknownKeyHandler )
  103. {
  104. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  105. key[0] = 0;
  106. if ( unknownKeyHandler )
  107. {
  108. unknownKeyHandler->SetDefaults( pSolid );
  109. }
  110. else
  111. {
  112. memset( pSolid, 0, sizeof(*pSolid) );
  113. }
  114. // disable these until the ragdoll is created
  115. pSolid->params.enableCollisions = false;
  116. while ( m_pText )
  117. {
  118. m_pText = ParseKeyvalue( m_pText, key, value );
  119. if ( key[0] == '}' )
  120. {
  121. NextBlock();
  122. return;
  123. }
  124. if ( !Q_stricmp( key, "index" ) )
  125. {
  126. pSolid->index = atoi(value);
  127. }
  128. else if ( !Q_stricmp( key, "name" ) )
  129. {
  130. Q_strncpy( pSolid->name, value, sizeof(pSolid->name) );
  131. }
  132. else if ( !Q_stricmp( key, "parent" ) )
  133. {
  134. Q_strncpy( pSolid->parent, value, sizeof(pSolid->parent) );
  135. }
  136. else if ( !Q_stricmp( key, "surfaceprop" ) )
  137. {
  138. Q_strncpy( pSolid->surfaceprop, value, sizeof(pSolid->surfaceprop) );
  139. }
  140. else if ( !Q_stricmp( key, "mass" ) )
  141. {
  142. pSolid->params.mass = atof(value);
  143. }
  144. else if ( !Q_stricmp( key, "massCenterOverride" ) )
  145. {
  146. ReadVector( value, pSolid->massCenterOverride );
  147. pSolid->params.massCenterOverride = &pSolid->massCenterOverride;
  148. }
  149. else if ( !Q_stricmp( key, "inertia" ) )
  150. {
  151. pSolid->params.inertia = atof(value);
  152. }
  153. else if ( !Q_stricmp( key, "damping" ) )
  154. {
  155. pSolid->params.damping = atof(value);
  156. }
  157. else if ( !Q_stricmp( key, "rotdamping" ) )
  158. {
  159. pSolid->params.rotdamping = atof(value);
  160. }
  161. else if ( !Q_stricmp( key, "volume" ) )
  162. {
  163. pSolid->params.volume = atof(value);
  164. }
  165. else if ( !Q_stricmp( key, "drag" ) )
  166. {
  167. pSolid->params.dragCoefficient = atof(value);
  168. }
  169. else if ( !Q_stricmp( key, "rollingdrag" ) )
  170. {
  171. //pSolid->params.rollingDrag = atof(value);
  172. }
  173. else
  174. {
  175. if ( unknownKeyHandler )
  176. {
  177. unknownKeyHandler->ParseKeyValue( pSolid, key, value );
  178. }
  179. }
  180. }
  181. }
  182. void CVPhysicsParse::ParseRagdollConstraint( constraint_ragdollparams_t *pConstraint, IVPhysicsKeyHandler *unknownKeyHandler )
  183. {
  184. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  185. key[0] = 0;
  186. if ( unknownKeyHandler )
  187. {
  188. unknownKeyHandler->SetDefaults( pConstraint );
  189. }
  190. else
  191. {
  192. memset( pConstraint, 0, sizeof(*pConstraint) );
  193. pConstraint->childIndex = -1;
  194. pConstraint->parentIndex = -1;
  195. }
  196. // BUGBUG: xmin/xmax, ymin/ymax, zmin/zmax specify clockwise rotations.
  197. // BUGBUG: HL rotations are counter-clockwise, so reverse these limits at some point!!!
  198. pConstraint->useClockwiseRotations = true;
  199. while ( m_pText )
  200. {
  201. m_pText = ParseKeyvalue( m_pText, key, value );
  202. if ( key[0] == '}' )
  203. {
  204. NextBlock();
  205. return;
  206. }
  207. if ( !Q_stricmp( key, "parent" ) )
  208. {
  209. pConstraint->parentIndex = atoi( value );
  210. }
  211. else if ( !Q_stricmp( key, "child" ) )
  212. {
  213. pConstraint->childIndex = atoi( value );
  214. }
  215. else if ( !Q_stricmp( key, "xmin" ) )
  216. {
  217. pConstraint->axes[0].minRotation = atof( value );
  218. }
  219. else if ( !Q_stricmp( key, "xmax" ) )
  220. {
  221. pConstraint->axes[0].maxRotation = atof( value );
  222. }
  223. else if ( !Q_stricmp( key, "xfriction" ) )
  224. {
  225. pConstraint->axes[0].angularVelocity = 0;
  226. pConstraint->axes[0].torque = atof( value );
  227. }
  228. else if ( !Q_stricmp( key, "ymin" ) )
  229. {
  230. pConstraint->axes[1].minRotation = atof( value );
  231. }
  232. else if ( !Q_stricmp( key, "ymax" ) )
  233. {
  234. pConstraint->axes[1].maxRotation = atof( value );
  235. }
  236. else if ( !Q_stricmp( key, "yfriction" ) )
  237. {
  238. pConstraint->axes[1].angularVelocity = 0;
  239. pConstraint->axes[1].torque = atof( value );
  240. }
  241. else if ( !Q_stricmp( key, "zmin" ) )
  242. {
  243. pConstraint->axes[2].minRotation = atof( value );
  244. }
  245. else if ( !Q_stricmp( key, "zmax" ) )
  246. {
  247. pConstraint->axes[2].maxRotation = atof( value );
  248. }
  249. else if ( !Q_stricmp( key, "zfriction" ) )
  250. {
  251. pConstraint->axes[2].angularVelocity = 0;
  252. pConstraint->axes[2].torque = atof( value );
  253. }
  254. else
  255. {
  256. if ( unknownKeyHandler )
  257. {
  258. unknownKeyHandler->ParseKeyValue( pConstraint, key, value );
  259. }
  260. }
  261. }
  262. }
  263. void CVPhysicsParse::ParseFluid( fluid_t *pFluid, IVPhysicsKeyHandler *unknownKeyHandler )
  264. {
  265. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  266. key[0] = 0;
  267. pFluid->index = -1;
  268. if ( unknownKeyHandler )
  269. {
  270. unknownKeyHandler->SetDefaults( pFluid );
  271. }
  272. else
  273. {
  274. memset( pFluid, 0, sizeof(*pFluid) );
  275. // HACKHACK: This is a reasonable default even though it is hardcoded
  276. V_strcpy_safe( pFluid->surfaceprop, "water" );
  277. }
  278. while ( m_pText )
  279. {
  280. m_pText = ParseKeyvalue( m_pText, key, value );
  281. if ( key[0] == '}' )
  282. {
  283. NextBlock();
  284. return;
  285. }
  286. if ( !Q_stricmp( key, "index" ) )
  287. {
  288. pFluid->index = atoi( value );
  289. }
  290. else if ( !Q_stricmp( key, "damping" ) )
  291. {
  292. pFluid->params.damping = atof( value );
  293. }
  294. else if ( !Q_stricmp( key, "surfaceplane" ) )
  295. {
  296. ReadVector4D( value, pFluid->params.surfacePlane );
  297. }
  298. else if ( !Q_stricmp( key, "currentvelocity" ) )
  299. {
  300. ReadVector( value, pFluid->params.currentVelocity );
  301. }
  302. else if ( !Q_stricmp( key, "contents" ) )
  303. {
  304. pFluid->params.contents = atoi( value );
  305. }
  306. else if ( !Q_stricmp( key, "surfaceprop" ) )
  307. {
  308. Q_strncpy( pFluid->surfaceprop, value, sizeof(pFluid->surfaceprop) );
  309. }
  310. else
  311. {
  312. if ( unknownKeyHandler )
  313. {
  314. unknownKeyHandler->ParseKeyValue( pFluid, key, value );
  315. }
  316. }
  317. }
  318. }
  319. void CVPhysicsParse::ParseSurfaceTable( int *table, IVPhysicsKeyHandler *unknownKeyHandler )
  320. {
  321. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  322. key[0] = 0;
  323. while ( m_pText )
  324. {
  325. m_pText = ParseKeyvalue( m_pText, key, value );
  326. if ( key[0] == '}' )
  327. {
  328. NextBlock();
  329. return;
  330. }
  331. int propIndex = physprops->GetSurfaceIndex( key );
  332. int tableIndex = atoi(value);
  333. if ( tableIndex >= 0 && tableIndex < 128 )
  334. {
  335. table[tableIndex] = propIndex;
  336. }
  337. }
  338. }
  339. void CVPhysicsParse::ParseSurfaceTablePacked( CUtlVector<char> &out )
  340. {
  341. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  342. key[0] = 0;
  343. int lastIndex = 0;
  344. while ( m_pText )
  345. {
  346. m_pText = ParseKeyvalue( m_pText, key, value );
  347. if ( key[0] == '}' )
  348. {
  349. NextBlock();
  350. return;
  351. }
  352. int len = Q_strlen( key );
  353. int outIndex = out.AddMultipleToTail( len + 1 );
  354. memcpy( &out[outIndex], key, len+1 );
  355. int tableIndex = atoi(value);
  356. Assert( tableIndex == lastIndex + 1);
  357. lastIndex = tableIndex;
  358. }
  359. }
  360. void CVPhysicsParse::ParseVehicleAxle( vehicle_axleparams_t &axle )
  361. {
  362. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  363. memset( &axle, 0, sizeof(axle) );
  364. key[0] = 0;
  365. while ( m_pText )
  366. {
  367. m_pText = ParseKeyvalue( m_pText, key, value );
  368. if ( key[0] == '}' )
  369. return;
  370. // parse subchunks
  371. if ( value[0] == '{' )
  372. {
  373. if ( !Q_stricmp( key, "wheel" ) )
  374. {
  375. ParseVehicleWheel( axle.wheels );
  376. }
  377. else if ( !Q_stricmp( key, "suspension" ) )
  378. {
  379. ParseVehicleSuspension( axle.suspension );
  380. }
  381. else
  382. {
  383. SkipBlock();
  384. }
  385. }
  386. else if ( !Q_stricmp( key, "offset" ) )
  387. {
  388. ReadVector( value, axle.offset );
  389. }
  390. else if ( !Q_stricmp( key, "wheeloffset" ) )
  391. {
  392. ReadVector( value, axle.wheelOffset );
  393. }
  394. else if ( !Q_stricmp( key, "torquefactor" ) )
  395. {
  396. axle.torqueFactor = atof( value );
  397. }
  398. else if ( !Q_stricmp( key, "brakefactor" ) )
  399. {
  400. axle.brakeFactor = atof( value );
  401. }
  402. }
  403. }
  404. void CVPhysicsParse::ParseVehicleWheel( vehicle_wheelparams_t &wheel )
  405. {
  406. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  407. key[0] = 0;
  408. while ( m_pText )
  409. {
  410. m_pText = ParseKeyvalue( m_pText, key, value );
  411. if ( key[0] == '}' )
  412. return;
  413. if ( !Q_stricmp( key, "radius" ) )
  414. {
  415. wheel.radius = atof( value );
  416. }
  417. else if ( !Q_stricmp( key, "mass" ) )
  418. {
  419. wheel.mass = atof( value );
  420. }
  421. else if ( !Q_stricmp( key, "inertia" ) )
  422. {
  423. wheel.inertia = atof( value );
  424. }
  425. else if ( !Q_stricmp( key, "damping" ) )
  426. {
  427. wheel.damping = atof( value );
  428. }
  429. else if ( !Q_stricmp( key, "rotdamping" ) )
  430. {
  431. wheel.rotdamping = atof( value );
  432. }
  433. else if ( !Q_stricmp( key, "frictionscale" ) )
  434. {
  435. wheel.frictionScale = atof( value );
  436. }
  437. else if ( !Q_stricmp( key, "material" ) )
  438. {
  439. wheel.materialIndex = physprops->GetSurfaceIndex( value );
  440. }
  441. else if ( !Q_stricmp( key, "skidmaterial" ) )
  442. {
  443. wheel.skidMaterialIndex = physprops->GetSurfaceIndex( value );
  444. }
  445. else if ( !Q_stricmp( key, "brakematerial" ) )
  446. {
  447. wheel.brakeMaterialIndex = physprops->GetSurfaceIndex( value );
  448. }
  449. }
  450. }
  451. void CVPhysicsParse::ParseVehicleSuspension( vehicle_suspensionparams_t &suspension )
  452. {
  453. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  454. key[0] = 0;
  455. while ( m_pText )
  456. {
  457. m_pText = ParseKeyvalue( m_pText, key, value );
  458. if ( key[0] == '}' )
  459. return;
  460. if ( !Q_stricmp( key, "springconstant" ) )
  461. {
  462. suspension.springConstant = atof( value );
  463. }
  464. else if ( !Q_stricmp( key, "springdamping" ) )
  465. {
  466. suspension.springDamping = atof( value );
  467. }
  468. else if ( !Q_stricmp( key, "stabilizerconstant" ) )
  469. {
  470. suspension.stabilizerConstant = atof( value );
  471. }
  472. else if ( !Q_stricmp( key, "springdampingcompression" ) )
  473. {
  474. suspension.springDampingCompression = atof( value );
  475. }
  476. else if ( !Q_stricmp( key, "maxbodyforce" ) )
  477. {
  478. suspension.maxBodyForce = atof( value );
  479. }
  480. }
  481. }
  482. void CVPhysicsParse::ParseVehicleBody( vehicle_bodyparams_t &body )
  483. {
  484. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  485. key[0] = 0;
  486. while ( m_pText )
  487. {
  488. m_pText = ParseKeyvalue( m_pText, key, value );
  489. if ( key[0] == '}' )
  490. return;
  491. if ( !Q_stricmp( key, "massCenterOverride" ) )
  492. {
  493. ReadVector( value, body.massCenterOverride );
  494. }
  495. else if ( !Q_stricmp( key, "addgravity" ) )
  496. {
  497. body.addGravity = atof( value );
  498. }
  499. else if ( !Q_stricmp( key, "maxAngularVelocity" ) )
  500. {
  501. body.maxAngularVelocity = atof( value );
  502. }
  503. else if ( !Q_stricmp( key, "massOverride" ) )
  504. {
  505. body.massOverride = atof( value );
  506. }
  507. else if ( !Q_stricmp( key, "tiltforce" ) )
  508. {
  509. body.tiltForce = atof( value );
  510. }
  511. else if ( !Q_stricmp( key, "tiltforceheight" ) )
  512. {
  513. body.tiltForceHeight = atof( value );
  514. }
  515. else if ( !Q_stricmp( key, "countertorquefactor" ) )
  516. {
  517. body.counterTorqueFactor = atof( value );
  518. }
  519. else if ( !Q_stricmp( key, "keepuprighttorque" ) )
  520. {
  521. body.keepUprightTorque = atof( value );
  522. }
  523. }
  524. }
  525. void CVPhysicsParse::ParseVehicleEngineBoost( vehicle_engineparams_t &engine )
  526. {
  527. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  528. key[0] = 0;
  529. while ( m_pText )
  530. {
  531. m_pText = ParseKeyvalue( m_pText, key, value );
  532. if ( key[0] == '}' )
  533. return;
  534. // parse subchunks
  535. if ( !Q_stricmp( key, "force" ) )
  536. {
  537. engine.boostForce = atof( value );
  538. }
  539. else if ( !Q_stricmp( key, "duration" ) )
  540. {
  541. engine.boostDuration = atof( value );
  542. }
  543. else if ( !Q_stricmp( key, "delay" ) )
  544. {
  545. engine.boostDelay = atof( value );
  546. }
  547. else if ( !Q_stricmp( key, "maxspeed" ) )
  548. {
  549. engine.boostMaxSpeed = atof( value );
  550. }
  551. else if ( !Q_stricmp( key, "torqueboost" ) )
  552. {
  553. engine.torqueBoost = atoi( value ) != 0 ? true : false;
  554. }
  555. }
  556. }
  557. void CVPhysicsParse::ParseVehicleEngine( vehicle_engineparams_t &engine )
  558. {
  559. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  560. key[0] = 0;
  561. while ( m_pText )
  562. {
  563. m_pText = ParseKeyvalue( m_pText, key, value );
  564. if ( key[0] == '}' )
  565. return;
  566. // parse subchunks
  567. if ( value[0] == '{' )
  568. {
  569. if ( !Q_stricmp( key, "boost" ) )
  570. {
  571. ParseVehicleEngineBoost( engine );
  572. }
  573. else
  574. {
  575. SkipBlock();
  576. }
  577. }
  578. else if ( !Q_stricmp( key, "gear" ) )
  579. {
  580. // Protect against exploits/overruns
  581. if ( engine.gearCount < ARRAYSIZE(engine.gearRatio) )
  582. {
  583. engine.gearRatio[engine.gearCount] = atof( value );
  584. engine.gearCount++;
  585. }
  586. else
  587. {
  588. Assert( 0 );
  589. }
  590. }
  591. else if ( !Q_stricmp( key, "horsepower" ) )
  592. {
  593. engine.horsepower = atof( value );
  594. }
  595. else if ( !Q_stricmp( key, "maxSpeed" ) )
  596. {
  597. engine.maxSpeed = atof( value );
  598. }
  599. else if ( !Q_stricmp( key, "maxReverseSpeed" ) )
  600. {
  601. engine.maxRevSpeed = atof( value );
  602. }
  603. else if ( !Q_stricmp( key, "axleratio" ) )
  604. {
  605. engine.axleRatio = atof( value );
  606. }
  607. else if ( !Q_stricmp( key, "maxRPM" ) )
  608. {
  609. engine.maxRPM = atof( value );
  610. }
  611. else if ( !Q_stricmp( key, "throttleTime" ) )
  612. {
  613. engine.throttleTime = atof( value );
  614. }
  615. else if ( !Q_stricmp( key, "AutoTransmission" ) )
  616. {
  617. engine.isAutoTransmission = atoi( value ) != 0 ? true : false;
  618. }
  619. else if ( !Q_stricmp( key, "shiftUpRPM" ) )
  620. {
  621. engine.shiftUpRPM = atof( value );
  622. }
  623. else if ( !Q_stricmp( key, "shiftDownRPM" ) )
  624. {
  625. engine.shiftDownRPM = atof( value );
  626. }
  627. else if ( !Q_stricmp( key, "autobrakeSpeedGain" ) )
  628. {
  629. engine.autobrakeSpeedGain = atof( value );
  630. }
  631. else if ( !Q_stricmp( key, "autobrakeSpeedFactor" ) )
  632. {
  633. engine.autobrakeSpeedFactor = atof( value );
  634. }
  635. }
  636. }
  637. void CVPhysicsParse::ParseVehicleSteering( vehicle_steeringparams_t &steering )
  638. {
  639. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  640. key[0] = 0;
  641. while ( m_pText )
  642. {
  643. m_pText = ParseKeyvalue( m_pText, key, value );
  644. if ( key[0] == '}' )
  645. return;
  646. // parse subchunks
  647. if ( !Q_stricmp( key, "degreesSlow" ) )
  648. {
  649. steering.degreesSlow = atof( value );
  650. }
  651. else if ( !Q_stricmp( key, "degreesFast" ) )
  652. {
  653. steering.degreesFast = atof( value );
  654. }
  655. else if ( !Q_stricmp( key, "degreesBoost" ) )
  656. {
  657. steering.degreesBoost = atof( value );
  658. }
  659. else if ( !Q_stricmp( key, "fastcarspeed" ) )
  660. {
  661. steering.speedFast = atof( value );
  662. }
  663. else if ( !Q_stricmp( key, "slowcarspeed" ) )
  664. {
  665. steering.speedSlow = atof( value );
  666. }
  667. else if ( !Q_stricmp( key, "slowsteeringrate" ) )
  668. {
  669. steering.steeringRateSlow = atof( value );
  670. }
  671. else if ( !Q_stricmp( key, "faststeeringrate" ) )
  672. {
  673. steering.steeringRateFast = atof( value );
  674. }
  675. else if ( !Q_stricmp( key, "steeringRestRateSlow" ) )
  676. {
  677. steering.steeringRestRateSlow = atof( value );
  678. }
  679. else if ( !Q_stricmp( key, "steeringRestRateFast" ) )
  680. {
  681. steering.steeringRestRateFast = atof( value );
  682. }
  683. else if ( !Q_stricmp( key, "throttleSteeringRestRateFactor" ) )
  684. {
  685. steering.throttleSteeringRestRateFactor = atof( value );
  686. }
  687. else if ( !Q_stricmp( key, "boostSteeringRestRateFactor" ) )
  688. {
  689. steering.boostSteeringRestRateFactor = atof( value );
  690. }
  691. else if ( !Q_stricmp( key, "boostSteeringRateFactor" ) )
  692. {
  693. steering.boostSteeringRateFactor = atof( value );
  694. }
  695. else if ( !Q_stricmp( key, "steeringExponent" ) )
  696. {
  697. steering.steeringExponent = atof( value );
  698. }
  699. else if ( !Q_stricmp( key, "turnThrottleReduceSlow" ) )
  700. {
  701. steering.turnThrottleReduceSlow = atof( value );
  702. }
  703. else if ( !Q_stricmp( key, "turnThrottleReduceFast" ) )
  704. {
  705. steering.turnThrottleReduceFast = atof( value );
  706. }
  707. else if ( !Q_stricmp( key, "brakeSteeringRateFactor" ) )
  708. {
  709. steering.brakeSteeringRateFactor = atof( value );
  710. }
  711. else if ( !Q_stricmp( key, "powerSlideAccel" ) )
  712. {
  713. steering.powerSlideAccel = atof( value );
  714. }
  715. else if ( !Q_stricmp( key, "skidallowed" ) )
  716. {
  717. steering.isSkidAllowed = atoi( value ) != 0 ? true : false;
  718. }
  719. else if ( !Q_stricmp( key, "dustcloud" ) )
  720. {
  721. steering.dustCloud = atoi( value ) != 0 ? true : false;
  722. }
  723. }
  724. }
  725. void CVPhysicsParse::ParseVehicle( vehicleparams_t *pVehicle, IVPhysicsKeyHandler *unknownKeyHandler )
  726. {
  727. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  728. key[0] = 0;
  729. if ( unknownKeyHandler )
  730. {
  731. unknownKeyHandler->SetDefaults( pVehicle );
  732. }
  733. else
  734. {
  735. memset( pVehicle, 0, sizeof(*pVehicle) );
  736. }
  737. while ( m_pText )
  738. {
  739. m_pText = ParseKeyvalue( m_pText, key, value );
  740. if ( key[0] == '}' )
  741. {
  742. NextBlock();
  743. return;
  744. }
  745. // parse subchunks
  746. if ( value[0] == '{' )
  747. {
  748. if ( !Q_stricmp( key, "axle" ) )
  749. {
  750. // Protect against exploits/overruns
  751. if ( pVehicle->axleCount < ARRAYSIZE(pVehicle->axles) )
  752. {
  753. ParseVehicleAxle( pVehicle->axles[pVehicle->axleCount] );
  754. pVehicle->axleCount++;
  755. }
  756. else
  757. {
  758. Assert( 0 );
  759. }
  760. }
  761. else if ( !Q_stricmp( key, "body" ) )
  762. {
  763. ParseVehicleBody( pVehicle->body );
  764. }
  765. else if ( !Q_stricmp( key, "engine" ) )
  766. {
  767. ParseVehicleEngine( pVehicle->engine );
  768. }
  769. else if ( !Q_stricmp( key, "steering" ) )
  770. {
  771. ParseVehicleSteering( pVehicle->steering );
  772. }
  773. else
  774. {
  775. SkipBlock();
  776. }
  777. }
  778. else if ( !Q_stricmp( key, "wheelsperaxle" ) )
  779. {
  780. pVehicle->wheelsPerAxle = atoi( value );
  781. }
  782. }
  783. }
  784. void CVPhysicsParse::ParseCustom( void *pCustom, IVPhysicsKeyHandler *unknownKeyHandler )
  785. {
  786. char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
  787. key[0] = 0;
  788. int indent = 0;
  789. if ( unknownKeyHandler )
  790. {
  791. unknownKeyHandler->SetDefaults( pCustom );
  792. }
  793. while ( m_pText )
  794. {
  795. m_pText = ParseKeyvalue( m_pText, key, value );
  796. if ( m_pText )
  797. {
  798. if ( key[0] == '{' )
  799. {
  800. indent++;
  801. }
  802. else if ( value[0] == '{' )
  803. {
  804. // They've got a named block here
  805. // Increase our indent, and let them parse the key
  806. indent++;
  807. if ( unknownKeyHandler )
  808. {
  809. unknownKeyHandler->ParseKeyValue( pCustom, key, value );
  810. }
  811. }
  812. else if ( key[0] == '}' )
  813. {
  814. indent--;
  815. if ( indent < 0 )
  816. {
  817. NextBlock();
  818. return;
  819. }
  820. }
  821. else
  822. {
  823. if ( unknownKeyHandler )
  824. {
  825. unknownKeyHandler->ParseKeyValue( pCustom, key, value );
  826. }
  827. }
  828. }
  829. }
  830. }
  831. IVPhysicsKeyParser *CreateVPhysicsKeyParser( const char *pKeyData )
  832. {
  833. return new CVPhysicsParse( pKeyData );
  834. }
  835. void DestroyVPhysicsKeyParser( IVPhysicsKeyParser *pParser )
  836. {
  837. delete pParser;
  838. }
  839. //-----------------------------------------------------------------------------
  840. // Helper functions for parsing script file
  841. //-----------------------------------------------------------------------------
  842. const char *ParseKeyvalue( const char *pBuffer, char (&key)[MAX_KEYVALUE], char (&value)[MAX_KEYVALUE] )
  843. {
  844. // Make sure value is always null-terminated.
  845. value[0] = 0;
  846. pBuffer = ParseFile( pBuffer, key, NULL );
  847. // no value on a close brace
  848. if ( key[0] == '}' && key[1] == 0 )
  849. {
  850. value[0] = 0;
  851. return pBuffer;
  852. }
  853. Q_strlower( key );
  854. pBuffer = ParseFile( pBuffer, value, NULL );
  855. Q_strlower( value );
  856. return pBuffer;
  857. }