g_vehicleLoad.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. //g_vehicleLoad.cpp
  2. // leave this line at the top for all NPC_xxxx.cpp files...
  3. #include "g_headers.h"
  4. #include "q_shared.h"
  5. #include "anims.h"
  6. #include "g_vehicles.h"
  7. extern qboolean G_ParseLiteral( const char **data, const char *string );
  8. extern void G_CreateG2AttachedWeaponModel( gentity_t *ent, const char *weaponModel, int boltNum, int weaponNum );
  9. vehicleInfo_t g_vehicleInfo[MAX_VEHICLES];
  10. int numVehicles = 1;//first one is null/default
  11. typedef enum {
  12. VF_INT,
  13. VF_FLOAT,
  14. VF_LSTRING, // string on disk, pointer in memory, TAG_LEVEL
  15. VF_VECTOR,
  16. VF_BOOL,
  17. VF_VEHTYPE,
  18. VF_ANIM
  19. } vehFieldType_t;
  20. typedef struct
  21. {
  22. char *name;
  23. int ofs;
  24. vehFieldType_t type;
  25. } vehField_t;
  26. vehField_t vehFields[VEH_PARM_MAX] =
  27. {
  28. {"name", VFOFS(name), VF_LSTRING}, //unique name of the vehicle
  29. //general data
  30. {"type", VFOFS(type), VF_VEHTYPE}, //what kind of vehicle
  31. {"numHands", VFOFS(numHands), VF_INT}, //if 2 hands, no weapons, if 1 hand, can use 1-handed weapons, if 0 hands, can use 2-handed weapons
  32. {"lookPitch", VFOFS(lookPitch), VF_FLOAT}, //How far you can look up and down off the forward of the vehicle
  33. {"lookYaw", VFOFS(lookYaw), VF_FLOAT}, //How far you can look left and right off the forward of the vehicle
  34. {"length", VFOFS(length), VF_FLOAT}, //how long it is - used for body length traces when turning/moving?
  35. {"width", VFOFS(width), VF_FLOAT}, //how wide it is - used for body length traces when turning/moving?
  36. {"height", VFOFS(height), VF_FLOAT}, //how tall it is - used for body length traces when turning/moving?
  37. {"centerOfGravity", VFOFS(centerOfGravity), VF_VECTOR},//offset from origin: {forward, right, up} as a modifier on that dimension (-1.0f is all the way back, 1.0f is all the way forward)
  38. //speed stats
  39. {"speedMax", VFOFS(speedMax), VF_FLOAT}, //top speed
  40. {"turboSpeed", VFOFS(turboSpeed), VF_FLOAT}, //turbo speed
  41. {"speedMin", VFOFS(speedMin), VF_FLOAT}, //if < 0, can go in reverse
  42. {"speedIdle", VFOFS(speedIdle), VF_FLOAT}, //what speed it drifts to when no accel/decel input is given
  43. {"accelIdle", VFOFS(accelIdle), VF_FLOAT}, //if speedIdle > 0, how quickly it goes up to that speed
  44. {"acceleration", VFOFS(acceleration), VF_FLOAT}, //when pressing on accelerator
  45. {"decelIdle", VFOFS(decelIdle), VF_FLOAT}, //when giving no input, how quickly it drops to speedIdle
  46. {"strafePerc", VFOFS(strafePerc), VF_FLOAT}, //multiplier on current speed for strafing. If 1.0f, you can strafe at the same speed as you're going forward, 0.5 is half, 0 is no strafing
  47. //handling stats
  48. {"bankingSpeed", VFOFS(bankingSpeed), VF_FLOAT}, //how quickly it pitches and rolls (not under player control)
  49. {"pitchLimit", VFOFS(pitchLimit), VF_FLOAT}, //how far it can roll forward or backward
  50. {"rollLimit", VFOFS(rollLimit), VF_FLOAT}, //how far it can roll to either side
  51. {"braking", VFOFS(braking), VF_FLOAT}, //when pressing on decelerator
  52. {"turningSpeed", VFOFS(turningSpeed), VF_FLOAT}, //how quickly you can turn
  53. {"turnWhenStopped", VFOFS(turnWhenStopped), VF_BOOL},//whether or not you can turn when not moving
  54. {"traction", VFOFS(traction), VF_FLOAT}, //how much your command input affects velocity
  55. {"friction", VFOFS(friction), VF_FLOAT}, //how much velocity is cut on its own
  56. {"maxSlope", VFOFS(maxSlope), VF_FLOAT}, //the max slope that it can go up with control
  57. //durability stats
  58. {"mass", VFOFS(mass), VF_INT}, //for momentum and impact force (player mass is 10)
  59. {"armor", VFOFS(armor), VF_INT}, //total points of damage it can take
  60. {"toughness", VFOFS(toughness), VF_FLOAT}, //modifies incoming damage, 1.0 is normal, 0.5 is half, etc. Simulates being made of tougher materials/construction
  61. {"malfunctionArmorLevel", VFOFS(malfunctionArmorLevel), VF_INT},//when armor drops to or below this point, start malfunctioning
  62. //visuals & sounds
  63. {"model", VFOFS(model), VF_LSTRING}, //what model to use - if make it an NPC's primary model, don't need this?
  64. {"skin", VFOFS(skin), VF_LSTRING}, //what skin to use - if make it an NPC's primary model, don't need this?
  65. {"riderAnim", VFOFS(riderAnim), VF_ANIM}, //what animation the rider uses
  66. {"gunswivelBone", VFOFS(gunswivelBone), VF_LSTRING},//gun swivel bones
  67. {"lFinBone", VFOFS(lFinBone), VF_LSTRING}, //left fin bone
  68. {"rFinBone", VFOFS(rFinBone), VF_LSTRING}, //right fin bone
  69. {"lExhaustTag", VFOFS(lExhaustTag), VF_LSTRING}, //left exhaust tag
  70. {"rExhaustTag", VFOFS(rExhaustTag), VF_LSTRING}, //right exhaust tag
  71. {"soundOn", VFOFS(soundOn), VF_LSTRING}, //sound to play when get on it
  72. {"soundLoop", VFOFS(soundLoop), VF_LSTRING}, //sound to loop while riding it
  73. {"soundOff", VFOFS(soundOff), VF_LSTRING}, //sound to play when get off
  74. {"exhaustFX", VFOFS(exhaustFX), VF_LSTRING}, //exhaust effect, played from "*exhaust" bolt(s)
  75. {"trailFX", VFOFS(trailFX), VF_LSTRING}, //trail effect, played from "*trail" bolt(s)
  76. {"impactFX", VFOFS(impactFX), VF_LSTRING}, //impact effect, for when it bumps into something
  77. {"explodeFX", VFOFS(explodeFX), VF_LSTRING}, //explosion effect, for when it blows up (should have the sound built into explosion effect)
  78. {"wakeFX", VFOFS(wakeFX), VF_LSTRING}, //effect it makes when going across water
  79. //other misc stats
  80. {"gravity", VFOFS(gravity), VF_INT}, //normal is 800
  81. {"hoverHeight", VFOFS(hoverHeight), VF_FLOAT}, //if 0, it's a ground vehicle
  82. {"hoverStrength", VFOFS(hoverStrength), VF_FLOAT}, //how hard it pushes off ground when less than hover height... causes "bounce", like shocks
  83. {"waterProof", VFOFS(waterProof), VF_BOOL}, //can drive underwater if it has to
  84. {"bouyancy", VFOFS(bouyancy), VF_FLOAT}, //when in water, how high it floats (1 is neutral bouyancy)
  85. {"fuelMax", VFOFS(fuelMax), VF_INT}, //how much fuel it can hold (capacity)
  86. {"fuelRate", VFOFS(fuelRate), VF_INT}, //how quickly is uses up fuel
  87. {"visibility", VFOFS(visibility), VF_INT}, //for sight alerts
  88. {"loudness", VFOFS(loudness), VF_INT}, //for sound alerts
  89. {"explosionRadius", VFOFS(explosionRadius), VF_FLOAT},//range of explosion
  90. {"explosionDamage", VFOFS(explosionDamage), VF_INT},//damage of explosion
  91. //new stuff
  92. {"maxPassengers", VFOFS(maxPassengers), VF_INT}, // The max number of passengers this vehicle may have (Default = 0).
  93. {"hideRider", VFOFS(hideRider), VF_BOOL }, // rider (and passengers?) should not be drawn
  94. {"killRiderOnDeath", VFOFS(killRiderOnDeath), VF_BOOL },//if rider is on vehicle when it dies, they should die
  95. {"flammable", VFOFS(flammable), VF_BOOL }, //whether or not the vehicle should catch on fire before it explodes
  96. {"explosionDelay", VFOFS(explosionDelay), VF_INT}, //how long the vehicle should be on fire/dying before it explodes
  97. //camera stuff
  98. {"cameraOverride", VFOFS(cameraOverride), VF_BOOL }, //override the third person camera with the below values - normal is 0 (off)
  99. {"cameraRange", VFOFS(cameraRange), VF_FLOAT}, //how far back the camera should be - normal is 80
  100. {"cameraVertOffset", VFOFS(cameraVertOffset), VF_FLOAT},//how high over the vehicle origin the camera should be - normal is 16
  101. {"cameraHorzOffset", VFOFS(cameraHorzOffset), VF_FLOAT},//how far to left/right (negative/positive) of of the vehicle origin the camera should be - normal is 0
  102. {"cameraPitchOffset", VFOFS(cameraPitchOffset), VF_FLOAT},//a modifier on the camera's pitch (up/down angle) to the vehicle - normal is 0
  103. {"cameraFOV", VFOFS(cameraFOV), VF_FLOAT}, //third person camera FOV, default is 80
  104. {"cameraAlpha", VFOFS(cameraAlpha), VF_BOOL }, //fade out the vehicle if it's in the way of the crosshair
  105. };
  106. stringID_table_t VehicleTable[VH_NUM_VEHICLES+1] =
  107. {
  108. ENUM2STRING(VH_WALKER), //something you ride inside of, it walks like you, like an AT-ST
  109. ENUM2STRING(VH_FIGHTER), //something you fly inside of, like an X-Wing or TIE fighter
  110. ENUM2STRING(VH_SPEEDER), //something you ride on that hovers, like a speeder or swoop
  111. ENUM2STRING(VH_ANIMAL), //animal you ride on top of that walks, like a tauntaun
  112. ENUM2STRING(VH_FLIER), //animal you ride on top of that flies, like a giant mynoc?
  113. "", -1
  114. };
  115. void G_VehicleSetDefaults( vehicleInfo_t *vehicle )
  116. {
  117. vehicle->name = "default"; //unique name of the vehicle
  118. /*
  119. //general data
  120. vehicle->type = VH_SPEEDER; //what kind of vehicle
  121. //FIXME: no saber or weapons if numHands = 2, should switch to speeder weapon, no attack anim on player
  122. vehicle->numHands = 2; //if 2 hands, no weapons, if 1 hand, can use 1-handed weapons, if 0 hands, can use 2-handed weapons
  123. vehicle->lookPitch = 35; //How far you can look up and down off the forward of the vehicle
  124. vehicle->lookYaw = 5; //How far you can look left and right off the forward of the vehicle
  125. vehicle->length = 0; //how long it is - used for body length traces when turning/moving?
  126. vehicle->width = 0; //how wide it is - used for body length traces when turning/moving?
  127. vehicle->height = 0; //how tall it is - used for body length traces when turning/moving?
  128. VectorClear( vehicle->centerOfGravity );//offset from origin: {forward, right, up} as a modifier on that dimension (-1.0f is all the way back, 1.0f is all the way forward)
  129. //speed stats - note: these are DESIRED speed, not actual current speed/velocity
  130. vehicle->speedMax = VEH_DEFAULT_SPEED_MAX; //top speed
  131. vehicle->turboSpeed = 0; //turboBoost
  132. vehicle->speedMin = 0; //if < 0, can go in reverse
  133. vehicle->speedIdle = 0; //what speed it drifts to when no accel/decel input is given
  134. vehicle->accelIdle = 0; //if speedIdle > 0, how quickly it goes up to that speed
  135. vehicle->acceleration = VEH_DEFAULT_ACCEL; //when pressing on accelerator (1/2 this when going in reverse)
  136. vehicle->decelIdle = VEH_DEFAULT_DECEL; //when giving no input, how quickly it desired speed drops to speedIdle
  137. vehicle->strafePerc = VEH_DEFAULT_STRAFE_PERC;//multiplier on current speed for strafing. If 1.0f, you can strafe at the same speed as you're going forward, 0.5 is half, 0 is no strafing
  138. //handling stats
  139. vehicle->bankingSpeed = VEH_DEFAULT_BANKING_SPEED; //how quickly it pitches and rolls (not under player control)
  140. vehicle->rollLimit = VEH_DEFAULT_ROLL_LIMIT; //how far it can roll to either side
  141. vehicle->pitchLimit = VEH_DEFAULT_PITCH_LIMIT; //how far it can pitch forward or backward
  142. vehicle->braking = VEH_DEFAULT_BRAKING; //when pressing on decelerator (backwards)
  143. vehicle->turningSpeed = VEH_DEFAULT_TURNING_SPEED; //how quickly you can turn
  144. vehicle->turnWhenStopped = qfalse; //whether or not you can turn when not moving
  145. vehicle->traction = VEH_DEFAULT_TRACTION; //how much your command input affects velocity
  146. vehicle->friction = VEH_DEFAULT_FRICTION; //how much velocity is cut on its own
  147. vehicle->maxSlope = VEH_DEFAULT_MAX_SLOPE; //the max slope that it can go up with control
  148. //durability stats
  149. vehicle->mass = VEH_DEFAULT_MASS; //for momentum and impact force (player mass is 10)
  150. vehicle->armor = VEH_DEFAULT_MAX_ARMOR; //total points of damage it can take
  151. vehicle->toughness = VEH_DEFAULT_TOUGHNESS; //modifies incoming damage, 1.0 is normal, 0.5 is half, etc. Simulates being made of tougher materials/construction
  152. vehicle->malfunctionArmorLevel = 0; //when armor drops to or below this point, start malfunctioning
  153. //visuals & sounds
  154. vehicle->model = "swoop"; //what model to use - if make it an NPC's primary model, don't need this?
  155. vehicle->modelIndex = 0; //set internally, not until this vehicle is spawned into the level
  156. vehicle->skin = NULL; //what skin to use - if make it an NPC's primary model, don't need this?
  157. vehicle->riderAnim = BOTH_GUNSIT1; //what animation the rider uses
  158. vehicle->gunswivelBone = NULL; //gun swivel bones
  159. vehicle->lFinBone = NULL; //left fin bone
  160. vehicle->rFinBone = NULL; //right fin bone
  161. vehicle->lExhaustTag = NULL; //left exhaust tag
  162. vehicle->rExhaustTag = NULL; //right exhaust tag
  163. vehicle->soundOn = NULL; //sound to play when get on it
  164. vehicle->soundLoop = NULL; //sound to loop while riding it
  165. vehicle->soundOff = NULL; //sound to play when get off
  166. vehicle->exhaustFX = NULL; //exhaust effect, played from "*exhaust" bolt(s)
  167. vehicle->trailFX = NULL; //trail effect, played from "*trail" bolt(s)
  168. vehicle->impactFX = NULL; //explosion effect, for when it blows up (should have the sound built into explosion effect)
  169. vehicle->explodeFX = NULL; //explosion effect, for when it blows up (should have the sound built into explosion effect)
  170. vehicle->wakeFX = NULL; //effect itmakes when going across water
  171. //other misc stats
  172. vehicle->gravity = VEH_DEFAULT_GRAVITY; //normal is 800
  173. vehicle->hoverHeight = 0; //if 0, it's a ground vehicle
  174. vehicle->hoverStrength = 0;//how hard it pushes off ground when less than hover height... causes "bounce", like shocks
  175. vehicle->waterProof = qtrue; //can drive underwater if it has to
  176. vehicle->bouyancy = 1.0f; //when in water, how high it floats (1 is neutral bouyancy)
  177. vehicle->fuelMax = 1000; //how much fuel it can hold (capacity)
  178. vehicle->fuelRate = 1; //how quickly is uses up fuel
  179. vehicle->visibility = VEH_DEFAULT_VISIBILITY; //radius for sight alerts
  180. vehicle->loudness = VEH_DEFAULT_LOUDNESS; //radius for sound alerts
  181. vehicle->explosionRadius = VEH_DEFAULT_EXP_RAD;
  182. vehicle->explosionDamage = VEH_DEFAULT_EXP_DMG;
  183. //new stuff
  184. vehicle->maxPassengers = 0;
  185. vehicle->hideRider = qfalse; // rider (and passengers?) should not be drawn
  186. vehicle->killRiderOnDeath = qfalse; //if rider is on vehicle when it dies, they should die
  187. vehicle->flammable = qfalse; //whether or not the vehicle should catch on fire before it explodes
  188. vehicle->explosionDelay = 0; //how long the vehicle should be on fire/dying before it explodes
  189. //camera stuff
  190. vehicle->cameraOverride = qfalse; //whether or not to use all of the following 3rd person camera override values
  191. vehicle->cameraRange = 0.0f; //how far back the camera should be - normal is 80
  192. vehicle->cameraVertOffset = 0.0f; //how high over the vehicle origin the camera should be - normal is 16
  193. vehicle->cameraHorzOffset = 0.0f; //how far to left/right (negative/positive) of of the vehicle origin the camera should be - normal is 0
  194. vehicle->cameraPitchOffset = 0.0f; //a modifier on the camera's pitch (up/down angle) to the vehicle - normal is 0
  195. vehicle->cameraFOV = 0.0f; //third person camera FOV, default is 80
  196. vehicle->cameraAlpha = qfalse; //fade out the vehicle if it's in the way of the crosshair
  197. */
  198. }
  199. void G_VehicleClampData( vehicleInfo_t *vehicle )
  200. {//sanity check and clamp the vehicle's data
  201. int i;
  202. for ( i = 0; i < 3; i++ )
  203. {
  204. if ( vehicle->centerOfGravity[i] > 1.0f )
  205. {
  206. vehicle->centerOfGravity[i] = 1.0f;
  207. }
  208. else if ( vehicle->centerOfGravity[i] < -1.0f )
  209. {
  210. vehicle->centerOfGravity[i] = -1.0f;
  211. }
  212. }
  213. // Validate passenger max.
  214. if ( vehicle->maxPassengers > VEH_MAX_PASSENGERS )
  215. {
  216. vehicle->maxPassengers = VEH_MAX_PASSENGERS;
  217. }
  218. else if ( vehicle->maxPassengers < 0 )
  219. {
  220. vehicle->maxPassengers = 0;
  221. }
  222. }
  223. static void G_ParseVehicleParms( vehicleInfo_t *vehicle, const char **holdBuf )
  224. {
  225. const char *token;
  226. const char *value;
  227. int i;
  228. vec3_t vec;
  229. byte *b = (byte *)vehicle;
  230. int _iFieldsRead = 0;
  231. vehicleType_t vehType;
  232. while ( holdBuf )
  233. {
  234. token = COM_ParseExt( holdBuf, qtrue );
  235. if ( !token[0] )
  236. {
  237. gi.Printf( S_COLOR_RED"ERROR: unexpected EOF while parsing vehicles!\n" );
  238. return;
  239. }
  240. if ( !Q_stricmp( token, "}" ) ) // End of data for this vehicle
  241. {
  242. break;
  243. }
  244. // Loop through possible parameters
  245. for ( i = 0; i < VEH_PARM_MAX; i++ )
  246. {
  247. if ( vehFields[i].name && !Q_stricmp( vehFields[i].name, token ) )
  248. {
  249. // found it
  250. if ( COM_ParseString( holdBuf, &value ) )
  251. {
  252. continue;
  253. }
  254. switch( vehFields[i].type )
  255. {
  256. case VF_INT:
  257. *(int *)(b+vehFields[i].ofs) = atoi(value);
  258. break;
  259. case VF_FLOAT:
  260. *(float *)(b+vehFields[i].ofs) = atof(value);
  261. break;
  262. case VF_LSTRING: // string on disk, pointer in memory, TAG_LEVEL
  263. *(char **)(b+vehFields[i].ofs) = G_NewString( value );
  264. break;
  265. case VF_VECTOR:
  266. _iFieldsRead = sscanf (value, "%f %f %f", &vec[0], &vec[1], &vec[2]);
  267. assert(_iFieldsRead==3 );
  268. if (_iFieldsRead!=3)
  269. {
  270. gi.Printf (S_COLOR_YELLOW"G_ParseVehicleParms: VEC3 sscanf() failed to read 3 floats ('angle' key bug?)\n");
  271. }
  272. ((float *)(b+vehFields[i].ofs))[0] = vec[0];
  273. ((float *)(b+vehFields[i].ofs))[1] = vec[1];
  274. ((float *)(b+vehFields[i].ofs))[2] = vec[2];
  275. break;
  276. case VF_BOOL:
  277. *(qboolean *)(b+vehFields[i].ofs) = (atof(value)!=0);
  278. break;
  279. case VF_VEHTYPE:
  280. vehType = (vehicleType_t)GetIDForString( VehicleTable, value );
  281. *(vehicleType_t *)(b+vehFields[i].ofs) = vehType;
  282. break;
  283. case VF_ANIM:
  284. int anim = GetIDForString( animTable, value );
  285. *(int *)(b+vehFields[i].ofs) = anim;
  286. break;
  287. }
  288. break;
  289. }
  290. }
  291. }
  292. }
  293. static void G_VehicleStoreParms( const char *p )
  294. {//load up all into a table: g_vehicleInfo
  295. const char *token;
  296. vehicleInfo_t *vehicle;
  297. ////////////////// HERE //////////////////////
  298. // The first vehicle just contains all the base level (not 'overridden') function calls.
  299. G_SetSharedVehicleFunctions( &g_vehicleInfo[0] );
  300. numVehicles = 1;
  301. //try to parse data out
  302. COM_BeginParseSession();
  303. //look for an open brace
  304. while ( p )
  305. {
  306. token = COM_ParseExt( &p, qtrue );
  307. if ( token[0] == 0 )
  308. {//barf
  309. return;
  310. }
  311. if ( !Q_stricmp( token, "{" ) )
  312. {//found one, parse out the goodies
  313. if ( numVehicles >= MAX_VEHICLES )
  314. {//sorry, no more vehicle slots!
  315. gi.Printf( S_COLOR_RED"Too many vehicles in *.veh (limit %d)\n", MAX_VEHICLES );
  316. break;
  317. }
  318. //token = token;
  319. vehicle = &g_vehicleInfo[numVehicles++];
  320. G_VehicleSetDefaults( vehicle );
  321. G_ParseVehicleParms( vehicle, &p );
  322. //sanity check and clamp the vehicle's data
  323. G_VehicleClampData( vehicle );
  324. ////////////////// HERE //////////////////////
  325. // Setup the shared function pointers.
  326. G_SetSharedVehicleFunctions( vehicle );
  327. switch( vehicle->type )
  328. {
  329. case VH_SPEEDER:
  330. G_SetSpeederVehicleFunctions( vehicle );
  331. break;
  332. case VH_ANIMAL:
  333. G_SetAnimalVehicleFunctions( vehicle );
  334. break;
  335. case VH_FIGHTER:
  336. G_SetFighterVehicleFunctions( vehicle );
  337. break;
  338. case VH_WALKER:
  339. G_SetAnimalVehicleFunctions( vehicle );
  340. break;
  341. }
  342. }
  343. }
  344. }
  345. void G_VehicleLoadParms( void )
  346. {//HMM... only do this if there's a vehicle on the level?
  347. int len, totallen, vehExtFNLen, fileCnt, i;
  348. char *buffer, *holdChar, *marker;
  349. char vehExtensionListBuf[2048]; // The list of file names read in
  350. #define MAX_VEHICLE_DATA_SIZE 0x20000
  351. char VehicleParms[MAX_VEHICLE_DATA_SIZE]={0};
  352. // gi.Printf( "Parsing *.veh vehicle definitions\n" );
  353. //set where to store the first one
  354. totallen = 0;
  355. marker = VehicleParms;
  356. //now load in the .veh vehicle definitions
  357. fileCnt = gi.FS_GetFileList("ext_data/vehicles", ".veh", vehExtensionListBuf, sizeof(vehExtensionListBuf) );
  358. holdChar = vehExtensionListBuf;
  359. for ( i = 0; i < fileCnt; i++, holdChar += vehExtFNLen + 1 )
  360. {
  361. vehExtFNLen = strlen( holdChar );
  362. //gi.Printf( "Parsing %s\n", holdChar );
  363. len = gi.FS_ReadFile( va( "ext_data/vehicles/%s", holdChar), (void **) &buffer );
  364. if ( len == -1 )
  365. {
  366. gi.Printf( "G_VehicleLoadParms: error reading file %s\n", holdChar );
  367. }
  368. else
  369. {
  370. if ( totallen && *(marker-1) == '}' )
  371. {//don't let it end on a } because that should be a stand-alone token
  372. strcat( marker, " " );
  373. totallen++;
  374. marker++;
  375. }
  376. if ( totallen + len >= MAX_VEHICLE_DATA_SIZE ) {
  377. G_Error( "G_VehicleLoadParms: ran out of space before reading %s\n(you must make the .npc files smaller)", holdChar );
  378. }
  379. strcat( marker, buffer );
  380. gi.FS_FreeFile( buffer );
  381. totallen += len;
  382. marker += len;
  383. }
  384. }
  385. G_VehicleStoreParms(VehicleParms);
  386. }