Initial commit.
This commit is contained in:
505
codemp/client/fxscheduler.h
Normal file
505
codemp/client/fxscheduler.h
Normal file
@@ -0,0 +1,505 @@
|
||||
|
||||
#if !defined(FX_UTIL_H_INC)
|
||||
#include "FxUtil.h"
|
||||
#endif
|
||||
|
||||
#if !defined(GENERICPARSER2_H_INC)
|
||||
#include "../qcommon/GenericParser2.h"
|
||||
#endif
|
||||
|
||||
#ifndef FX_SCHEDULER_H_INC
|
||||
#define FX_SCHEDULER_H_INC
|
||||
|
||||
#pragma warning (push, 3) //go back down to 3 for the stl include
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#pragma warning (pop)
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
#define FX_FILE_PATH "effects"
|
||||
|
||||
#define FX_MAX_TRACE_DIST 16384 // SOF2 uses a larger scale
|
||||
#define FX_MAX_EFFECTS 256 // how many effects the system can store
|
||||
#define FX_MAX_2DEFFECTS 64 // how many 2d effects the system can store
|
||||
#define FX_MAX_EFFECT_COMPONENTS 24 // how many primitives an effect can hold, this should be plenty
|
||||
#define FX_MAX_PRIM_NAME 32
|
||||
|
||||
//-----------------------------------------------
|
||||
// These are spawn flags for primitiveTemplates
|
||||
//-----------------------------------------------
|
||||
|
||||
#define FX_ORG_ON_SPHERE 0x00001 // Pretty dang expensive, calculates a point on a sphere/ellipsoid
|
||||
#define FX_AXIS_FROM_SPHERE 0x00002 // Can be used in conjunction with org_on_sphere to cause particles to move out
|
||||
// from the center of the sphere
|
||||
#define FX_ORG_ON_CYLINDER 0x00004 // calculate point on cylinder/disk
|
||||
|
||||
#define FX_ORG2_FROM_TRACE 0x00010
|
||||
#define FX_TRACE_IMPACT_FX 0x00020 // if trace impacts, we should play one of the specified impact fx files
|
||||
#define FX_ORG2_IS_OFFSET 0x00040 // template specified org2 should be the offset from a trace endpos or
|
||||
// passed in org2. You might use this to lend a random flair to the endpos.
|
||||
// Note: this is done pre-trace, so you may have to specify large numbers for this
|
||||
|
||||
#define FX_CHEAP_ORG_CALC 0x00100 // Origin is calculated relative to passed in axis unless this is on.
|
||||
#define FX_CHEAP_ORG2_CALC 0x00200 // Origin2 is calculated relative to passed in axis unless this is on.
|
||||
#define FX_VEL_IS_ABSOLUTE 0x00400 // Velocity isn't relative to passed in axis with this flag on.
|
||||
#define FX_ACCEL_IS_ABSOLUTE 0x00800 // Acceleration isn't relative to passed in axis with this flag on.
|
||||
|
||||
#define FX_RAND_ROT_AROUND_FWD 0x01000 // Randomly rotates up and right around forward vector
|
||||
#define FX_EVEN_DISTRIBUTION 0x02000 // When you have a delay, it normally picks a random time to play. When
|
||||
// this flag is on, it generates an even time distribution
|
||||
#define FX_RGB_COMPONENT_INTERP 0x04000 // Picks a color on the line defined by RGB min & max, default is to pick color in cube defined by min & max
|
||||
|
||||
#define FX_AFFECTED_BY_WIND 0x10000 // this effect primitive needs to query wind
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
// CMediaHandles
|
||||
//
|
||||
// Primitive templates might want to use a list of sounds, shaders
|
||||
// or models to get a bit more variation in their effects.
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
class CMediaHandles
|
||||
{
|
||||
private:
|
||||
|
||||
vector<int> mMediaList;
|
||||
|
||||
public:
|
||||
|
||||
void AddHandle( int item ) { mMediaList.push_back( item ); }
|
||||
int GetHandle() { if (mMediaList.size()==0) {return 0;}
|
||||
else {return mMediaList[irand(0,mMediaList.size()-1)];} }
|
||||
|
||||
void operator=(const CMediaHandles &that );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
// CFxRange
|
||||
//
|
||||
// Primitive templates typically use this class to define each of
|
||||
// its members. This is done to make it easier to create effects
|
||||
// with a desired range of characteristics.
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
class CFxRange
|
||||
{
|
||||
private:
|
||||
|
||||
float mMin;
|
||||
float mMax;
|
||||
|
||||
public:
|
||||
|
||||
CFxRange(void) { mMin = 0.0f; mMax = 0.0f; }
|
||||
|
||||
inline void SetRange(float min,float max) { mMin = min; mMax = max; }
|
||||
|
||||
inline float GetMax(void) const { return mMax; }
|
||||
inline float GetMin(void) const { return mMin; }
|
||||
inline float GetVal(float fraction) const { if(mMin != mMax) { return mMin + fraction * (mMax - mMin); } else { return mMin; } }
|
||||
inline float GetVal(void) const { if(mMin != mMax) { return flrand(mMin,mMax); } else { return mMin; } }
|
||||
|
||||
inline int GetRoundedVal() const {if(mMin == mMax){return (int)mMin;}
|
||||
return (int)(flrand(mMin, mMax) + 0.5f);}
|
||||
|
||||
bool operator==(const CFxRange &rhs) const { return ((mMin == rhs.mMin) && (mMax == rhs.mMax)); }
|
||||
};
|
||||
|
||||
|
||||
//----------------------------
|
||||
// Supported primitive types
|
||||
//----------------------------
|
||||
|
||||
enum EPrimType
|
||||
{
|
||||
None = 0,
|
||||
Particle, // sprite
|
||||
Line,
|
||||
Tail, // comet-like tail thing
|
||||
Cylinder,
|
||||
Emitter, // emits effects as it moves, can also attach a chunk
|
||||
Sound,
|
||||
Decal, // projected onto architecture
|
||||
OrientedParticle,
|
||||
Electricity,
|
||||
FxRunner,
|
||||
Light,
|
||||
CameraShake,
|
||||
ScreenFlash
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
// CPrimitiveTemplate
|
||||
//
|
||||
// The primitive template is used to spawn 1 or more fx primitives
|
||||
// with the range of characteristics defined by the template.
|
||||
//
|
||||
// As such, I just made this one huge shared class knowing that
|
||||
// there won't be many of them in memory at once, and we won't
|
||||
// be dynamically creating and deleting them mid-game. Also,
|
||||
// note that not every primitive type will use all of these fields.
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
class CPrimitiveTemplate
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// These kinds of things should not even be allowed to be accessed publicly
|
||||
bool mCopy;
|
||||
int mRefCount; // For a copy of a primitive...when we figure out how many items we want to spawn,
|
||||
// we'll store that here and then decrement us for each we actually spawn. When we
|
||||
// hit zero, we are no longer used and so we can just free ourselves
|
||||
|
||||
char mName[FX_MAX_PRIM_NAME];
|
||||
|
||||
EPrimType mType;
|
||||
|
||||
CFxRange mSpawnDelay;
|
||||
CFxRange mSpawnCount;
|
||||
CFxRange mLife;
|
||||
int mCullRange;
|
||||
|
||||
CMediaHandles mMediaHandles;
|
||||
CMediaHandles mImpactFxHandles;
|
||||
CMediaHandles mDeathFxHandles;
|
||||
CMediaHandles mEmitterFxHandles;
|
||||
CMediaHandles mPlayFxHandles;
|
||||
|
||||
int mFlags; // These need to get passed on to the primitive
|
||||
int mSpawnFlags; // These are only used to control spawning, but never get passed to prims.
|
||||
|
||||
EMatImpactEffect mMatImpactFX;
|
||||
|
||||
vec3_t mMin;
|
||||
vec3_t mMax;
|
||||
|
||||
CFxRange mOrigin1X;
|
||||
CFxRange mOrigin1Y;
|
||||
CFxRange mOrigin1Z;
|
||||
|
||||
CFxRange mOrigin2X;
|
||||
CFxRange mOrigin2Y;
|
||||
CFxRange mOrigin2Z;
|
||||
|
||||
CFxRange mRadius; // spawn on sphere/ellipse/disk stuff.
|
||||
CFxRange mHeight;
|
||||
CFxRange mWindModifier;
|
||||
|
||||
CFxRange mRotation;
|
||||
CFxRange mRotationDelta;
|
||||
|
||||
CFxRange mAngle1;
|
||||
CFxRange mAngle2;
|
||||
CFxRange mAngle3;
|
||||
|
||||
CFxRange mAngle1Delta;
|
||||
CFxRange mAngle2Delta;
|
||||
CFxRange mAngle3Delta;
|
||||
|
||||
CFxRange mVelX;
|
||||
CFxRange mVelY;
|
||||
CFxRange mVelZ;
|
||||
|
||||
CFxRange mAccelX;
|
||||
CFxRange mAccelY;
|
||||
CFxRange mAccelZ;
|
||||
|
||||
CFxRange mGravity;
|
||||
|
||||
CFxRange mDensity;
|
||||
CFxRange mVariance;
|
||||
|
||||
CFxRange mRedStart;
|
||||
CFxRange mGreenStart;
|
||||
CFxRange mBlueStart;
|
||||
|
||||
CFxRange mRedEnd;
|
||||
CFxRange mGreenEnd;
|
||||
CFxRange mBlueEnd;
|
||||
|
||||
CFxRange mRGBParm;
|
||||
|
||||
CFxRange mAlphaStart;
|
||||
CFxRange mAlphaEnd;
|
||||
CFxRange mAlphaParm;
|
||||
|
||||
CFxRange mSizeStart;
|
||||
CFxRange mSizeEnd;
|
||||
CFxRange mSizeParm;
|
||||
|
||||
CFxRange mSize2Start;
|
||||
CFxRange mSize2End;
|
||||
CFxRange mSize2Parm;
|
||||
|
||||
CFxRange mLengthStart;
|
||||
CFxRange mLengthEnd;
|
||||
CFxRange mLengthParm;
|
||||
|
||||
CFxRange mTexCoordS;
|
||||
CFxRange mTexCoordT;
|
||||
|
||||
CFxRange mElasticity;
|
||||
|
||||
int mSoundRadius;
|
||||
int mSoundVolume;
|
||||
|
||||
// Lower level parsing utilities
|
||||
bool ParseVector( const char *val, vec3_t min, vec3_t max );
|
||||
bool ParseFloat( const char *val, float *min, float *max );
|
||||
bool ParseGroupFlags( const char *val, int *flags );
|
||||
|
||||
// Base key processing
|
||||
// Note that these all have their own parse functions in case it becomes important to do certain kinds
|
||||
// of validation specific to that type.
|
||||
bool ParseMin( const char *val );
|
||||
bool ParseMax( const char *val );
|
||||
bool ParseDelay( const char *val );
|
||||
bool ParseCount( const char *val );
|
||||
bool ParseLife( const char *val );
|
||||
bool ParseElasticity( const char *val );
|
||||
bool ParseFlags( const char *val );
|
||||
bool ParseSpawnFlags( const char *val );
|
||||
|
||||
bool ParseOrigin1( const char *val );
|
||||
bool ParseOrigin2( const char *val );
|
||||
bool ParseRadius( const char *val );
|
||||
bool ParseHeight( const char *val );
|
||||
bool ParseWindModifier( const char *val );
|
||||
bool ParseRotation( const char *val );
|
||||
bool ParseRotationDelta( const char *val );
|
||||
bool ParseAngle( const char *val );
|
||||
bool ParseAngleDelta( const char *val );
|
||||
bool ParseVelocity( const char *val );
|
||||
bool ParseAcceleration( const char *val );
|
||||
bool ParseGravity( const char *val );
|
||||
bool ParseDensity( const char *val );
|
||||
bool ParseVariance( const char *val );
|
||||
|
||||
// Group type processing
|
||||
bool ParseRGB( CGPGroup *grp );
|
||||
bool ParseAlpha( CGPGroup *grp );
|
||||
bool ParseSize( CGPGroup *grp );
|
||||
bool ParseSize2( CGPGroup *grp );
|
||||
bool ParseLength( CGPGroup *grp );
|
||||
|
||||
bool ParseModels( CGPValue *grp );
|
||||
bool ParseShaders( CGPValue *grp );
|
||||
bool ParseSounds( CGPValue *grp );
|
||||
|
||||
bool ParseImpactFxStrings( CGPValue *grp );
|
||||
bool ParseDeathFxStrings( CGPValue *grp );
|
||||
bool ParseEmitterFxStrings( CGPValue *grp );
|
||||
bool ParsePlayFxStrings( CGPValue *grp );
|
||||
|
||||
// Group keys
|
||||
bool ParseRGBStart( const char *val );
|
||||
bool ParseRGBEnd( const char *val );
|
||||
bool ParseRGBParm( const char *val );
|
||||
bool ParseRGBFlags( const char *val );
|
||||
|
||||
bool ParseAlphaStart( const char *val );
|
||||
bool ParseAlphaEnd( const char *val );
|
||||
bool ParseAlphaParm( const char *val );
|
||||
bool ParseAlphaFlags( const char *val );
|
||||
|
||||
bool ParseSizeStart( const char *val );
|
||||
bool ParseSizeEnd( const char *val );
|
||||
bool ParseSizeParm( const char *val );
|
||||
bool ParseSizeFlags( const char *val );
|
||||
|
||||
bool ParseSize2Start( const char *val );
|
||||
bool ParseSize2End( const char *val );
|
||||
bool ParseSize2Parm( const char *val );
|
||||
bool ParseSize2Flags( const char *val );
|
||||
|
||||
bool ParseLengthStart( const char *val );
|
||||
bool ParseLengthEnd( const char *val );
|
||||
bool ParseLengthParm( const char *val );
|
||||
bool ParseLengthFlags( const char *val );
|
||||
|
||||
bool ParseMaterialImpact(const char *val);
|
||||
|
||||
public:
|
||||
|
||||
CPrimitiveTemplate();
|
||||
~CPrimitiveTemplate() {};
|
||||
|
||||
bool ParsePrimitive( CGPGroup *grp );
|
||||
|
||||
void operator=(const CPrimitiveTemplate &that);
|
||||
};
|
||||
|
||||
// forward declaration
|
||||
struct SEffectTemplate;
|
||||
|
||||
// Effects are built of one or more primitives
|
||||
struct SEffectTemplate
|
||||
{
|
||||
bool mInUse;
|
||||
bool mCopy;
|
||||
char mEffectName[MAX_QPATH]; // is this extraneous??
|
||||
int mPrimitiveCount;
|
||||
int mRepeatDelay;
|
||||
CPrimitiveTemplate *mPrimitives[FX_MAX_EFFECT_COMPONENTS];
|
||||
|
||||
bool operator == (const char * name) const
|
||||
{
|
||||
return !stricmp( mEffectName, name );
|
||||
}
|
||||
void operator=(const SEffectTemplate &that);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
// CFxScheduler
|
||||
//
|
||||
// The scheduler not only handles requests to play an effect, it
|
||||
// tracks the request throughout its life if necessary, creating
|
||||
// any of the delayed components as needed.
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
class CFxScheduler
|
||||
{
|
||||
private:
|
||||
|
||||
// We hold a scheduled effect here
|
||||
struct SScheduledEffect
|
||||
{
|
||||
CPrimitiveTemplate *mpTemplate; // primitive template
|
||||
int mStartTime;
|
||||
char mModelNum; // uset to determine which ghoul2 model we want to bolt this effect to
|
||||
char mBoltNum; // used to determine which bolt on the ghoul2 model we should be attaching this effect to
|
||||
short mEntNum; // used to determine which entity this ghoul model is attached to.
|
||||
bool mPortalEffect; // rww - render this before skyportals, and not in the normal world view.
|
||||
bool mIsRelative; // bolt this puppy on keep it updated
|
||||
int iGhoul2;
|
||||
vec3_t mOrigin;
|
||||
vec3_t mAxis[3];
|
||||
|
||||
bool operator <= (const int time) const
|
||||
{
|
||||
return mStartTime <= time;
|
||||
}
|
||||
};
|
||||
|
||||
/* Looped Effects get stored and reschedule at mRepeatRate */
|
||||
#define MAX_LOOPED_FX 32
|
||||
// We hold a looped effect here
|
||||
struct SLoopedEffect
|
||||
{
|
||||
int mId; // effect id
|
||||
int mBoltInfo; // used to determine which bolt on the ghoul2 model we should be attaching this effect to
|
||||
CGhoul2Info_v mGhoul2;
|
||||
int mNextTime; //time to render again
|
||||
int mLoopStopTime; //time to die
|
||||
bool mPortalEffect; // rww - render this before skyportals, and not in the normal world view.
|
||||
bool mIsRelative; // bolt this puppy on keep it updated
|
||||
};
|
||||
|
||||
SLoopedEffect mLoopedEffectArray[MAX_LOOPED_FX];
|
||||
|
||||
int ScheduleLoopedEffect( int id, int boltInfo, int iGhoul2, bool isPortal, int iLoopTime, bool isRelative );
|
||||
void AddLoopedEffects( );
|
||||
|
||||
|
||||
class CScheduled2DEffect
|
||||
{
|
||||
public:
|
||||
CScheduled2DEffect():
|
||||
mScreenX(0),
|
||||
mScreenY(0),
|
||||
mWidth(0),
|
||||
mHeight(0),
|
||||
mShaderHandle(0)
|
||||
{mColor[0]=mColor[1]=mColor[2]=mColor[3]=1.0f;}
|
||||
|
||||
public:
|
||||
float mScreenX;
|
||||
float mScreenY;
|
||||
float mWidth;
|
||||
float mHeight;
|
||||
vec4_t mColor; // bytes A, G, B, R -- see class paletteRGBA_c
|
||||
qhandle_t mShaderHandle;
|
||||
};
|
||||
|
||||
// this makes looking up the index based on the string name much easier
|
||||
typedef map<string, int> TEffectID;
|
||||
|
||||
typedef list<SScheduledEffect*> TScheduledEffect;
|
||||
|
||||
// Effects
|
||||
SEffectTemplate mEffectTemplates[FX_MAX_EFFECTS];
|
||||
TEffectID mEffectIDs; // if you only have the unique effect name, you'll have to use this to get the ID.
|
||||
|
||||
// 2D effects
|
||||
CScheduled2DEffect m2DEffects[FX_MAX_2DEFFECTS];
|
||||
int mNextFree2DEffect;
|
||||
|
||||
// List of scheduled effects that will need to be created at the correct time.
|
||||
TScheduledEffect mFxSchedule;
|
||||
|
||||
|
||||
// Private function prototypes
|
||||
SEffectTemplate *GetNewEffectTemplate( int *id, const char *file );
|
||||
|
||||
void AddPrimitiveToEffect( SEffectTemplate *fx, CPrimitiveTemplate *prim );
|
||||
int ParseEffect( const char *file, CGPGroup *base );
|
||||
|
||||
void CreateEffect( CPrimitiveTemplate *fx, const vec3_t origin, vec3_t axis[3], int lateTime, int fxParm = -1, int iGhoul2 = 0, int entNum = -1, int modelNum = -1, int boltNum = -1);
|
||||
void CreateEffect( CPrimitiveTemplate *fx, SScheduledEffect *schedFx );
|
||||
|
||||
public:
|
||||
|
||||
CFxScheduler();
|
||||
|
||||
int RegisterEffect( const char *file, bool bHasCorrectPath = false ); // handles pre-caching
|
||||
|
||||
// Nasty overloaded madness
|
||||
//rww - maybe this should be done differently.. it's more than a bit confusing.
|
||||
//Remind me when I don't have 50 files checked out.
|
||||
void PlayEffect( int id, vec3_t org, vec3_t fwd, int vol = -1, int rad = -1, bool isPortal = false ); // builds arbitrary perp. right vector, does a cross product to define up
|
||||
void PlayEffect( int id, vec3_t origin, vec3_t axis[3], const int boltInfo=-1, int iGhoul2 = 0,
|
||||
int fxParm = -1, int vol = -1, int rad = -1, bool isPortal = false, int iLoopTime = false, bool isRelative = false );
|
||||
void PlayEffect( const char *file, vec3_t org, int vol = -1, int rad = -1 ); // uses a default up axis
|
||||
void PlayEffect( const char *file, vec3_t org, vec3_t fwd, int vol = -1, int rad = -1 ); // builds arbitrary perp. right vector, does a cross product to define up
|
||||
void PlayEffect( const char *file, vec3_t origin,
|
||||
vec3_t axis[3], const int boltInfo = -1, int iGhoul2 = 0, int fxParm = -1, int vol = -1, int rad = -1, int iLoopTime = false, bool isRelative = false );
|
||||
|
||||
void StopEffect( const char *file, const int boltInfo, bool isPortal = false ); //find a scheduled Looping effect with these parms and kill it
|
||||
void AddScheduledEffects( bool portal ); // call once per CGame frame
|
||||
|
||||
// kef -- called for a 2D effect instead of addRefToScene
|
||||
bool Add2DEffect(float x, float y, float w, float h, vec4_t color, qhandle_t shaderHandle);
|
||||
// kef -- called once per cgame frame AFTER cgi.RenderScene
|
||||
void Draw2DEffects(float screenXScale, float screenYScale);
|
||||
|
||||
int NumScheduledFx() { return mFxSchedule.size(); }
|
||||
void Clean(bool bRemoveTemplates = true, int idToPreserve = 0); // clean out the system
|
||||
|
||||
// FX Override functions
|
||||
SEffectTemplate *GetEffectCopy( int fxHandle, int *newHandle );
|
||||
SEffectTemplate *GetEffectCopy( const char *file, int *newHandle );
|
||||
|
||||
CPrimitiveTemplate *GetPrimitiveCopy( SEffectTemplate *effectCopy, const char *componentName );
|
||||
|
||||
void MaterialImpact(trace_t *tr, CEffect *effect);
|
||||
};
|
||||
|
||||
//-------------------
|
||||
// The one and only
|
||||
//-------------------
|
||||
extern CFxScheduler theFxScheduler;
|
||||
|
||||
#endif // FX_SCHEDULER_H_INC
|
||||
Reference in New Issue
Block a user