2360 lines
No EOL
52 KiB
C++
2360 lines
No EOL
52 KiB
C++
|
|
// this include must remain at the top of every CPP file
|
|
#include "common_headers.h"
|
|
|
|
#if !defined(FX_SCHEDULER_H_INC)
|
|
#include "FxScheduler.h"
|
|
#endif
|
|
|
|
//------------------------------------------------------
|
|
// CPrimitiveTemplate
|
|
// Set up our minimal default values
|
|
//
|
|
// Input:
|
|
// none
|
|
//
|
|
// Return:
|
|
// none
|
|
//------------------------------------------------------
|
|
CPrimitiveTemplate::CPrimitiveTemplate()
|
|
{
|
|
// We never start out as a copy or with a name
|
|
mCopy = false;
|
|
mName[0] = 0;
|
|
mCullRange = 0;
|
|
|
|
mFlags = mSpawnFlags = 0;
|
|
|
|
mLife.SetRange( 1.0f, 1.0f );
|
|
mSpawnCount.SetRange( 1.0f, 1.0f );
|
|
mRadius.SetRange( 1.0f, 1.0f );
|
|
mHeight.SetRange( 1.0f, 1.0f );
|
|
|
|
VectorSet( mMin, 0.0f, 0.0f, 0.0f );
|
|
VectorSet( mMax, 0.0f, 0.0f, 0.0f );
|
|
|
|
mRedStart.SetRange( 1.0f, 1.0f );
|
|
mGreenStart.SetRange( 1.0f, 1.0f );
|
|
mBlueStart.SetRange( 1.0f, 1.0f );
|
|
|
|
mRedEnd.SetRange( 1.0f, 1.0f );
|
|
mGreenEnd.SetRange( 1.0f, 1.0f );
|
|
mBlueEnd.SetRange( 1.0f, 1.0f );
|
|
|
|
mAlphaStart.SetRange( 1.0f, 1.0f );
|
|
mAlphaEnd.SetRange( 1.0f, 1.0f );
|
|
|
|
mSizeStart.SetRange( 1.0f, 1.0f );
|
|
mSizeEnd.SetRange( 1.0f, 1.0f );
|
|
|
|
mSize2Start.SetRange( 1.0f, 1.0f );
|
|
mSize2End.SetRange( 1.0f, 1.0f );
|
|
|
|
mLengthStart.SetRange( 1.0f, 1.0f );
|
|
mLengthEnd.SetRange( 1.0f, 1.0f );
|
|
|
|
mTexCoordS.SetRange( 1.0f, 1.0f );
|
|
mTexCoordT.SetRange( 1.0f, 1.0f );
|
|
|
|
mVariance.SetRange( 1.0f, 1.0f );
|
|
mDensity.SetRange( 10.0f, 10.0f );// default this high so it doesn't do bad things
|
|
}
|
|
|
|
//-----------------------------------------------------------
|
|
void CPrimitiveTemplate::operator=(const CPrimitiveTemplate &that)
|
|
{
|
|
// I'm assuming that doing a memcpy wouldn't work here
|
|
// If you are looking at this and know a better way to do this, please tell me.
|
|
strcpy( mName, that.mName );
|
|
|
|
mType = that.mType;
|
|
|
|
mSpawnDelay = that.mSpawnDelay;
|
|
mSpawnCount = that.mSpawnCount;
|
|
mLife = that.mLife;
|
|
mCullRange = that.mCullRange;
|
|
|
|
mMediaHandles = that.mMediaHandles;
|
|
mImpactFxHandles = that.mImpactFxHandles;
|
|
mDeathFxHandles = that.mDeathFxHandles;
|
|
mEmitterFxHandles = that.mEmitterFxHandles;
|
|
mPlayFxHandles = that.mPlayFxHandles;
|
|
|
|
mFlags = that.mFlags;
|
|
mSpawnFlags = that.mSpawnFlags;
|
|
|
|
VectorCopy( that.mMin, mMin );
|
|
VectorCopy( that.mMax, mMax );
|
|
|
|
mOrigin1X = that.mOrigin1X;
|
|
mOrigin1Y = that.mOrigin1Y;
|
|
mOrigin1Z = that.mOrigin1Z;
|
|
|
|
mOrigin2X = that.mOrigin2X;
|
|
mOrigin2Y = that.mOrigin2Y;
|
|
mOrigin2Z = that.mOrigin2Z;
|
|
|
|
mRadius = that.mRadius;
|
|
mHeight = that.mHeight;
|
|
|
|
mRotation = that.mRotation;
|
|
mRotationDelta = that.mRotationDelta;
|
|
|
|
mAngle1 = that.mAngle1;
|
|
mAngle2 = that.mAngle2;
|
|
mAngle3 = that.mAngle3;
|
|
|
|
mAngle1Delta = that.mAngle1Delta;
|
|
mAngle2Delta = that.mAngle2Delta;
|
|
mAngle3Delta = that.mAngle3Delta;
|
|
|
|
mVelX = that.mVelX;
|
|
mVelY = that.mVelY;
|
|
mVelZ = that.mVelZ;
|
|
|
|
mAccelX = that.mAccelX;
|
|
mAccelY = that.mAccelY;
|
|
mAccelZ = that.mAccelZ;
|
|
|
|
mGravity = that.mGravity;
|
|
|
|
mDensity = that.mDensity;
|
|
mVariance = that.mVariance;
|
|
|
|
mRedStart = that.mRedStart;
|
|
mGreenStart = that.mGreenStart;
|
|
mBlueStart = that.mBlueStart;
|
|
|
|
mRedEnd = that.mRedEnd;
|
|
mGreenEnd = that.mGreenEnd;
|
|
mBlueEnd = that.mBlueEnd;
|
|
|
|
mRGBParm = that.mRGBParm;
|
|
|
|
mAlphaStart = that.mAlphaStart;
|
|
mAlphaEnd = that.mAlphaEnd;
|
|
mAlphaParm = that.mAlphaParm;
|
|
|
|
mSizeStart = that.mSizeStart;
|
|
mSizeEnd = that.mSizeEnd;
|
|
mSizeParm = that.mSizeParm;
|
|
|
|
mSize2Start = that.mSize2Start;
|
|
mSize2End = that.mSize2End;
|
|
mSize2Parm = that.mSize2Parm;
|
|
|
|
mLengthStart = that.mLengthStart;
|
|
mLengthEnd = that.mLengthEnd;
|
|
mLengthParm = that.mLengthParm;
|
|
|
|
mTexCoordS = that.mTexCoordS;
|
|
mTexCoordT = that.mTexCoordT;
|
|
|
|
mElasticity = that.mElasticity;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseFloat
|
|
// Removes up to two values from a passed in string and
|
|
// sets these values into the passed in min and max
|
|
// fields. if no max is present, min is copied into it.
|
|
//
|
|
// input:
|
|
// string that contains up to two float values
|
|
// min & max are used to return the parse values
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseFloat( const char *val, float *min, float *max )
|
|
{
|
|
// We don't allow passing in a null for either of the fields
|
|
if ( min == 0 || max == 0 )
|
|
{ // failue
|
|
return false;
|
|
}
|
|
|
|
// attempt to read out the values
|
|
int v = sscanf( val, "%f %f", min, max );
|
|
|
|
if ( v == 0 )
|
|
{ // nothing was there, failure
|
|
return false;
|
|
}
|
|
else if ( v == 1 )
|
|
{ // only one field entered, this is ok, but we should copy min into max
|
|
*max = *min;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------
|
|
// ParseVector
|
|
// Removes up to six values from a passed in string and
|
|
// sets these values into the passed in min and max vector
|
|
// fields. if no max is present, min is copied into it.
|
|
//
|
|
// input:
|
|
// string that contains up to six float values
|
|
// min & max are used to return the parse values
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseVector( const char *val, vec3_t min, vec3_t max )
|
|
{
|
|
// we don't allow passing in a null
|
|
if ( min == 0 || max == 0 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// attempt to read out our values
|
|
int v = sscanf( val, "%f %f %f %f %f %f", &min[0], &min[1], &min[2], &max[0], &max[1], &max[2] );
|
|
|
|
// Check for completeness
|
|
if ( v < 3 || v == 4 || v == 5 )
|
|
{ // not a complete value
|
|
return false;
|
|
}
|
|
else if ( v == 3 )
|
|
{ // only a min was entered, so copy the result into max
|
|
VectorCopy( min, max );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseGroupFlags
|
|
// Group flags are generic in nature, so we can easily
|
|
// use a generic function to parse them in, then the
|
|
// caller can shift them into the appropriate range.
|
|
//
|
|
// input:
|
|
// string that contains the flag strings
|
|
// *flags returns the set bit flags
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseGroupFlags( const char *val, int *flags )
|
|
{
|
|
// Must pass in a non-null pointer
|
|
if ( flags == 0 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
char flag[][32] = {"\0","\0","\0","0"};
|
|
bool ok = true;
|
|
|
|
// For a sub group, really you probably only have one or two flags set
|
|
int v = sscanf( val, "%s %s %s %s", flag[0], flag[1], flag[2], flag[3] );
|
|
|
|
// Clear out the flags field, then convert the flag string to an actual value ( use generic flags )
|
|
*flags = 0;
|
|
|
|
for ( int i = 0; i < 4; i++ )
|
|
{
|
|
if ( i + 1 > v )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if ( !stricmp( flag[i], "linear" ))
|
|
{
|
|
*flags |= FX_LINEAR;
|
|
}
|
|
else if ( !stricmp( flag[i], "nonlinear" ))
|
|
{
|
|
*flags |= FX_NONLINEAR;
|
|
}
|
|
else if ( !stricmp( flag[i], "wave" ))
|
|
{
|
|
*flags |= FX_WAVE;
|
|
}
|
|
else if ( !stricmp( flag[i], "random" ))
|
|
{
|
|
*flags |= FX_RAND;
|
|
}
|
|
else if ( !stricmp( flag[i], "clamp" ))
|
|
{
|
|
*flags |= FX_CLAMP;
|
|
}
|
|
else
|
|
{ // we have badness going on, but continue on in case there are any valid fields in here
|
|
ok = false;
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseMin
|
|
// Reads in a min bounding box field in vector format
|
|
//
|
|
// input:
|
|
// string that contains three float values
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseMin( const char *val )
|
|
{
|
|
vec3_t min;
|
|
|
|
if ( ParseVector( val, min, min ) == true )
|
|
{
|
|
VectorCopy( min, mMin );
|
|
|
|
// We assume that if a min is being set that we are using physics and a bounding box
|
|
mFlags |= (FX_USE_BBOX | FX_APPLY_PHYSICS);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseMax
|
|
// Reads in a max bounding box field in vector format
|
|
//
|
|
// input:
|
|
// string that contains three float values
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseMax( const char *val )
|
|
{
|
|
vec3_t max;
|
|
|
|
if ( ParseVector( val, max, max ) == true )
|
|
{
|
|
VectorCopy( max, mMax );
|
|
|
|
// We assume that if a max is being set that we are using physics and a bounding box
|
|
mFlags |= (FX_USE_BBOX | FX_APPLY_PHYSICS);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseLife
|
|
// Reads in a ranged life value
|
|
//
|
|
// input:
|
|
// string that contains a float range ( two vals )
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseLife( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mLife.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseDelay
|
|
// Reads in a ranged delay value
|
|
//
|
|
// input:
|
|
// string that contains a float range ( two vals )
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseDelay( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mSpawnDelay.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseCount
|
|
// Reads in a ranged count value
|
|
//
|
|
// input:
|
|
// string that contains a float range ( two vals )
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseCount( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mSpawnCount.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseElasticity
|
|
// Reads in a ranged elasticity value
|
|
//
|
|
// input:
|
|
// string that contains a float range ( two vals )
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseElasticity( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mElasticity.SetRange( min, max );
|
|
|
|
// We assume that if elasticity is set that we are using physics, but don't assume we are
|
|
// using a bounding box unless a min/max are explicitly set
|
|
// mFlags |= FX_APPLY_PHYSICS;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseOrigin1
|
|
// Reads in an origin field in vector format
|
|
//
|
|
// input:
|
|
// string that contains three float values
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseOrigin1( const char *val )
|
|
{
|
|
vec3_t min, max;
|
|
|
|
if ( ParseVector( val, min, max ) == true )
|
|
{
|
|
mOrigin1X.SetRange( min[0], max[0] );
|
|
mOrigin1Y.SetRange( min[1], max[1] );
|
|
mOrigin1Z.SetRange( min[2], max[2] );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseOrigin2
|
|
// Reads in an origin field in vector format
|
|
//
|
|
// input:
|
|
// string that contains three float values
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseOrigin2( const char *val )
|
|
{
|
|
vec3_t min, max;
|
|
|
|
if ( ParseVector( val, min, max ) == true )
|
|
{
|
|
mOrigin2X.SetRange( min[0], max[0] );
|
|
mOrigin2Y.SetRange( min[1], max[1] );
|
|
mOrigin2Z.SetRange( min[2], max[2] );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseRadius
|
|
// Reads in a ranged radius value
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseRadius( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mRadius.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseHeight
|
|
// Reads in a ranged height value
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseHeight( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mHeight.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseRotation
|
|
// Reads in a ranged rotation value
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseRotation( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == qtrue )
|
|
{
|
|
mRotation.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseRotationDelta
|
|
// Reads in a ranged rotationDelta value
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseRotationDelta( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == qtrue )
|
|
{
|
|
mRotationDelta.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseAngle
|
|
// Reads in a ranged angle field in vector format
|
|
//
|
|
// input:
|
|
// string that contains one or two vectors
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseAngle( const char *val )
|
|
{
|
|
vec3_t min, max;
|
|
|
|
if ( ParseVector( val, min, max ) == true )
|
|
{
|
|
mAngle1.SetRange( min[0], max[0] );
|
|
mAngle2.SetRange( min[1], max[1] );
|
|
mAngle3.SetRange( min[2], max[2] );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseAngleDelta
|
|
// Reads in a ranged angleDelta field in vector format
|
|
//
|
|
// input:
|
|
// string that contains one or two vectors
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseAngleDelta( const char *val )
|
|
{
|
|
vec3_t min, max;
|
|
|
|
if ( ParseVector( val, min, max ) == true )
|
|
{
|
|
mAngle1Delta.SetRange( min[0], max[0] );
|
|
mAngle2Delta.SetRange( min[1], max[1] );
|
|
mAngle3Delta.SetRange( min[2], max[2] );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseVelocity
|
|
// Reads in a ranged velocity field in vector format
|
|
//
|
|
// input:
|
|
// string that contains one or two vectors
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseVelocity( const char *val )
|
|
{
|
|
vec3_t min, max;
|
|
|
|
if ( ParseVector( val, min, max ) == true )
|
|
{
|
|
mVelX.SetRange( min[0], max[0] );
|
|
mVelY.SetRange( min[1], max[1] );
|
|
mVelZ.SetRange( min[2], max[2] );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseFlags
|
|
// These are flags that are not specific to a group,
|
|
// rather, they are specific to the whole primitive.
|
|
//
|
|
// input:
|
|
// string that contains the flag strings
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseFlags( const char *val )
|
|
{
|
|
char flag[][32] = {"\0","\0","\0","\0","\0","\0","\0"};
|
|
bool ok = true;
|
|
|
|
// For a primitive, really you probably only have two or less flags set
|
|
int v = sscanf( val, "%s %s %s %s %s %s %s", flag[0], flag[1], flag[2], flag[3], flag[4], flag[5], flag[6] );
|
|
|
|
for ( int i = 0; i < 7; i++ )
|
|
{
|
|
if ( i + 1 > v )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if ( !stricmp( flag[i], "useModel" ))
|
|
{
|
|
mFlags |= FX_ATTACHED_MODEL;
|
|
}
|
|
else if ( !stricmp( flag[i], "useBBox" ))
|
|
{
|
|
mFlags |= FX_USE_BBOX;
|
|
}
|
|
else if ( !stricmp( flag[i], "usePhysics" ))
|
|
{
|
|
mFlags |= FX_APPLY_PHYSICS;
|
|
}
|
|
else if ( !stricmp( flag[i], "expensivePhysics" ))
|
|
{
|
|
mFlags |= FX_EXPENSIVE_PHYSICS;
|
|
}
|
|
else if ( !stricmp( flag[i], "impactKills" ))
|
|
{
|
|
mFlags |= FX_KILL_ON_IMPACT;
|
|
}
|
|
else if ( !stricmp( flag[i], "impactFx" ))
|
|
{
|
|
mFlags |= FX_IMPACT_RUNS_FX;
|
|
}
|
|
else if ( !stricmp( flag[i], "deathFx" ))
|
|
{
|
|
mFlags |= FX_DEATH_RUNS_FX;
|
|
}
|
|
else if ( !stricmp( flag[i], "useAlpha" ))
|
|
{
|
|
mFlags |= FX_USE_ALPHA;
|
|
}
|
|
else if ( !stricmp( flag[i], "emitFx" ))
|
|
{
|
|
mFlags |= FX_EMIT_FX;
|
|
}
|
|
else if ( !stricmp( flag[i], "depthHack" ))
|
|
{
|
|
mFlags |= FX_DEPTH_HACK;
|
|
}
|
|
else if ( !stricmp( flag[i], "setShaderTime" ))
|
|
{
|
|
mFlags |= FX_SET_SHADER_TIME;
|
|
}
|
|
else
|
|
{ // we have badness going on, but continue on in case there are any valid fields in here
|
|
ok = false;
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSpawnFlags
|
|
// These kinds of flags control how things spawn. They
|
|
// never get passed on to a primitive.
|
|
//
|
|
// input:
|
|
// string that contains the flag strings
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSpawnFlags( const char *val )
|
|
{
|
|
char flag[][32] = {"\0","\0","\0","\0","\0","\0","\0"};
|
|
bool ok = true;
|
|
|
|
// For a primitive, really you probably only have two or less flags set
|
|
int v = sscanf( val, "%s %s %s %s %s %s %s", flag[0], flag[1], flag[2], flag[3], flag[4], flag[5], flag[6] );
|
|
|
|
for ( int i = 0; i < 7; i++ )
|
|
{
|
|
if ( i + 1 > v )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if ( !stricmp( flag[i], "org2fromTrace" ))
|
|
{
|
|
mSpawnFlags |= FX_ORG2_FROM_TRACE;
|
|
}
|
|
else if ( !stricmp( flag[i], "traceImpactFx" ))
|
|
{
|
|
mSpawnFlags |= FX_TRACE_IMPACT_FX;
|
|
}
|
|
else if ( !stricmp( flag[i], "org2isOffset" ))
|
|
{
|
|
mSpawnFlags |= FX_ORG2_IS_OFFSET;
|
|
}
|
|
else if ( !stricmp( flag[i], "cheapOrgCalc" ))
|
|
{
|
|
mSpawnFlags |= FX_CHEAP_ORG_CALC;
|
|
}
|
|
else if ( !stricmp( flag[i], "cheapOrg2Calc" ))
|
|
{
|
|
mSpawnFlags |= FX_CHEAP_ORG2_CALC;
|
|
}
|
|
else if ( !stricmp( flag[i], "absoluteVel" ))
|
|
{
|
|
mSpawnFlags |= FX_VEL_IS_ABSOLUTE;
|
|
}
|
|
else if ( !stricmp( flag[i], "absoluteAccel" ))
|
|
{
|
|
mSpawnFlags |= FX_ACCEL_IS_ABSOLUTE;
|
|
}
|
|
else if ( !stricmp( flag[i], "orgOnSphere" )) // sphere/ellipsoid
|
|
{
|
|
mSpawnFlags |= FX_ORG_ON_SPHERE;
|
|
}
|
|
else if ( !stricmp( flag[i], "orgOnCylinder" )) // cylinder/disk
|
|
{
|
|
mSpawnFlags |= FX_ORG_ON_CYLINDER;
|
|
}
|
|
else if ( !stricmp( flag[i], "axisFromSphere" ))
|
|
{
|
|
mSpawnFlags |= FX_AXIS_FROM_SPHERE;
|
|
}
|
|
else if ( !stricmp( flag[i], "randrotaroundfwd" ))
|
|
{
|
|
mSpawnFlags |= FX_RAND_ROT_AROUND_FWD;
|
|
}
|
|
else if ( !stricmp( flag[i], "evenDistribution" ))
|
|
{
|
|
mSpawnFlags |= FX_EVEN_DISTRIBUTION;
|
|
}
|
|
else if ( !stricmp( flag[i], "rgbComponentInterpolation" ))
|
|
{
|
|
mSpawnFlags |= FX_RGB_COMPONENT_INTERP;
|
|
}
|
|
else if ( !stricmp( flag[i], "lessAttenuation" ))
|
|
{
|
|
mSpawnFlags |= FX_SND_LESS_ATTENUATION;
|
|
}
|
|
else
|
|
{ // we have badness going on, but continue on in case there are any valid fields in here
|
|
ok = false;
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseAcceleration
|
|
// Reads in a ranged acceleration field in vector format
|
|
//
|
|
// input:
|
|
// string that contains one or two vectors
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseAcceleration( const char *val )
|
|
{
|
|
vec3_t min, max;
|
|
|
|
if ( ParseVector( val, min, max ) == true )
|
|
{
|
|
mAccelX.SetRange( min[0], max[0] );
|
|
mAccelY.SetRange( min[1], max[1] );
|
|
mAccelZ.SetRange( min[2], max[2] );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseGravity
|
|
// Reads in a ranged gravity value
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseGravity( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mGravity.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseDensity
|
|
// Reads in a ranged density value. Density is only
|
|
// for emitters that are calling effects...it basically
|
|
// specifies how often the emitter should emit fx.
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseDensity( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mDensity.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseVariance
|
|
// Reads in a ranged variance value. Variance is only
|
|
// valid for emitters that are calling effects...
|
|
// it basically determines the amount of slop in the
|
|
// density calculations
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseVariance( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mVariance.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseRGBStart
|
|
// Reads in a ranged rgbStart field in vector format
|
|
//
|
|
// input:
|
|
// string that contains one or two vectors
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseRGBStart( const char *val )
|
|
{
|
|
vec3_t min, max;
|
|
|
|
if ( ParseVector( val, min, max ) == true )
|
|
{
|
|
mRedStart.SetRange( min[0], max[0] );
|
|
mGreenStart.SetRange( min[1], max[1] );
|
|
mBlueStart.SetRange( min[2], max[2] );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseRGBEnd
|
|
// Reads in a ranged rgbEnd field in vector format
|
|
//
|
|
// input:
|
|
// string that contains one or two vectors
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseRGBEnd( const char *val )
|
|
{
|
|
vec3_t min, max;
|
|
|
|
if ( ParseVector( val, min, max ) == true )
|
|
{
|
|
mRedEnd.SetRange( min[0], max[0] );
|
|
mGreenEnd.SetRange( min[1], max[1] );
|
|
mBlueEnd.SetRange( min[2], max[2] );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseRGBParm
|
|
// Reads in a ranged rgbParm field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseRGBParm( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mRGBParm.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseRGBFlags
|
|
// Reads in a set of rgbFlags in string format
|
|
//
|
|
// input:
|
|
// string that contains the flag strings
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseRGBFlags( const char *val )
|
|
{
|
|
int flags;
|
|
|
|
if ( ParseGroupFlags( val, &flags ) == true )
|
|
{
|
|
// Convert our generic flag values into type specific ones
|
|
mFlags |= ( flags << FX_RGB_SHIFT );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseAlphaStart
|
|
// Reads in a ranged alphaStart field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseAlphaStart( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mAlphaStart.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseAlphaEnd
|
|
// Reads in a ranged alphaEnd field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseAlphaEnd( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mAlphaEnd.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseAlphaParm
|
|
// Reads in a ranged alphaParm field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseAlphaParm( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mAlphaParm.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseAlphaFlags
|
|
// Reads in a set of alphaFlags in string format
|
|
//
|
|
// input:
|
|
// string that contains the flag strings
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseAlphaFlags( const char *val )
|
|
{
|
|
int flags;
|
|
|
|
if ( ParseGroupFlags( val, &flags ) == true )
|
|
{
|
|
// Convert our generic flag values into type specific ones
|
|
mFlags |= ( flags << FX_ALPHA_SHIFT );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSizeStart
|
|
// Reads in a ranged sizeStart field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSizeStart( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mSizeStart.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSizeEnd
|
|
// Reads in a ranged sizeEnd field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSizeEnd( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mSizeEnd.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSizeParm
|
|
// Reads in a ranged sizeParm field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSizeParm( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mSizeParm.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSizeFlags
|
|
// Reads in a set of sizeFlags in string format
|
|
//
|
|
// input:
|
|
// string that contains the flag strings
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSizeFlags( const char *val )
|
|
{
|
|
int flags;
|
|
|
|
if ( ParseGroupFlags( val, &flags ) == true )
|
|
{
|
|
// Convert our generic flag values into type specific ones
|
|
mFlags |= ( flags << FX_SIZE_SHIFT );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSize2Start
|
|
// Reads in a ranged Size2Start field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSize2Start( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mSize2Start.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSize2End
|
|
// Reads in a ranged Size2End field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSize2End( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mSize2End.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSize2Parm
|
|
// Reads in a ranged Size2Parm field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSize2Parm( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mSize2Parm.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSize2Flags
|
|
// Reads in a set of Size2Flags in string format
|
|
//
|
|
// input:
|
|
// string that contains the flag strings
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSize2Flags( const char *val )
|
|
{
|
|
int flags;
|
|
|
|
if ( ParseGroupFlags( val, &flags ) == true )
|
|
{
|
|
// Convert our generic flag values into type specific ones
|
|
mFlags |= ( flags << FX_SIZE2_SHIFT );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseLengthStart
|
|
// Reads in a ranged lengthStart field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseLengthStart( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mLengthStart.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseLengthEnd
|
|
// Reads in a ranged lengthEnd field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseLengthEnd( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mLengthEnd.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseLengthParm
|
|
// Reads in a ranged lengthParm field in float format
|
|
//
|
|
// input:
|
|
// string that contains one or two floats
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseLengthParm( const char *val )
|
|
{
|
|
float min, max;
|
|
|
|
if ( ParseFloat( val, &min, &max ) == true )
|
|
{
|
|
mLengthParm.SetRange( min, max );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseLengthFlags
|
|
// Reads in a set of lengthFlags in string format
|
|
//
|
|
// input:
|
|
// string that contains the flag strings
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseLengthFlags( const char *val )
|
|
{
|
|
int flags;
|
|
|
|
if ( ParseGroupFlags( val, &flags ) == true )
|
|
{
|
|
// Convert our generic flag values into type specific ones
|
|
mFlags |= ( flags << FX_LENGTH_SHIFT );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseShaders
|
|
// Reads in a group of shaders and registers them
|
|
//
|
|
// input:
|
|
// Parse group that contains the list of shaders to parse
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseShaders( CGPValue *grp )
|
|
{
|
|
const char *val;
|
|
int handle;
|
|
|
|
if ( grp->IsList() )
|
|
{
|
|
// If we are a list we have to do separate processing
|
|
CGPObject *list = grp->GetList();
|
|
|
|
while ( list )
|
|
{
|
|
// name is actually the value contained in the list
|
|
val = list->GetName();
|
|
|
|
handle = theFxHelper.RegisterShader( val );
|
|
mMediaHandles.AddHandle( handle );
|
|
|
|
list = (CGPValue *)list->GetNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Let's get a value
|
|
val = grp->GetTopValue();
|
|
|
|
if ( val )
|
|
{
|
|
handle = theFxHelper.RegisterShader( val );
|
|
mMediaHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
// empty "list"
|
|
theFxHelper.Print( "CPrimitiveTemplate::ParseShaders called with an empty list!\n" );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSounds
|
|
// Reads in a group of sounds and registers them
|
|
//
|
|
// input:
|
|
// Parse group that contains the list of sounds to parse
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSounds( CGPValue *grp )
|
|
{
|
|
const char *val;
|
|
int handle;
|
|
|
|
if ( grp->IsList() )
|
|
{
|
|
// If we are a list we have to do separate processing
|
|
CGPObject *list = grp->GetList();
|
|
|
|
while ( list )
|
|
{
|
|
// name is actually the value contained in the list
|
|
val = list->GetName();
|
|
|
|
handle = theFxHelper.RegisterSound( val );
|
|
mMediaHandles.AddHandle( handle );
|
|
|
|
list = (CGPValue *)list->GetNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Let's get a value
|
|
val = grp->GetTopValue();
|
|
|
|
if ( val )
|
|
{
|
|
handle = theFxHelper.RegisterSound( val );
|
|
mMediaHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
// empty "list"
|
|
theFxHelper.Print( "CPrimitiveTemplate::ParseSounds called with an empty list!\n" );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#ifdef _IMMERSION
|
|
//------------------------------------------------------
|
|
// ParseForces
|
|
// Reads in a group of forces and registers them
|
|
//
|
|
// input:
|
|
// Parse group that contains the list of forces to parse
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseForces( CGPValue *grp )
|
|
{
|
|
const char *val;
|
|
int handle;
|
|
|
|
if ( grp->IsList() )
|
|
{
|
|
// If we are a list we have to do separate processing
|
|
CGPObject *list = grp->GetList();
|
|
|
|
while ( list )
|
|
{
|
|
// name is actually the value contained in the list
|
|
val = list->GetName();
|
|
|
|
// Assumes FF_CHANNEL_WEAPON because sound mechanism assumes this
|
|
handle = theFxHelper.RegisterForce( val, FF_CHANNEL_WEAPON );
|
|
mMediaHandles.AddHandle( handle );
|
|
|
|
list = (CGPValue *)list->GetNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Let's get a value
|
|
val = grp->GetTopValue();
|
|
|
|
if ( val )
|
|
{
|
|
// Assumes FF_CHANNEL_WEAPON because sound mechanism assumes this
|
|
handle = theFxHelper.RegisterForce( val, FF_CHANNEL_WEAPON );
|
|
mMediaHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
// empty "list"
|
|
theFxHelper.Print( "CPrimitiveTemplate::ParseForces called with an empty list!\n" );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#endif // _IMMERSION
|
|
//------------------------------------------------------
|
|
// ParseModels
|
|
// Reads in a group of models and registers them
|
|
//
|
|
// input:
|
|
// Parse group that contains the list of models to parse
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseModels( CGPValue *grp )
|
|
{
|
|
const char *val;
|
|
int handle;
|
|
|
|
if ( grp->IsList() )
|
|
{
|
|
// If we are a list we have to do separate processing
|
|
CGPObject *list = grp->GetList();
|
|
|
|
while ( list )
|
|
{
|
|
// name is actually the value contained in the list
|
|
val = list->GetName();
|
|
|
|
handle = theFxHelper.RegisterModel( val );
|
|
mMediaHandles.AddHandle( handle );
|
|
|
|
list = (CGPValue *)list->GetNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Let's get a value
|
|
val = grp->GetTopValue();
|
|
|
|
if ( val )
|
|
{
|
|
handle = theFxHelper.RegisterModel( val );
|
|
mMediaHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
// empty "list"
|
|
theFxHelper.Print( "CPrimitiveTemplate::ParseModels called with an empty list!\n" );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
mFlags |= FX_ATTACHED_MODEL;
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseImpactFxStrings
|
|
// Reads in a group of fx file names and registers them
|
|
//
|
|
// input:
|
|
// Parse group that contains the list of fx to parse
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseImpactFxStrings( CGPValue *grp )
|
|
{
|
|
const char *val;
|
|
int handle;
|
|
|
|
if ( grp->IsList() )
|
|
{
|
|
// If we are a list we have to do separate processing
|
|
CGPObject *list = grp->GetList();
|
|
|
|
while ( list )
|
|
{
|
|
// name is actually the value contained in the list
|
|
val = list->GetName();
|
|
handle = theFxScheduler.RegisterEffect( val );
|
|
|
|
if ( handle )
|
|
{
|
|
mImpactFxHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "FxTemplate: Impact effect file not found.\n" );
|
|
return false;
|
|
}
|
|
|
|
list = (CGPValue *)list->GetNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Let's get a value
|
|
val = grp->GetTopValue();
|
|
|
|
if ( val )
|
|
{
|
|
handle = theFxScheduler.RegisterEffect( val );
|
|
|
|
if ( handle )
|
|
{
|
|
mImpactFxHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "FxTemplate: Impact effect file not found.\n" );
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// empty "list"
|
|
theFxHelper.Print( "CPrimitiveTemplate::ParseImpactFxStrings called with an empty list!\n" );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
mFlags |= FX_IMPACT_RUNS_FX | FX_APPLY_PHYSICS;
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseDeathFxStrings
|
|
// Reads in a group of fx file names and registers them
|
|
//
|
|
// input:
|
|
// Parse group that contains the list of fx to parse
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseDeathFxStrings( CGPValue *grp )
|
|
{
|
|
const char *val;
|
|
int handle;
|
|
|
|
if ( grp->IsList() )
|
|
{
|
|
// If we are a list we have to do separate processing
|
|
CGPObject *list = grp->GetList();
|
|
|
|
while ( list )
|
|
{
|
|
// name is actually the value contained in the list
|
|
val = list->GetName();
|
|
handle = theFxScheduler.RegisterEffect( val );
|
|
|
|
if ( handle )
|
|
{
|
|
mDeathFxHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "FxTemplate: Death effect file not found.\n" );
|
|
return false;
|
|
}
|
|
|
|
list = (CGPValue *)list->GetNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Let's get a value
|
|
val = grp->GetTopValue();
|
|
|
|
if ( val )
|
|
{
|
|
handle = theFxScheduler.RegisterEffect( val );
|
|
|
|
if ( handle )
|
|
{
|
|
mDeathFxHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "FxTemplate: Death effect file not found.\n" );
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// empty "list"
|
|
theFxHelper.Print( "CPrimitiveTemplate::ParseDeathFxStrings called with an empty list!\n" );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
mFlags |= FX_DEATH_RUNS_FX;
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseEmitterFxStrings
|
|
// Reads in a group of fx file names and registers them
|
|
//
|
|
// input:
|
|
// Parse group that contains the list of fx to parse
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseEmitterFxStrings( CGPValue *grp )
|
|
{
|
|
const char *val;
|
|
int handle;
|
|
|
|
if ( grp->IsList() )
|
|
{
|
|
// If we are a list we have to do separate processing
|
|
CGPObject *list = grp->GetList();
|
|
|
|
while ( list )
|
|
{
|
|
// name is actually the value contained in the list
|
|
val = list->GetName();
|
|
handle = theFxScheduler.RegisterEffect( val );
|
|
|
|
if ( handle )
|
|
{
|
|
mEmitterFxHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "FxTemplate: Emitter effect file not found.\n" );
|
|
return false;
|
|
}
|
|
|
|
list = (CGPValue *)list->GetNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Let's get a value
|
|
val = grp->GetTopValue();
|
|
|
|
if ( val )
|
|
{
|
|
handle = theFxScheduler.RegisterEffect( val );
|
|
|
|
if ( handle )
|
|
{
|
|
mEmitterFxHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "FxTemplate: Emitter effect file not found.\n" );
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// empty "list"
|
|
theFxHelper.Print( "CPrimitiveTemplate::ParseEmitterFxStrings called with an empty list!\n" );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
mFlags |= FX_EMIT_FX;
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParsePlayFxStrings
|
|
// Reads in a group of fx file names and registers them
|
|
//
|
|
// input:
|
|
// Parse group that contains the list of fx to parse
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParsePlayFxStrings( CGPValue *grp )
|
|
{
|
|
const char *val;
|
|
int handle;
|
|
|
|
if ( grp->IsList() )
|
|
{
|
|
// If we are a list we have to do separate processing
|
|
CGPObject *list = grp->GetList();
|
|
|
|
while ( list )
|
|
{
|
|
// name is actually the value contained in the list
|
|
val = list->GetName();
|
|
handle = theFxScheduler.RegisterEffect( val );
|
|
|
|
if ( handle )
|
|
{
|
|
mPlayFxHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "FxTemplate: Effect file not found.\n" );
|
|
return false;
|
|
}
|
|
|
|
list = (CGPValue *)list->GetNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Let's get a value
|
|
val = grp->GetTopValue();
|
|
|
|
if ( val )
|
|
{
|
|
handle = theFxScheduler.RegisterEffect( val );
|
|
|
|
if ( handle )
|
|
{
|
|
mPlayFxHandles.AddHandle( handle );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "FxTemplate: Effect file not found.\n" );
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// empty "list"
|
|
theFxHelper.Print( "CPrimitiveTemplate::ParsePlayFxStrings called with an empty list!\n" );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseRGB
|
|
// Takes an RGB group and chomps out any pairs contained
|
|
// in it.
|
|
//
|
|
// input:
|
|
// the parse group to process
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseRGB( CGPGroup *grp )
|
|
{
|
|
CGPValue *pairs;
|
|
const char *key;
|
|
const char *val;
|
|
|
|
// Inside of the group, we should have a series of pairs
|
|
pairs = grp->GetPairs();
|
|
|
|
while( pairs )
|
|
{
|
|
// Let's get the key field
|
|
key = pairs->GetName();
|
|
val = pairs->GetTopValue();
|
|
|
|
// Huge stricmp lists suxor
|
|
if ( !stricmp( key, "start" ))
|
|
{
|
|
ParseRGBStart( val );
|
|
}
|
|
else if ( !stricmp( key, "end" ))
|
|
{
|
|
ParseRGBEnd( val );
|
|
}
|
|
else if ( !stricmp( key, "parm" ) || !stricmp( key, "parms" ))
|
|
{
|
|
ParseRGBParm( val );
|
|
}
|
|
else if ( !stricmp( key, "flags" ) || !stricmp( key, "flag" ))
|
|
{
|
|
ParseRGBFlags( val );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "Unknown key parsing an RGB group: %s\n", key );
|
|
}
|
|
|
|
pairs = (CGPValue *)pairs->GetNext();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseAlpha
|
|
// Takes an alpha group and chomps out any pairs contained
|
|
// in it.
|
|
//
|
|
// input:
|
|
// the parse group to process
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseAlpha( CGPGroup *grp )
|
|
{
|
|
CGPValue *pairs;
|
|
const char *key;
|
|
const char *val;
|
|
|
|
// Inside of the group, we should have a series of pairs
|
|
pairs = grp->GetPairs();
|
|
|
|
while( pairs )
|
|
{
|
|
// Let's get the key field
|
|
key = pairs->GetName();
|
|
val = pairs->GetTopValue();
|
|
|
|
// Huge stricmp lists suxor
|
|
if ( !stricmp( key, "start" ))
|
|
{
|
|
ParseAlphaStart( val );
|
|
}
|
|
else if ( !stricmp( key, "end" ))
|
|
{
|
|
ParseAlphaEnd( val );
|
|
}
|
|
else if ( !stricmp( key, "parm" ) || !stricmp( key, "parms" ))
|
|
{
|
|
ParseAlphaParm( val );
|
|
}
|
|
else if ( !stricmp( key, "flags" ) || !stricmp( key, "flag" ))
|
|
{
|
|
ParseAlphaFlags( val );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "Unknown key parsing an Alpha group: %s\n", key );
|
|
}
|
|
|
|
pairs = (CGPValue *)pairs->GetNext();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSize
|
|
// Takes a size group and chomps out any pairs contained
|
|
// in it.
|
|
//
|
|
// input:
|
|
// the parse group to process
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSize( CGPGroup *grp )
|
|
{
|
|
CGPValue *pairs;
|
|
const char *key;
|
|
const char *val;
|
|
|
|
// Inside of the group, we should have a series of pairs
|
|
pairs = grp->GetPairs();
|
|
|
|
while( pairs )
|
|
{
|
|
// Let's get the key field
|
|
key = pairs->GetName();
|
|
val = pairs->GetTopValue();
|
|
|
|
// Huge stricmp lists suxor
|
|
if ( !stricmp( key, "start" ))
|
|
{
|
|
ParseSizeStart( val );
|
|
}
|
|
else if ( !stricmp( key, "end" ))
|
|
{
|
|
ParseSizeEnd( val );
|
|
}
|
|
else if ( !stricmp( key, "parm" ) || !stricmp( key, "parms" ))
|
|
{
|
|
ParseSizeParm( val );
|
|
}
|
|
else if ( !stricmp( key, "flags" ) || !stricmp( key, "flag" ))
|
|
{
|
|
ParseSizeFlags( val );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "Unknown key parsing a Size group: %s\n", key );
|
|
}
|
|
|
|
pairs = (CGPValue *)pairs->GetNext();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseSize2
|
|
// Takes a Size2 group and chomps out any pairs contained
|
|
// in it.
|
|
//
|
|
// input:
|
|
// the parse group to process
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseSize2( CGPGroup *grp )
|
|
{
|
|
CGPValue *pairs;
|
|
const char *key;
|
|
const char *val;
|
|
|
|
// Inside of the group, we should have a series of pairs
|
|
pairs = grp->GetPairs();
|
|
|
|
while( pairs )
|
|
{
|
|
// Let's get the key field
|
|
key = pairs->GetName();
|
|
val = pairs->GetTopValue();
|
|
|
|
// Huge stricmp lists suxor
|
|
if ( !stricmp( key, "start" ))
|
|
{
|
|
ParseSize2Start( val );
|
|
}
|
|
else if ( !stricmp( key, "end" ))
|
|
{
|
|
ParseSize2End( val );
|
|
}
|
|
else if ( !stricmp( key, "parm" ) || !stricmp( key, "parms" ))
|
|
{
|
|
ParseSize2Parm( val );
|
|
}
|
|
else if ( !stricmp( key, "flags" ) || !stricmp( key, "flag" ))
|
|
{
|
|
ParseSize2Flags( val );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "Unknown key parsing a Size2 group: %s\n", key );
|
|
}
|
|
|
|
pairs = (CGPValue *)pairs->GetNext();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ParseLength
|
|
// Takes a length group and chomps out any pairs contained
|
|
// in it.
|
|
//
|
|
// input:
|
|
// the parse group to process
|
|
//
|
|
// return:
|
|
// success of parse operation.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParseLength( CGPGroup *grp )
|
|
{
|
|
CGPValue *pairs;
|
|
const char *key;
|
|
const char *val;
|
|
|
|
// Inside of the group, we should have a series of pairs
|
|
pairs = grp->GetPairs();
|
|
|
|
while( pairs )
|
|
{
|
|
// Let's get the key field
|
|
key = pairs->GetName();
|
|
val = pairs->GetTopValue();
|
|
|
|
// Huge stricmp lists suxor
|
|
if ( !stricmp( key, "start" ))
|
|
{
|
|
ParseLengthStart( val );
|
|
}
|
|
else if ( !stricmp( key, "end" ))
|
|
{
|
|
ParseLengthEnd( val );
|
|
}
|
|
else if ( !stricmp( key, "parm" ) || !stricmp( key, "parms" ))
|
|
{
|
|
ParseLengthParm( val );
|
|
}
|
|
else if ( !stricmp( key, "flags" ) || !stricmp( key, "flag" ))
|
|
{
|
|
ParseLengthFlags( val );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "Unknown key parsing a Length group: %s\n", key );
|
|
}
|
|
|
|
pairs = (CGPValue *)pairs->GetNext();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// Parse a primitive, apply defaults first, grab any base level
|
|
// key pairs, then process any sub groups we may contain.
|
|
//------------------------------------------------------
|
|
bool CPrimitiveTemplate::ParsePrimitive( CGPGroup *grp )
|
|
{
|
|
CGPGroup *subGrp;
|
|
CGPValue *pairs;
|
|
const char *key;
|
|
const char *val;
|
|
|
|
// Lets work with the pairs first
|
|
pairs = grp->GetPairs();
|
|
|
|
while( pairs )
|
|
{
|
|
// the fields
|
|
key = pairs->GetName();
|
|
val = pairs->GetTopValue();
|
|
|
|
// Huge stricmp lists suxor
|
|
if ( !stricmp( key, "count" ))
|
|
{
|
|
ParseCount( val );
|
|
}
|
|
else if ( !stricmp( key, "shaders" ) || !stricmp( key, "shader" ))
|
|
{
|
|
ParseShaders( pairs );
|
|
}
|
|
else if ( !stricmp( key, "models" ) || !stricmp( key, "model" ))
|
|
{
|
|
ParseModels( pairs );
|
|
}
|
|
else if ( !stricmp( key, "sounds" ) || !stricmp( key, "sound" ))
|
|
{
|
|
ParseSounds( pairs );
|
|
}
|
|
#ifdef _IMMERSION
|
|
else if ( !stricmp( key, "forces" ) || !stricmp( key, "force" ))
|
|
{
|
|
ParseForces( pairs );
|
|
}
|
|
#endif // _IMMERSION
|
|
else if ( !stricmp( key, "impactfx" ))
|
|
{
|
|
ParseImpactFxStrings( pairs );
|
|
}
|
|
else if ( !stricmp( key, "deathfx" ))
|
|
{
|
|
ParseDeathFxStrings( pairs );
|
|
}
|
|
else if ( !stricmp( key, "emitfx" ))
|
|
{
|
|
ParseEmitterFxStrings( pairs );
|
|
}
|
|
else if ( !stricmp( key, "playfx" ))
|
|
{
|
|
ParsePlayFxStrings( pairs );
|
|
}
|
|
else if ( !stricmp( key, "life" ))
|
|
{
|
|
ParseLife( val );
|
|
}
|
|
else if ( !stricmp( key, "cullrange" ))
|
|
{
|
|
mCullRange = atoi( val );
|
|
mCullRange *= mCullRange; // Square
|
|
}
|
|
else if ( !stricmp( key, "delay" ))
|
|
{
|
|
ParseDelay( val );
|
|
}
|
|
else if ( !stricmp( key, "bounce" ) || !stricmp( key, "intensity" )) // me==bad for reusing this...but it shouldn't hurt anything)
|
|
{
|
|
ParseElasticity( val );
|
|
}
|
|
else if ( !stricmp( key, "min" ))
|
|
{
|
|
ParseMin( val );
|
|
}
|
|
else if ( !stricmp( key, "max" ))
|
|
{
|
|
ParseMax( val );
|
|
}
|
|
else if ( !stricmp( key, "angle" ) || !stricmp( key, "angles" ))
|
|
{
|
|
ParseAngle( val );
|
|
}
|
|
else if ( !stricmp( key, "angleDelta" ))
|
|
{
|
|
ParseAngleDelta( val );
|
|
}
|
|
else if ( !stricmp( key, "velocity" ) || !stricmp( key, "vel" ))
|
|
{
|
|
ParseVelocity( val );
|
|
}
|
|
else if ( !stricmp( key, "acceleration" ) || !stricmp( key, "accel" ))
|
|
{
|
|
ParseAcceleration( val );
|
|
}
|
|
else if ( !stricmp( key, "gravity" ))
|
|
{
|
|
ParseGravity( val );
|
|
}
|
|
else if ( !stricmp( key, "density" ))
|
|
{
|
|
ParseDensity( val );
|
|
}
|
|
else if ( !stricmp( key, "variance" ))
|
|
{
|
|
ParseVariance( val );
|
|
}
|
|
else if ( !stricmp( key, "origin" ))
|
|
{
|
|
ParseOrigin1( val );
|
|
}
|
|
else if ( !stricmp( key, "origin2" ))
|
|
{
|
|
ParseOrigin2( val );
|
|
}
|
|
else if ( !stricmp( key, "radius" )) // part of ellipse/cylinder calcs.
|
|
{
|
|
ParseRadius( val );
|
|
}
|
|
else if ( !stricmp( key, "height" )) // part of ellipse/cylinder calcs.
|
|
{
|
|
ParseHeight( val );
|
|
}
|
|
else if ( !stricmp( key, "rotation" ))
|
|
{
|
|
ParseRotation( val );
|
|
}
|
|
else if ( !Q_stricmp( key, "rotationDelta" ))
|
|
{
|
|
ParseRotationDelta( val );
|
|
}
|
|
else if ( !stricmp( key, "flags" ) || !stricmp( key, "flag" ))
|
|
{ // these need to get passed on to the primitive
|
|
ParseFlags( val );
|
|
}
|
|
else if ( !stricmp( key, "spawnFlags" ) || !stricmp( key, "spawnFlag" ))
|
|
{ // these are used to spawn things in cool ways, but don't ever get passed on to prims.
|
|
ParseSpawnFlags( val );
|
|
}
|
|
else if ( !stricmp( key, "name" ))
|
|
{
|
|
if ( val )
|
|
{
|
|
// just stash the descriptive name of the primitive
|
|
strcpy( mName, val );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "Unknown key parsing an effect primitive: %s\n", key );
|
|
}
|
|
|
|
pairs = (CGPValue *)pairs->GetNext();
|
|
}
|
|
|
|
subGrp = grp->GetSubGroups();
|
|
|
|
// Lets chomp on the groups now
|
|
while ( subGrp )
|
|
{
|
|
key = subGrp->GetName();
|
|
|
|
if ( !stricmp( key, "rgb" ))
|
|
{
|
|
ParseRGB( subGrp );
|
|
}
|
|
else if ( !stricmp( key, "alpha" ))
|
|
{
|
|
ParseAlpha( subGrp );
|
|
}
|
|
else if ( !stricmp( key, "size" ) || !stricmp( key, "width" ))
|
|
{
|
|
ParseSize( subGrp );
|
|
}
|
|
else if ( !stricmp( key, "size2" ) || !stricmp( key, "width2" ))
|
|
{
|
|
ParseSize2( subGrp );
|
|
}
|
|
else if ( !stricmp( key, "length" ) || !stricmp( key, "height" ))
|
|
{
|
|
ParseLength( subGrp );
|
|
}
|
|
else
|
|
{
|
|
theFxHelper.Print( "Unknown group key parsing a particle: %s\n", key );
|
|
}
|
|
|
|
subGrp = (CGPGroup *)subGrp->GetNext();
|
|
}
|
|
|
|
return true;
|
|
} |