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.
942 lines
21 KiB
942 lines
21 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
#include "cbase.h" |
|
|
|
#include "vcollide_parse_private.h" |
|
|
|
#include "tier1/strtools.h" |
|
#include "vphysics/constraints.h" |
|
#include "vphysics/vehicles.h" |
|
#include "filesystem_helpers.h" |
|
#include "bspfile.h" |
|
#include "utlbuffer.h" |
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
static void ReadVector( const char *pString, Vector& out ) |
|
{ |
|
float x, y, z; |
|
sscanf( pString, "%f %f %f", &x, &y, &z ); |
|
out[0] = x; |
|
out[1] = y; |
|
out[2] = z; |
|
} |
|
|
|
static void ReadAngles( const char *pString, QAngle& out ) |
|
{ |
|
float x, y, z; |
|
sscanf( pString, "%f %f %f", &x, &y, &z ); |
|
out[0] = x; |
|
out[1] = y; |
|
out[2] = z; |
|
} |
|
|
|
static void ReadVector4D( const char *pString, Vector4D& out ) |
|
{ |
|
float x, y, z, w; |
|
sscanf( pString, "%f %f %f %f", &x, &y, &z, &w ); |
|
out[0] = x; |
|
out[1] = y; |
|
out[2] = z; |
|
out[3] = w; |
|
} |
|
|
|
class CVPhysicsParse : public IVPhysicsKeyParser |
|
{ |
|
public: |
|
~CVPhysicsParse() {} |
|
|
|
CVPhysicsParse( const char *pKeyData ); |
|
void NextBlock( void ); |
|
|
|
const char *GetCurrentBlockName( void ); |
|
bool Finished( void ); |
|
void ParseSolid( solid_t *pSolid, IVPhysicsKeyHandler *unknownKeyHandler ); |
|
void ParseFluid( fluid_t *pFluid, IVPhysicsKeyHandler *unknownKeyHandler ); |
|
void ParseRagdollConstraint( constraint_ragdollparams_t *pConstraint, IVPhysicsKeyHandler *unknownKeyHandler ); |
|
void ParseSurfaceTable( int *table, IVPhysicsKeyHandler *unknownKeyHandler ); |
|
void ParseSurfaceTablePacked( CUtlVector<char> &out ); |
|
void ParseVehicle( vehicleparams_t *pVehicle, IVPhysicsKeyHandler *unknownKeyHandler ); |
|
void ParseCustom( void *pCustom, IVPhysicsKeyHandler *unknownKeyHandler ); |
|
void SkipBlock( void ) { ParseCustom(NULL, NULL); } |
|
|
|
private: |
|
void ParseVehicleAxle( vehicle_axleparams_t &axle ); |
|
void ParseVehicleWheel( vehicle_wheelparams_t &wheel ); |
|
void ParseVehicleSuspension( vehicle_suspensionparams_t &suspension ); |
|
void ParseVehicleBody( vehicle_bodyparams_t &body ); |
|
void ParseVehicleEngine( vehicle_engineparams_t &engine ); |
|
void ParseVehicleEngineBoost( vehicle_engineparams_t &engine ); |
|
void ParseVehicleSteering( vehicle_steeringparams_t &steering ); |
|
|
|
const char *m_pText; |
|
char m_blockName[MAX_KEYVALUE]; |
|
}; |
|
|
|
|
|
CVPhysicsParse::CVPhysicsParse( const char *pKeyData ) |
|
{ |
|
m_pText = pKeyData; |
|
NextBlock(); |
|
} |
|
|
|
void CVPhysicsParse::NextBlock( void ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( !Q_strcmp(value, "{") ) |
|
{ |
|
V_strcpy_safe( m_blockName, key ); |
|
return; |
|
} |
|
} |
|
|
|
// Make sure m_blockName is initialized -- should this be done? |
|
m_blockName[ 0 ] = 0; |
|
} |
|
|
|
|
|
const char *CVPhysicsParse::GetCurrentBlockName( void ) |
|
{ |
|
if ( m_pText ) |
|
return m_blockName; |
|
|
|
return NULL; |
|
} |
|
|
|
|
|
bool CVPhysicsParse::Finished( void ) |
|
{ |
|
if ( m_pText ) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
|
|
void CVPhysicsParse::ParseSolid( solid_t *pSolid, IVPhysicsKeyHandler *unknownKeyHandler ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
key[0] = 0; |
|
|
|
if ( unknownKeyHandler ) |
|
{ |
|
unknownKeyHandler->SetDefaults( pSolid ); |
|
} |
|
else |
|
{ |
|
memset( pSolid, 0, sizeof(*pSolid) ); |
|
} |
|
|
|
// disable these until the ragdoll is created |
|
pSolid->params.enableCollisions = false; |
|
|
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
{ |
|
NextBlock(); |
|
return; |
|
} |
|
|
|
if ( !Q_stricmp( key, "index" ) ) |
|
{ |
|
pSolid->index = atoi(value); |
|
} |
|
else if ( !Q_stricmp( key, "name" ) ) |
|
{ |
|
Q_strncpy( pSolid->name, value, sizeof(pSolid->name) ); |
|
} |
|
else if ( !Q_stricmp( key, "parent" ) ) |
|
{ |
|
Q_strncpy( pSolid->parent, value, sizeof(pSolid->parent) ); |
|
} |
|
else if ( !Q_stricmp( key, "surfaceprop" ) ) |
|
{ |
|
Q_strncpy( pSolid->surfaceprop, value, sizeof(pSolid->surfaceprop) ); |
|
} |
|
else if ( !Q_stricmp( key, "mass" ) ) |
|
{ |
|
pSolid->params.mass = atof(value); |
|
} |
|
else if ( !Q_stricmp( key, "massCenterOverride" ) ) |
|
{ |
|
ReadVector( value, pSolid->massCenterOverride ); |
|
pSolid->params.massCenterOverride = &pSolid->massCenterOverride; |
|
} |
|
else if ( !Q_stricmp( key, "inertia" ) ) |
|
{ |
|
float inertia = atof(value); |
|
pSolid->params.inertia = (inertia > 1e14f) ? 1e14f : inertia; |
|
} |
|
else if ( !Q_stricmp( key, "damping" ) ) |
|
{ |
|
pSolid->params.damping = atof(value); |
|
} |
|
else if ( !Q_stricmp( key, "rotdamping" ) ) |
|
{ |
|
pSolid->params.rotdamping = atof(value); |
|
} |
|
else if ( !Q_stricmp( key, "volume" ) ) |
|
{ |
|
pSolid->params.volume = atof(value); |
|
} |
|
else if ( !Q_stricmp( key, "drag" ) ) |
|
{ |
|
pSolid->params.dragCoefficient = atof(value); |
|
} |
|
else if ( !Q_stricmp( key, "rollingdrag" ) ) |
|
{ |
|
//pSolid->params.rollingDrag = atof(value); |
|
} |
|
else |
|
{ |
|
if ( unknownKeyHandler ) |
|
{ |
|
unknownKeyHandler->ParseKeyValue( pSolid, key, value ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CVPhysicsParse::ParseRagdollConstraint( constraint_ragdollparams_t *pConstraint, IVPhysicsKeyHandler *unknownKeyHandler ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
if ( unknownKeyHandler ) |
|
{ |
|
unknownKeyHandler->SetDefaults( pConstraint ); |
|
} |
|
else |
|
{ |
|
memset( pConstraint, 0, sizeof(*pConstraint) ); |
|
pConstraint->childIndex = -1; |
|
pConstraint->parentIndex = -1; |
|
} |
|
|
|
// BUGBUG: xmin/xmax, ymin/ymax, zmin/zmax specify clockwise rotations. |
|
// BUGBUG: HL rotations are counter-clockwise, so reverse these limits at some point!!! |
|
pConstraint->useClockwiseRotations = true; |
|
|
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
{ |
|
NextBlock(); |
|
return; |
|
} |
|
|
|
if ( !Q_stricmp( key, "parent" ) ) |
|
{ |
|
pConstraint->parentIndex = atoi( value ); |
|
} |
|
else if ( !Q_stricmp( key, "child" ) ) |
|
{ |
|
pConstraint->childIndex = atoi( value ); |
|
} |
|
else if ( !Q_stricmp( key, "xmin" ) ) |
|
{ |
|
pConstraint->axes[0].minRotation = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "xmax" ) ) |
|
{ |
|
pConstraint->axes[0].maxRotation = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "xfriction" ) ) |
|
{ |
|
pConstraint->axes[0].angularVelocity = 0; |
|
pConstraint->axes[0].torque = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "ymin" ) ) |
|
{ |
|
pConstraint->axes[1].minRotation = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "ymax" ) ) |
|
{ |
|
pConstraint->axes[1].maxRotation = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "yfriction" ) ) |
|
{ |
|
pConstraint->axes[1].angularVelocity = 0; |
|
pConstraint->axes[1].torque = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "zmin" ) ) |
|
{ |
|
pConstraint->axes[2].minRotation = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "zmax" ) ) |
|
{ |
|
pConstraint->axes[2].maxRotation = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "zfriction" ) ) |
|
{ |
|
pConstraint->axes[2].angularVelocity = 0; |
|
pConstraint->axes[2].torque = atof( value ); |
|
} |
|
else |
|
{ |
|
if ( unknownKeyHandler ) |
|
{ |
|
unknownKeyHandler->ParseKeyValue( pConstraint, key, value ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
void CVPhysicsParse::ParseFluid( fluid_t *pFluid, IVPhysicsKeyHandler *unknownKeyHandler ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
pFluid->index = -1; |
|
if ( unknownKeyHandler ) |
|
{ |
|
unknownKeyHandler->SetDefaults( pFluid ); |
|
} |
|
else |
|
{ |
|
memset( pFluid, 0, sizeof(*pFluid) ); |
|
// HACKHACK: This is a reasonable default even though it is hardcoded |
|
V_strcpy_safe( pFluid->surfaceprop, "water" ); |
|
} |
|
|
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
{ |
|
NextBlock(); |
|
return; |
|
} |
|
|
|
if ( !Q_stricmp( key, "index" ) ) |
|
{ |
|
pFluid->index = atoi( value ); |
|
} |
|
else if ( !Q_stricmp( key, "damping" ) ) |
|
{ |
|
pFluid->params.damping = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "surfaceplane" ) ) |
|
{ |
|
ReadVector4D( value, pFluid->params.surfacePlane ); |
|
} |
|
else if ( !Q_stricmp( key, "currentvelocity" ) ) |
|
{ |
|
ReadVector( value, pFluid->params.currentVelocity ); |
|
} |
|
else if ( !Q_stricmp( key, "contents" ) ) |
|
{ |
|
pFluid->params.contents = atoi( value ); |
|
} |
|
else if ( !Q_stricmp( key, "surfaceprop" ) ) |
|
{ |
|
Q_strncpy( pFluid->surfaceprop, value, sizeof(pFluid->surfaceprop) ); |
|
} |
|
else |
|
{ |
|
if ( unknownKeyHandler ) |
|
{ |
|
unknownKeyHandler->ParseKeyValue( pFluid, key, value ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CVPhysicsParse::ParseSurfaceTable( int *table, IVPhysicsKeyHandler *unknownKeyHandler ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
{ |
|
NextBlock(); |
|
return; |
|
} |
|
|
|
int propIndex = physprops->GetSurfaceIndex( key ); |
|
int tableIndex = atoi(value); |
|
if ( tableIndex >= 0 && tableIndex < 128 ) |
|
{ |
|
table[tableIndex] = propIndex; |
|
} |
|
} |
|
} |
|
|
|
void CVPhysicsParse::ParseSurfaceTablePacked( CUtlVector<char> &out ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
int lastIndex = 0; |
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
{ |
|
NextBlock(); |
|
return; |
|
} |
|
|
|
int len = Q_strlen( key ); |
|
int outIndex = out.AddMultipleToTail( len + 1 ); |
|
memcpy( &out[outIndex], key, len+1 ); |
|
int tableIndex = atoi(value); |
|
Assert( tableIndex == lastIndex + 1); |
|
lastIndex = tableIndex; |
|
} |
|
} |
|
|
|
void CVPhysicsParse::ParseVehicleAxle( vehicle_axleparams_t &axle ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
memset( &axle, 0, sizeof(axle) ); |
|
key[0] = 0; |
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
return; |
|
|
|
// parse subchunks |
|
if ( value[0] == '{' ) |
|
{ |
|
if ( !Q_stricmp( key, "wheel" ) ) |
|
{ |
|
ParseVehicleWheel( axle.wheels ); |
|
} |
|
else if ( !Q_stricmp( key, "suspension" ) ) |
|
{ |
|
ParseVehicleSuspension( axle.suspension ); |
|
} |
|
else |
|
{ |
|
SkipBlock(); |
|
} |
|
} |
|
else if ( !Q_stricmp( key, "offset" ) ) |
|
{ |
|
ReadVector( value, axle.offset ); |
|
} |
|
else if ( !Q_stricmp( key, "wheeloffset" ) ) |
|
{ |
|
ReadVector( value, axle.wheelOffset ); |
|
} |
|
else if ( !Q_stricmp( key, "torquefactor" ) ) |
|
{ |
|
axle.torqueFactor = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "brakefactor" ) ) |
|
{ |
|
axle.brakeFactor = atof( value ); |
|
} |
|
} |
|
} |
|
|
|
void CVPhysicsParse::ParseVehicleWheel( vehicle_wheelparams_t &wheel ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
return; |
|
|
|
if ( !Q_stricmp( key, "radius" ) ) |
|
{ |
|
wheel.radius = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "mass" ) ) |
|
{ |
|
wheel.mass = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "inertia" ) ) |
|
{ |
|
float inertia = atof(value); |
|
wheel.inertia = (inertia > 1e14f) ? 1e14f : inertia; |
|
} |
|
else if ( !Q_stricmp( key, "damping" ) ) |
|
{ |
|
wheel.damping = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "rotdamping" ) ) |
|
{ |
|
wheel.rotdamping = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "frictionscale" ) ) |
|
{ |
|
wheel.frictionScale = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "material" ) ) |
|
{ |
|
wheel.materialIndex = physprops->GetSurfaceIndex( value ); |
|
} |
|
else if ( !Q_stricmp( key, "skidmaterial" ) ) |
|
{ |
|
wheel.skidMaterialIndex = physprops->GetSurfaceIndex( value ); |
|
} |
|
else if ( !Q_stricmp( key, "brakematerial" ) ) |
|
{ |
|
wheel.brakeMaterialIndex = physprops->GetSurfaceIndex( value ); |
|
} |
|
} |
|
} |
|
|
|
|
|
void CVPhysicsParse::ParseVehicleSuspension( vehicle_suspensionparams_t &suspension ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
return; |
|
|
|
if ( !Q_stricmp( key, "springconstant" ) ) |
|
{ |
|
suspension.springConstant = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "springdamping" ) ) |
|
{ |
|
suspension.springDamping = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "stabilizerconstant" ) ) |
|
{ |
|
suspension.stabilizerConstant = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "springdampingcompression" ) ) |
|
{ |
|
suspension.springDampingCompression = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "maxbodyforce" ) ) |
|
{ |
|
suspension.maxBodyForce = atof( value ); |
|
} |
|
} |
|
} |
|
|
|
|
|
void CVPhysicsParse::ParseVehicleBody( vehicle_bodyparams_t &body ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
return; |
|
|
|
if ( !Q_stricmp( key, "massCenterOverride" ) ) |
|
{ |
|
ReadVector( value, body.massCenterOverride ); |
|
} |
|
else if ( !Q_stricmp( key, "addgravity" ) ) |
|
{ |
|
body.addGravity = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "maxAngularVelocity" ) ) |
|
{ |
|
body.maxAngularVelocity = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "massOverride" ) ) |
|
{ |
|
body.massOverride = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "tiltforce" ) ) |
|
{ |
|
body.tiltForce = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "tiltforceheight" ) ) |
|
{ |
|
body.tiltForceHeight = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "countertorquefactor" ) ) |
|
{ |
|
body.counterTorqueFactor = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "keepuprighttorque" ) ) |
|
{ |
|
body.keepUprightTorque = atof( value ); |
|
} |
|
} |
|
} |
|
|
|
|
|
void CVPhysicsParse::ParseVehicleEngineBoost( vehicle_engineparams_t &engine ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
return; |
|
// parse subchunks |
|
if ( !Q_stricmp( key, "force" ) ) |
|
{ |
|
engine.boostForce = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "duration" ) ) |
|
{ |
|
engine.boostDuration = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "delay" ) ) |
|
{ |
|
engine.boostDelay = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "maxspeed" ) ) |
|
{ |
|
engine.boostMaxSpeed = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "torqueboost" ) ) |
|
{ |
|
engine.torqueBoost = atoi( value ) != 0 ? true : false; |
|
} |
|
|
|
} |
|
} |
|
|
|
void CVPhysicsParse::ParseVehicleEngine( vehicle_engineparams_t &engine ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
return; |
|
// parse subchunks |
|
if ( value[0] == '{' ) |
|
{ |
|
if ( !Q_stricmp( key, "boost" ) ) |
|
{ |
|
ParseVehicleEngineBoost( engine ); |
|
} |
|
else |
|
{ |
|
SkipBlock(); |
|
} |
|
} |
|
else if ( !Q_stricmp( key, "gear" ) ) |
|
{ |
|
// Protect against exploits/overruns |
|
if ( engine.gearCount < ARRAYSIZE(engine.gearRatio) ) |
|
{ |
|
engine.gearRatio[engine.gearCount] = atof( value ); |
|
engine.gearCount++; |
|
} |
|
else |
|
{ |
|
Assert( 0 ); |
|
} |
|
} |
|
else if ( !Q_stricmp( key, "horsepower" ) ) |
|
{ |
|
engine.horsepower = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "maxSpeed" ) ) |
|
{ |
|
engine.maxSpeed = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "maxReverseSpeed" ) ) |
|
{ |
|
engine.maxRevSpeed = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "axleratio" ) ) |
|
{ |
|
engine.axleRatio = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "maxRPM" ) ) |
|
{ |
|
engine.maxRPM = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "throttleTime" ) ) |
|
{ |
|
engine.throttleTime = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "AutoTransmission" ) ) |
|
{ |
|
engine.isAutoTransmission = atoi( value ) != 0 ? true : false; |
|
} |
|
else if ( !Q_stricmp( key, "shiftUpRPM" ) ) |
|
{ |
|
engine.shiftUpRPM = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "shiftDownRPM" ) ) |
|
{ |
|
engine.shiftDownRPM = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "autobrakeSpeedGain" ) ) |
|
{ |
|
engine.autobrakeSpeedGain = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "autobrakeSpeedFactor" ) ) |
|
{ |
|
engine.autobrakeSpeedFactor = atof( value ); |
|
} |
|
} |
|
} |
|
|
|
|
|
void CVPhysicsParse::ParseVehicleSteering( vehicle_steeringparams_t &steering ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
return; |
|
// parse subchunks |
|
if ( !Q_stricmp( key, "degreesSlow" ) ) |
|
{ |
|
steering.degreesSlow = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "degreesFast" ) ) |
|
{ |
|
steering.degreesFast = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "degreesBoost" ) ) |
|
{ |
|
steering.degreesBoost = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "fastcarspeed" ) ) |
|
{ |
|
steering.speedFast = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "slowcarspeed" ) ) |
|
{ |
|
steering.speedSlow = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "slowsteeringrate" ) ) |
|
{ |
|
steering.steeringRateSlow = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "faststeeringrate" ) ) |
|
{ |
|
steering.steeringRateFast = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "steeringRestRateSlow" ) ) |
|
{ |
|
steering.steeringRestRateSlow = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "steeringRestRateFast" ) ) |
|
{ |
|
steering.steeringRestRateFast = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "throttleSteeringRestRateFactor" ) ) |
|
{ |
|
steering.throttleSteeringRestRateFactor = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "boostSteeringRestRateFactor" ) ) |
|
{ |
|
steering.boostSteeringRestRateFactor = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "boostSteeringRateFactor" ) ) |
|
{ |
|
steering.boostSteeringRateFactor = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "steeringExponent" ) ) |
|
{ |
|
steering.steeringExponent = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "turnThrottleReduceSlow" ) ) |
|
{ |
|
steering.turnThrottleReduceSlow = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "turnThrottleReduceFast" ) ) |
|
{ |
|
steering.turnThrottleReduceFast = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "brakeSteeringRateFactor" ) ) |
|
{ |
|
steering.brakeSteeringRateFactor = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "powerSlideAccel" ) ) |
|
{ |
|
steering.powerSlideAccel = atof( value ); |
|
} |
|
else if ( !Q_stricmp( key, "skidallowed" ) ) |
|
{ |
|
steering.isSkidAllowed = atoi( value ) != 0 ? true : false; |
|
} |
|
else if ( !Q_stricmp( key, "dustcloud" ) ) |
|
{ |
|
steering.dustCloud = atoi( value ) != 0 ? true : false; |
|
} |
|
} |
|
} |
|
|
|
void CVPhysicsParse::ParseVehicle( vehicleparams_t *pVehicle, IVPhysicsKeyHandler *unknownKeyHandler ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
if ( unknownKeyHandler ) |
|
{ |
|
unknownKeyHandler->SetDefaults( pVehicle ); |
|
} |
|
else |
|
{ |
|
memset( pVehicle, 0, sizeof(*pVehicle) ); |
|
} |
|
|
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
if ( key[0] == '}' ) |
|
{ |
|
NextBlock(); |
|
return; |
|
} |
|
|
|
// parse subchunks |
|
if ( value[0] == '{' ) |
|
{ |
|
if ( !Q_stricmp( key, "axle" ) ) |
|
{ |
|
// Protect against exploits/overruns |
|
if ( pVehicle->axleCount < ARRAYSIZE(pVehicle->axles) ) |
|
{ |
|
ParseVehicleAxle( pVehicle->axles[pVehicle->axleCount] ); |
|
pVehicle->axleCount++; |
|
} |
|
else |
|
{ |
|
Assert( 0 ); |
|
} |
|
} |
|
else if ( !Q_stricmp( key, "body" ) ) |
|
{ |
|
ParseVehicleBody( pVehicle->body ); |
|
} |
|
else if ( !Q_stricmp( key, "engine" ) ) |
|
{ |
|
ParseVehicleEngine( pVehicle->engine ); |
|
} |
|
else if ( !Q_stricmp( key, "steering" ) ) |
|
{ |
|
ParseVehicleSteering( pVehicle->steering ); |
|
} |
|
else |
|
{ |
|
SkipBlock(); |
|
} |
|
} |
|
else if ( !Q_stricmp( key, "wheelsperaxle" ) ) |
|
{ |
|
pVehicle->wheelsPerAxle = atoi( value ); |
|
} |
|
} |
|
} |
|
|
|
void CVPhysicsParse::ParseCustom( void *pCustom, IVPhysicsKeyHandler *unknownKeyHandler ) |
|
{ |
|
char key[MAX_KEYVALUE], value[MAX_KEYVALUE]; |
|
|
|
key[0] = 0; |
|
int indent = 0; |
|
if ( unknownKeyHandler ) |
|
{ |
|
unknownKeyHandler->SetDefaults( pCustom ); |
|
} |
|
|
|
while ( m_pText ) |
|
{ |
|
m_pText = ParseKeyvalue( m_pText, key, value ); |
|
|
|
if ( m_pText ) |
|
{ |
|
if ( key[0] == '{' ) |
|
{ |
|
indent++; |
|
} |
|
else if ( value[0] == '{' ) |
|
{ |
|
// They've got a named block here |
|
// Increase our indent, and let them parse the key |
|
indent++; |
|
if ( unknownKeyHandler ) |
|
{ |
|
unknownKeyHandler->ParseKeyValue( pCustom, key, value ); |
|
} |
|
} |
|
else if ( key[0] == '}' ) |
|
{ |
|
indent--; |
|
if ( indent < 0 ) |
|
{ |
|
NextBlock(); |
|
return; |
|
} |
|
} |
|
else |
|
{ |
|
if ( unknownKeyHandler ) |
|
{ |
|
unknownKeyHandler->ParseKeyValue( pCustom, key, value ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
IVPhysicsKeyParser *CreateVPhysicsKeyParser( const char *pKeyData ) |
|
{ |
|
return new CVPhysicsParse( pKeyData ); |
|
} |
|
|
|
void DestroyVPhysicsKeyParser( IVPhysicsKeyParser *pParser ) |
|
{ |
|
delete pParser; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Helper functions for parsing script file |
|
//----------------------------------------------------------------------------- |
|
|
|
const char *ParseKeyvalue( const char *pBuffer, char (&key)[MAX_KEYVALUE], char (&value)[MAX_KEYVALUE] ) |
|
{ |
|
// Make sure value is always null-terminated. |
|
value[0] = 0; |
|
|
|
pBuffer = ParseFile( pBuffer, key, NULL ); |
|
|
|
// no value on a close brace |
|
if ( key[0] == '}' && key[1] == 0 ) |
|
{ |
|
value[0] = 0; |
|
return pBuffer; |
|
} |
|
|
|
Q_strlower( key ); |
|
|
|
pBuffer = ParseFile( pBuffer, value, NULL ); |
|
|
|
Q_strlower( value ); |
|
|
|
return pBuffer; |
|
}
|
|
|