//-----------------------------------------------------------------------------
//
//  $Logfile:: /game/surface.h                                                $
// $Revision:: 2                                                              $
//   $Author:: Burgermac                                                      $
//     $Date:: 12/27/00 7:03 PM                                               $
//
// Copyright (C) 1998 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:
// Controls surfaces
//

#ifndef __SURFACE_H__
#define __SURFACE_H__

#include "g_local.h"
#include "listener.h"
#include "archive.h"

extern Event EV_Surface_TransOn;
extern Event EV_Surface_TransOff;
extern Event EV_Surface_TransToggle;
extern Event EV_Surface_TransMag;
extern Event EV_Surface_Translucence;
extern Event EV_Surface_Magnitude;
extern Event EV_Surface_Frequency;
extern Event EV_Surface_TransAngle;
extern Event EV_Surface_DamageFrame;

class Surface : public Class
{
private:
	str surface_name;
	int surface_number;
	int damage;
	int state;
	int threshold;
	int numframes;
	int style;

public:
	CLASS_PROTOTYPE( Surface );
	const char*  SurfaceName()
	{
		return surface_name.c_str();
	}
	int         SurfaceNumber()
	{
		return surface_number;
	};
	int         Damage()
	{
		return damage;
	};
	int         State()
	{
		return state;
	};
	int         Threshold()
	{
		return threshold;
	};
	int         NumFrames()
	{
		return numframes;
	};
	int         LightStyle()
	{
		return style;
	};
	void        SetThreshold( int num )
	{
		threshold = num;
	};
	void        SetNumFrames( int num )
	{
		numframes = num;
	};
	void        SetLightStyle( int num )
	{
		style = num;
	};
	void        SetDamage( int num )
	{
		damage = num;
	};
	void        SetNumber( int num )
	{
		surface_number = num;
	};
	void        SetState( int num )
	{
		state = num;
	};
	void        SetName( const char* surf_name )
	{
		surface_name = surf_name;
	};
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );

};

inline void Surface::Archive( Archiver& arc )
{
	arc.WriteInteger( damage );
	arc.WriteInteger( state );
}

inline void Surface::Unarchive( Archiver& arc )
{
	damage = arc.ReadInteger();
	state = arc.ReadInteger();
}


class SurfaceModifier : public Listener
{
private:
	Container<Surface*> surfaceList;
	void     DoDamage( trace_t* trace, const char* group_name, float damage, Entity* attacker = world );

public:
	CLASS_PROTOTYPE( SurfaceModifier );

	~SurfaceModifier();
	void     CreateSurface( const char* surf_name, csurface_t* surfinfo );
	int      AddSurface( Surface* surf );
	void     RemoveSurface( const char* surf_name );
	int      SurfaceExists( const char* surf_name );
	Surface*  GetSurface( const char* surf_name );
	void     DamageSurface( trace_t* trace, float damage, Entity* attacker );
	void     Reset();

	void TranslationOn( Event* ev );
	void TranslationOff( Event* ev );
	void TranslationToggle( Event* ev );
	void SetTranslationMagnitude( Event* ev );
	void SetTranslationAngle( Event* ev );
	void SetTranslucence( Event* ev );
	void SetMagnitude( Event* ev );
	void SetFrequency( Event* ev );
	void SetDamageFrame( Event* ev );
	void SetDamage( Event* ev );
	virtual void Archive( Archiver& arc );
	virtual void Unarchive( Archiver& arc );
};

inline void SurfaceModifier::Archive( Archiver& arc )
{
	int i;
	Surface* surf;
	netsurface_t* s;
	int num;

	Listener::Archive( arc );

	num = surfaceList.NumObjects();
	arc.WriteInteger( num );
	for( i = 1; i <= num; i++ )
	{
		//
		// we only save out the dynamic fields
		//
		surf = surfaceList.ObjectAt( i );
		arc.WriteObject( surf );
	}

	// write the surface states
	s = g_surfaces;
	for( i = 0; i < game.maxsurfaces; i++, s++ )
	{
		arc.WriteBoolean( s->inuse );
		if( s->inuse )
		{
			arc.WriteRaw( &s->s, sizeof( s->s ) );
		}
	}
}

inline void SurfaceModifier::Unarchive( Archiver& arc )
{
	int i;
	Surface* surf;
	netsurface_t* s;
	int num;
	char* name;

	Listener::Unarchive( arc );

	// get the number
	num = arc.ReadInteger();
	for( i = 1; i <= num; i++ )
	{
		//
		// we only read in the dynamic fields
		//
		surf = surfaceList.ObjectAt( i );
		arc.ReadObject( surf );
	}

	// read the surface states
	s = g_surfaces;
	for( i = 0; i < game.maxsurfaces; i++, s++ )
	{
		s->inuse = arc.ReadBoolean();
		if( s->inuse )
		{
			name = s->s.name;
			arc.ReadRaw( &s->s, sizeof( s->s ) );
			s->s.name = name;
		}
	}
}

extern SurfaceModifier surfaceManager;

extern "C" void CreateSurfaces( csurface_t* surfaces, int count );

#endif /* surface.h */
