//-----------------------------------------------------------------------------
//
//  $Logfile:: /game/specialfx.h                                              $
// $Revision:: 2                                                              $
//   $Author:: Burgermac                                                      $
//     $Date:: 12/27/00 6:41 PM                                               $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// DESCRIPTION:
// special effects
//

#ifndef __SPECIAL_FX_H__
#define __SPECIAL_FX_H__

#include "g_local.h"
#include "entity.h"
#include "trigger.h"
#include "light.h"
#include "scriptslave.h"

void SpawnBlastDamage( trace_t* trace, int damage, Entity* attacker );
void Particles( Vector org, Vector norm, int count, int lightstyle, int flags );
void SpawnBlood( Vector org, Vector vel, int damage );
void SpawnSparks( Vector org,   Vector norm, int count );
void BurnWall( Vector org, Vector end, int amount );
void SpawnRocketExplosion( Vector org );
void SpawnScaledExplosion( Vector org, float scale );
void SpawnTeleportEffect( Vector org, int lightstyle );
void SpawnBeam( Vector start, Vector end, int parent_entnum, int modelindex, float alpha, float life, int flags );

void SpawnTempDlight( Vector org, float r, float g, float b, float radius, float decay, float life );

void TempModel( Entity* parent, Vector origin, Vector angles, const char* modelname, int anim, float scale, float alpha, int flags, float life );

void TesselateModel( Entity* ent, int min_size, int max_size, Vector dir, float power, float percentage, int thickness, Vector origin, int type = TESS_DEFAULT_TYPE, int lightstyle = TESS_DEFAULT_LIGHTSTYLE );

void ChangeMusic( const char* current, const char* fallback, qboolean force );

void ChangeSoundtrack( const char* soundtrack );

class Bubble : public Entity
{
public:
	CLASS_PROTOTYPE( Bubble );

	virtual void Think( Event* ev );
	virtual void Touch( Event* ev );
	virtual void Setup( Vector pos );
};

class Beam : public Entity
{
private:
	Vector start;
	Vector end;

public:
	CLASS_PROTOTYPE( Beam );

	Beam();
	void            setBeam( Vector start, Vector end, int diameter, float r, float g, float b, float alpha, float lifespan );
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );
};

inline void Beam::Archive( Archiver& arc )
{
	Entity::Archive( arc );
	arc.WriteVector( start );
	arc.WriteVector( end );
}

inline void Beam::Unarchive( Archiver& arc )
{
	Entity::Unarchive( arc );
	arc.ReadVector( &start );
	arc.ReadVector( &end );
}

class Projectile : public Entity
{
protected:
	int owner;

public:
	CLASS_PROTOTYPE( Projectile );
	float fov;
	Projectile();
	virtual void Setup( Entity* owner, Vector pos, Vector dir );
	Entity* Owner( void ); //###
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );
};

inline void Projectile::Archive( Archiver& arc )
{
	Entity::Archive( arc );
	arc.WriteInteger( owner );
	arc.WriteFloat( fov );
}

inline void Projectile::Unarchive( Archiver& arc )
{
	Entity::Unarchive( arc );
	owner = arc.ReadInteger();
	fov = arc.ReadFloat();
}

class FireSprite : public Light
{
public:
	CLASS_PROTOTYPE( FireSprite );

	FireSprite();
	~FireSprite();
};

class FuncBeam : public ScriptSlave
{
protected:
	Entity*      end;
	float damage;
	float life;

public:
	CLASS_PROTOTYPE( FuncBeam );

	FuncBeam();
	void        Activate( Event* ev );
	void        Deactivate( Event* ev );
	void        SetDiameter( Event* ev );
	void        SetLightstyle( Event* ev );
	void        SetMaxoffset( Event* ev );
	void        SetMinoffset( Event* ev );
	void        SetColor( Event* ev );
	void        SetTarget( Event* ev );
	void        Shoot( Vector start, Vector end, int diameter );
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );
};

inline void FuncBeam::Archive( Archiver& arc )
{
	ScriptSlave::Archive( arc );
	arc.WriteObjectPointer( end );
	arc.WriteFloat( damage );
	arc.WriteFloat( life );
}

inline void FuncBeam::Unarchive( Archiver& arc )
{
	ScriptSlave::Unarchive( arc );
	arc.ReadObjectPointer( ( Class** )&end );
	damage = arc.ReadFloat();
	life = arc.ReadFloat();
}

class Sprite : public Trigger
{
public:
	CLASS_PROTOTYPE( Sprite );
	Sprite();

	void        Activate( Event* ev );
	void        Deactivate( Event* ev );
};

//
//### 2015 specialfx
//

void SpawnThrowerFlame( Vector org, Vector dest ); // for flamethrower
void SpawnThrowerFlameRow( Vector org, Vector dest, Vector org2, Vector dest2 ); // for flamethrower
void SpawnThrowerFlameHit( Vector org, Vector dir ); // for flamethrower
void SpawnFlame( Vector org, Vector dira, Vector dest, Vector dirb, int count, int style, int size ); // for misc flames
void SpawnHoverBoost( Vector org, int yaw ); // for hoverbike vertical booster
void SpawnNukeExplosion( Vector org,    int size, int lightstyle ); // for nuke
void SpawnBowExplosion( Vector org, int size ); // for plasma bow
void SizedParticles( Vector org, Vector norm, int count, int lightstyle, int flags, int size, int growrate ); // variable sized particles
void FullParticles( Vector org, Vector norm, int count, int lightstyle, int flags, int size, int growrate, int speed, int spread, Vector accel ); // fully controllable particles

class FireHurtField : public TriggerUse
{
protected:
	float damage;
	qboolean fireon;
	EntityPtr parentfire;

	void        Hurt( Event* ev );
	void        SetHurt( Event* ev );

public:
	CLASS_PROTOTYPE( FireHurtField );

	FireHurtField();
	void Setup( Vector minpos, Vector maxpos, int firedamage );
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );
};

inline void FireHurtField::Archive( Archiver& arc )
{
	TriggerUse::Archive( arc );

	arc.WriteFloat( damage );
	arc.WriteBoolean( fireon );
	arc.WriteSafePointer( parentfire );
}

inline void FireHurtField::Unarchive( Archiver& arc )
{
	TriggerUse::Unarchive( arc );

	damage = arc.ReadFloat();
	fireon = arc.ReadBoolean();
	arc.ReadSafePointer( &parentfire );
}

/*template class SafePtr<FireHurtField>;*/
typedef SafePtr<FireHurtField> FireHurtFieldPtr;

class FuncFire : public Entity
{
private:
	int flaming;
	int flamecount;
	Vector flameend;
	Vector flamevela;
	Vector flamevelb;
	float flamedelay;
	float flamerandom;
	int flametype;
	int flamesize;
	FireHurtFieldPtr hurtfield;
	int flamedamage;

public:
	CLASS_PROTOTYPE( FuncFire );

	FuncFire();
	virtual void Animate( Event* ev );
	virtual void ToggleFlame( Event* ev );

	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );
};

inline void FuncFire::Archive( Archiver& arc )
{
	Entity::Archive( arc );

	arc.WriteInteger( flaming );
	arc.WriteInteger( flamecount );
	arc.WriteVector( flameend );
	arc.WriteVector( flamevela );
	arc.WriteVector( flamevelb );
	arc.WriteFloat( flamedelay );
	arc.WriteFloat( flamerandom );
	arc.WriteInteger( flametype );
	arc.WriteInteger( flamesize );
	arc.WriteSafePointer( hurtfield );
	arc.WriteInteger( flamedamage );
}

inline void FuncFire::Unarchive( Archiver& arc )
{
	Entity::Unarchive( arc );

	flaming = arc.ReadInteger();
	flamecount = arc.ReadInteger();
	arc.ReadVector( &flameend );
	arc.ReadVector( &flamevela );
	arc.ReadVector( &flamevelb );
	flamedelay = arc.ReadFloat();
	flamerandom = arc.ReadFloat();
	flametype = arc.ReadInteger();
	flamesize = arc.ReadInteger();
	arc.ReadSafePointer( &hurtfield );
	flamedamage = arc.ReadInteger();
}

void SpawnCrawlerSpitDamage( trace_t* trace, int damage, Entity* attacker );

#endif /* specialfx.h */
