// 02/08/02 November235: Particle System #pragma once class ParticleType; class ParticleSystem; #define COLLISION_NONE 0 #define COLLISION_DIE 1 #define COLLISION_BOUNCE 2 struct particle { particle* nextpart; particle* m_pOverlay; // for making multi-layered particles ParticleType *pType; vec3_t origin; vec3_t velocity; vec3_t accel; vec3_t m_vecWind; int m_iEntIndex; // if non-zero, this particle is tied to the given entity float m_fRed; float m_fGreen; float m_fBlue; float m_fRedStep; float m_fGreenStep; float m_fBlueStep; float m_fAlpha; float m_fAlphaStep; float frame; float m_fFrameStep; float m_fAngle; float m_fAngleStep; float m_fSize; float m_fSizeStep; float m_fDrag; float age; float age_death; float age_spray; }; class RandomRange { public: RandomRange() { m_fMin = m_fMax = 0; m_bDefined = false; } RandomRange(float fValue) { m_fMin = m_fMax = fValue; m_bDefined = true; } RandomRange(float fMin, float fMax) { m_fMin = fMin; m_fMax = fMax; m_bDefined = true; } RandomRange( char *szToken ); float m_fMax; float m_fMin; bool m_bDefined; float GetInstance() { return gEngfuncs.pfnRandomFloat(m_fMin, m_fMax); } float GetOffset(float fBasis) { return GetInstance()-fBasis; } bool IsDefined() { return m_bDefined; } //(m_fMin == 0 && m_fMax == 0); } }; #define MAX_TYPENAME 30 class ParticleType { public: ParticleType( ParticleType *pNext = NULL ); ParticleType(char *szFilename); bool m_bIsDefined; // is this ParticleType just a placeholder? int m_iRenderMode; int m_iDrawCond; // int m_iCollision; RandomRange m_Bounce; RandomRange m_BounceFriction; bool m_bBouncing; RandomRange m_Life; RandomRange m_StartAlpha; RandomRange m_EndAlpha; RandomRange m_StartRed; RandomRange m_EndRed; RandomRange m_StartGreen; RandomRange m_EndGreen; RandomRange m_StartBlue; RandomRange m_EndBlue; RandomRange m_StartSize; RandomRange m_SizeDelta; RandomRange m_EndSize; RandomRange m_StartFrame; RandomRange m_EndFrame; RandomRange m_FrameRate; // incompatible with EndFrame bool m_bEndFrame; RandomRange m_StartAngle; RandomRange m_AngleDelta; RandomRange m_SprayRate; RandomRange m_SprayForce; RandomRange m_SprayPitch; RandomRange m_SprayYaw; ParticleType *m_pSprayType; RandomRange m_Gravity; RandomRange m_WindStrength; RandomRange m_WindYaw; HSPRITE m_hSprite; ParticleType *m_pOverlayType; RandomRange m_Drag; ParticleType *m_pNext; char m_szName[MAX_TYPENAME]; // here is a particle system. Add a (set of) particles according to this type, and initialise their values. particle* CreateParticle(ParticleSystem *pSys);//particle *pPart); // initialise this particle. Does not define velocity or age. void InitParticle(particle *pPart, ParticleSystem *pSys); }; class ParticleSystem { public: ParticleSystem( int entindex, char *szFilename );//int iParticles ); // ParticleSystem( int iParticles ); ~ParticleSystem( void ); void AllocateParticles( int iParticles ); void CalculateDistance(); // ParticleType *GetMainType() { return GetType(m_szMainType); } ParticleType *GetType( const char *szName ); ParticleType *AddPlaceholderType( const char *szName ); ParticleType *ParseType( char *&szFile ); cl_entity_t *GetEntity() { return gEngfuncs.GetEntityByIndex(m_iEntIndex); } static float c_fCosTable[360 + 90]; static bool c_bCosTableInit; // General functions bool UpdateSystem( float frametime, /*vec3_t &right, vec3_t &up,*/ int messagenum ); // If this function returns false, the manager deletes the system void DrawSystem();//vec3_t &right, vec3_t &up); particle *ActivateParticle(); // adds one of the free particles to the active list, and returns it for initialisation. //MUST CHECK WHETHER THIS RESULT IS NULL! static float CosLookup(int angle) { return angle < 0? c_fCosTable[angle+360]: c_fCosTable[angle]; } static float SinLookup(int angle) { return angle < -90? c_fCosTable[angle+450]: c_fCosTable[angle+90]; } // returns false if the particle has died bool UpdateParticle( particle *part, float frametime ); void DrawParticle( particle* part, vec3_t &right, vec3_t &up ); // Utility functions that have to be public // bool ParticleIsVisible( particle* part ); // Pointer to next system for linked list structure ParticleSystem* m_pNextSystem; particle* m_pActiveParticle; float m_fViewerDist; int m_iEntIndex; private: // the block of allocated particles particle* m_pAllParticles; // First particles in the linked list for the active particles and the dead particles // particle* m_pActiveParticle; particle* m_pFreeParticle; particle* m_pMainParticle; // the "source" particle. ParticleType *m_pFirstType; ParticleType *m_pMainType; //char m_szMainType[MAX_TYPENAME]; // name of the main particle type };