//-----------------------------------------------------------------------------
//
//  $Logfile:: /Quake 2 Engine/Sin/code/game/gravpath.h                       $
// $Revision:: 11                                                             $
//   $Author:: Jimdose                                                        $
//     $Date:: 10/25/98 11:53p                                                $
//
// 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.
//
// $Log:: /Quake 2 Engine/Sin/code/game/gravpath.h                            $
// 
// 11    10/25/98 11:53p Jimdose
// added EXPORT_TEMPLATE
// 
// 10    10/21/98 2:18a Jimdose
// Added Reset to Unarchive
// 
// 9     10/07/98 11:51p Jimdose
// Added destructor for GravPathManager
// added Reset to GravPath::Unarchive 
// 
// 8     9/30/98 4:36p Aldie
// Added reset
// 
// 7     9/29/98 11:46p Aldie
// Added force spawnflag
// 
// 6     9/28/98 9:12p Markd
// Put in archive and unarchive functions
// 
// 5     8/27/98 2:54p Aldie
// Added a headnode flag
// 
// 4     8/27/98 2:31p Aldie
// Update active flag as a public var
// 
// 3     8/26/98 9:45p Aldie
// Added activate and deactivate
// 
// 2     5/22/98 12:19p Aldie
// First version of gravpath
//
// DESCRIPTION:
// Gravity path - Used for underwater currents and wells.

#ifndef __GRAVPATH_H__
#define __GRAVPATH_H__

#include "g_local.h"
#include "class.h"
#include "container.h"


class GravPathNode : public Entity
   {
   private:
      float    speed;
      float    radius;
      qboolean headnode;
   
   public:
      qboolean       active; 

      CLASS_PROTOTYPE(GravPathNode);
                     GravPathNode();
      void           CreatePath(Event *ev); 
      void           Activate(Event *ev); 
      void           Deactivate(Event *ev); 
      float          Speed(void);
      float          Radius(void) {return radius;};
	   virtual void   Archive( Archiver &arc );
      virtual void   Unarchive( Archiver &arc );
   };

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

   arc.WriteFloat( speed );
   arc.WriteFloat( radius );
   arc.WriteBoolean( headnode );
   arc.WriteBoolean( active );
   }

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

   arc.ReadFloat( &speed );
   arc.ReadFloat( &radius );
   arc.ReadBoolean( &headnode );
   arc.ReadBoolean( &active );
   }

typedef SafePtr<GravPathNode> GravPathNodePtr;

//
// Exported templated classes must be explicitly instantiated
//
#ifdef EXPORT_TEMPLATE
template class SafePtr<GravPathNode>;
template class Container<GravPathNodePtr>;
#endif

class GravPath : public Listener
	{
	private:
		Container<GravPathNodePtr>	pathlist;
		float							   pathlength;
      
		GravPathNodePtr    	      from;
		GravPathNodePtr   		   to;
		int							   nextnode;
		
	public:
      CLASS_PROTOTYPE( GravPath );

						      GravPath();
                        ~GravPath();
		void			      Clear(void);
		void			      Reset(void);
		void			      AddNode(GravPathNode *node);
		GravPathNode      *GetNode(int num);
		GravPathNode      *NextNode(void);
		Vector		      ClosestPointOnPath(Vector pos, Entity &ent,float *bestdist,float *speed,float *radius);
		float			      DistanceAlongPath(Vector pos, float *speed);
		Vector		      PointAtDistance(float dist);
		void			      DrawPath(Event *ev);
		int			      NumNodes(void);
		float			      Length(void);
		GravPathNode		*Start(void);
		GravPathNode		*End(void);
	   virtual void      Archive( Archiver &arc );
      virtual void      Unarchive( Archiver &arc );

      Vector                     mins;
      Vector                     maxs;
      Vector                     origin;
      qboolean                   force;
	};

inline void GravPath::Archive
	(
	Archiver &arc
	)

   {
   int i, num;

   Listener::Archive( arc );

   num = pathlist.NumObjects();
   arc.WriteInteger( num );
   for ( i = 1; i <= num; i++ )
      {
      arc.WriteSafePointer( pathlist.ObjectAt( i ) );
      }

   arc.WriteFloat( pathlength );
   arc.WriteSafePointer( from );
   arc.WriteSafePointer( to );
   arc.WriteInteger( nextnode );
   arc.WriteVector( mins );
   arc.WriteVector( maxs );
   arc.WriteVector( origin );
   arc.WriteBoolean( force );
   }

inline void GravPath::Unarchive
	(
	Archiver &arc
	)

   {
   int i, num;

   Reset();

   Listener::Unarchive( arc );

   arc.ReadInteger( &num );
   pathlist.Resize( num );
   for ( i = 1; i <= num; i++ )
      {
      arc.ReadSafePointer( pathlist.AddressOfObjectAt( i ) );
      }

   arc.ReadFloat( &pathlength );
   arc.ReadSafePointer( &from );
   arc.ReadSafePointer( &to );
   arc.ReadInteger( &nextnode );
   arc.ReadVector( &mins );
   arc.ReadVector( &maxs );
   arc.ReadVector( &origin );
   arc.ReadBoolean( &force );
   }

#ifdef EXPORT_TEMPLATE
template class Container<GravPath *>;
#endif

class GravPathManager : public Class
   {
	private:
	   Container<GravPath *>	pathList;

	public:
      CLASS_PROTOTYPE( GravPathManager );
               ~GravPathManager();
      void     Reset( void );
      void     AddPath(GravPath *p);
      void     RemovePath(GravPath *p);
      Vector   CalculateGravityPull(Entity &ent, Vector position, qboolean *force);
	   virtual void Archive( Archiver &arc );
      virtual void Unarchive( Archiver &arc );
   };

inline void GravPathManager::Archive
	(
	Archiver &arc
	)
   {
   int i, num;

   Class::Archive( arc );

   num = pathList.NumObjects();
   arc.WriteInteger( num );
   for ( i = 1; i <= num; i++ )
      {
      arc.WriteObject( pathList.ObjectAt( i ) );
      }
   }

inline void GravPathManager::Unarchive
	(
	Archiver &arc
	)
   {
   int i, num;

   Reset();

   Class::Unarchive( arc );

   arc.ReadInteger( &num );
   for ( i = 1; i <= num; i++ )
      {
      GravPath * ptr;

      ptr = new GravPath;
      arc.ReadObject( ptr );
      pathList.AddObject( ptr );
      }
   }

extern GravPathManager gravPathManager;

extern Event EV_DrawGravPath;

#endif /* gravpath.h */
