/**
* Transformation FX
* @version: 9-14-2002
* @author Joseph 'Pcjoe' Florencio
*/

#ifndef TRANSFORMFX_H
#define TRANSFORMFX_H

// Used for adding transform events
typedef enum fx_types
{
	ROTATE_LGHTING_SPHERE,
	PURPLE_LGHTING_SPHERE,
	PINK_SOLID_SPHERE,
	WHITE_SPHERE,
	HARD_INNDER_SPHERE,
	EXPLOSION_SPHERE,
	SHOCKWAVE_CORE,
	SHOCKWAVE_CORE_INVERSE,
	SHOCKWAVE_FROM_CORE,
	SHOCKWAVE_FROM_CORE_INVERSE,
	FLASHY_AURA,
	FLASHY_WHITE_AURA,
	LIGHTING,
	FLOATING_ROCKS,
	DUST,
	COLUMN_DUST,
	ROTATING_DUST,
	EXPANDED_DUST,
	STEAM,
	STEAM_HEAD,
	SPIRIT_BOMB,
	SWOOP_DUSTTRAIL,
	DUSTTRAIL,
	// Sounds
	SCREAM,
	SCREAM2,
	PSCREAM,
	NONE,
};

#define LOW_QUALITY_FX		1
#define MEDIUM_QUALITY_FX	2
#define HIGH_QUALITY_FX		3

struct trans_event
{
	int iFlag;			// type of particle fx
	int iIndex;			// Owner of event
	float flTimeStart;	// Time event starts
	float flTimeEnd;	// Time event ends
	char szSound[256];
	trans_event *pNext;	// Next event
};

struct trans_event_manager
{
	int iIndex;					// Owner of event
	float flTimeStart;			// Time total event starts
	float flDurration;			// How long the event is
	int iCharacter;				// Owners character
	trans_event *pEvents;		// Event list
	trans_event_manager *pNext;	// Next event manager
};

struct particle_fx
{
	// General Varibles
	vec3_t vecOrigin;	// Origin
	vec3_t vecOrigin2;	// Second origin if needed ( Lighting )
	vec3_t vecVelocity;	// Velocity
	vec3_t vecRotation;	// Rotation ( If its 3d )
	vec3_t vecRotation2;// Only use if needed...
	int iColor[4];		// Color - R, G, B, A
	int iSprite;		// Sprite
	int iFrame;			// Current frame
	float flRotationSpeed;	// Rotation Speed
	int iMaxFrames;		// Max amount of frames in the model
	float flEnergy;		// Current energy
	float flEnergyDelta;// Rate at which energy will be taken away
	float flSize;		// Current size
	float flSizeDelta;	// Rate at which the size will change
	float flSpeed;		// The speed of the partice
	float flWeight;		// How much affect the surrounding environment has on this object
	float flFrameTime;	// Time at which the frames were changed.
	float flFrameDelta;	// Frame delta for models
	// Particle Specific Varibles
	// Floating Rocks
	bool blCollision;	// If it hit the ground
	int iBounce;		// The amount of times it bounced
};

struct partsys_s
{
	particle_fx *pParticle;	// Particle list...
	vec3_t vecOrigin;		// Origin of particle system
	vec3_t vecForce;		// Outside vector forces
	int iMaxParticles;		// Max amount of particles
	int iMaxFrames;			// Max amount of frames
	float flFrameDelta;		// How fast the frames should go
	bool blvecOriginPlayer;	// If we should use the Origin of the player as the particle system origin
};

struct part_manager_s
{
	int m_iIndex;						// Index of player that owns this particle job
	int m_iFlag;						// Type of particle FX this job managing
	int m_iCharacter;					// Character the FX event is attached to. Used for coloring particle(s)
	float flTimeStart;					// Time total event starts
	float flTimeEnd;					// How long the event is
	float flDieTime;					// How long the particles have to disapear after death
	float flEmitDelta;					// How fast the next particle should come out
	float flEmitTime;					// Usines the EmitDelta to release particles
	bool blDisplay;						// Wether to display this or not...
	partsys_s *pPartSys;				// Particle system
	particle_fx *pParticle;				// Only used if its only one 3d element
	part_manager_s *pNext;				// Next job in the list
};


class CParticleFx
{
public:
	// Creating particle system
	void CreateParticleSystem( int iNumParticles, trans_event *pEvent );
	// Create a particle system with a preset vecorigin
	void CreateParticleSystem( int iNumParticles, vec3_t vecOrigin, trans_event *pEvent );
	// Create a colored particle system, using the character as a base
	void CreateParticleSystem( int iNumParticles, int iCharacter, trans_event *pEvent );
	// Kill particle system
	void KillSystem( float flDieTime, part_manager_s *pPartManager );
	part_manager_s *RemoveSystem( part_manager_s *pPartManager );
	part_manager_s *FindPrevJob( int iIndex, int iFlag, float flTimeStart );
	// Draw function...
	void Draw( float Time, float flTimeDifference );
	// Search and delete
	void SearchAndDelete( int iType, int iIndex );
	// Time
	float flTime;
	int iQuality;
private:
	/**
	* See if there is any collision at the vecOrigin.
	* @param vec3_t vecOrigin: Position to check for collision3
	* @param vec3_t vecDirection: Direction of the particle thats being checked
	* @param float flSize: Size of the area that will be checked for collisions
	* Return: The type of content the particle is touching( nothing/solid/water )
	*/
	int CollisionCheck( vec3_t vecOrigin, vec3_t vecDirection, float flSize );

	/**
	* Does a traceline Directly down to the floor.
	* @param vec3_t Origin: The origin of the particle that you want to be traced
	* @param bool &water: If the trace landed ontop of water
	* @param int direction: Trace Down(0), trace up(1)
	* @return vec3_t: The position after the traceline
	*/
	vec3_t ParticleTrace(vec3_t Origin, bool &blwater, int direction);

	void AnimateSprite( int iNum, part_manager_s *pPartManager );

	// Used for creation of particle system
	void InitializeSystem( int iNumParticles, part_manager_s *pPartManager );
	// Used for creation of a particle system with a predefined origin
	void InitializeSystem( int iNumParticles, vec3_t vecOrigin, part_manager_s *pPartManager );
	// Used to copy the info from a transformation event to a partile fx job
	part_manager_s *CopyInfo( trans_event *pEvent );
	// Commands that manage the particle system
	void Update( float flTime, float flTimeDifference, part_manager_s *pPartManager );
	void UpdateSpecific( float flTime, int iNum, float flTimeDifference, part_manager_s *pPartManager );
	// Main Emitter
	void Emit( part_manager_s *pPartManager );
	// Different Emitters for different particles
	void CreateRocks( int iNum, partsys_s *pPartSys, vec3_t vecOrigin );
	void CreateDust( int iNum, partsys_s *pPartSys, bool blWater, vec3_t vecOrigin, float flFarOut );
	void CreateIncommingDust( int iNum, partsys_s *pPartSys, bool blWater, vec3_t vecOrigin, float flFarOut );
	void ReCreateColumnDust( int iNum, partsys_s *pPartSys ); // Recreates Incomming Dust to upward moving dust
	void CreateColumnDust( int iNum, partsys_s *pPartSys, bool blWater, vec3_t vecOrigin );
	void CreateRotatingDust( int iNum, int iParticlesEmitted, int iMaxParticlesEmitted, partsys_s *pPartSys, bool blWater, vec3_t vecOrigin );
	void CreateSteam( partsys_s *pPartSys, int iNum, float flTimeStart, float flTimeEnd );
	void CreateSteamHead(int iNum, partsys_s *pPartSys, bool blSwitchSides, bool blHead, int iIndex, float flTimeStart, float flTimeEnd );
	void CreateLighting( int iNum, partsys_s *pPartSys, bool blWater, vec3_t vecOrigin );
	void CreateSB_Charger( int iNum, partsys_s *pPartSys );
	void CreateSwoopDustTrail( int iNum, partsys_s *pPartSys, bool blWater, vec3_t vecOrigin, int iIndex );
	void CreateSwoopCone( int iNum, partsys_s *pPartSys, bool blWater, vec3_t vecOrigin, int iIndex );
};

#endif
