//-----------------------------------------------------------------------------
//
//  $Logfile:: /Quake 2 Engine/Sin/code/game/steering.h                       $
// $Revision:: 7                                                              $
//   $Author:: Jimdose                                                        $
//     $Date:: 10/25/98 5:00a                                                 $
//
// Copyright (C) 1998 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// $Log:: /Quake 2 Engine/Sin/code/game/steering.h                            $
// 
// 7     10/25/98 5:00a Jimdose
// added archive functions to all steering classes
// 
// 6     10/19/98 11:45p Jimdose
// added FindCurrentNode to FollowPath
// 
// 5     10/18/98 3:22a Jimdose
// Simplified FollowPath
// 
// 4     9/22/98 5:12p Jimdose
// Added Turn
// Added wander code to chase
// 
// 3     9/22/98 1:56a Jimdose
// Added ShowInfo
// Added ObstacleAvoidance2 temporarily
// 
// 2     9/18/98 10:57p Jimdose
// Separated from Behavior.h
// 
// 1     9/18/98 5:01p Jimdose
//
// DESCRIPTION:
// Steering behaviors for AI.
// 

#ifndef __STEERING_H__
#define __STEERING_H__

#include "g_local.h"
#include "entity.h"
#include "path.h"

class Actor;

class Steering : public Listener
	{
	public:
		Vector					steeringforce;
		Vector					origin;
		Vector					movedir;
		float						maxspeed;

      CLASS_PROTOTYPE( Steering );

									Steering();

      virtual void         ShowInfo( Actor &self );
		virtual void			Begin( Actor &self );
		virtual qboolean		Evaluate( Actor &self );
		virtual void			End( Actor &self );

      void						ResetForces( void );
		void						SetPosition( Vector pos );
		void						SetDir( Vector dir );
		void						SetMaxSpeed( float speed );

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

inline void Steering::Archive
	(
	Archiver &arc
	)

   {
   Listener::Archive( arc );

   arc.WriteVector( steeringforce );
	arc.WriteVector( origin );
	arc.WriteVector( movedir );
	arc.WriteFloat( maxspeed );
   }

inline void Steering::Unarchive
	(
	Archiver &arc
	)

   {
   Listener::Unarchive( arc );

   arc.ReadVector( &steeringforce );
	arc.ReadVector( &origin );
	arc.ReadVector( &movedir );
	arc.ReadFloat( &maxspeed );
   }

class Seek : public Steering
	{
	protected:
		Vector					targetposition;
		Vector					targetvelocity;

	public:
      CLASS_PROTOTYPE( Seek );

									Seek();
		void						SetTargetPosition( Vector pos );
		void						SetTargetVelocity( Vector vel );
      void                 ShowInfo( Actor &self );
		qboolean					Evaluate( Actor &self );
	   virtual void         Archive( Archiver &arc );
      virtual void         Unarchive( Archiver &arc );
	};

inline void Seek::Archive
	(
	Archiver &arc
	)

   {
   Steering::Archive( arc );

   arc.WriteVector( targetposition );
	arc.WriteVector( targetvelocity );
   }

inline void Seek::Unarchive
	(
	Archiver &arc
	)

   {
   Steering::Unarchive( arc );

   arc.ReadVector( &targetposition );
	arc.ReadVector( &targetvelocity );
   }

class ObstacleAvoidance : public Steering
	{
	protected:
      qboolean             avoidwalls;

	public:
      CLASS_PROTOTYPE( ObstacleAvoidance );

                           ObstacleAvoidance();
      void                 AvoidWalls( qboolean );
      void                 ShowInfo( Actor &self );
		qboolean					Evaluate( Actor &self );
	   virtual void         Archive( Archiver &arc );
      virtual void         Unarchive( Archiver &arc );
	};

inline void ObstacleAvoidance::Archive
	(
	Archiver &arc
	)

   {
   Steering::Archive( arc );

	arc.WriteBoolean( avoidwalls );
   }

inline void ObstacleAvoidance::Unarchive
	(
	Archiver &arc
	)

   {
   Steering::Unarchive( arc );

   arc.ReadBoolean( &avoidwalls );
   }

class ObstacleAvoidance2 : public Steering
	{
	protected:
      qboolean             avoidwalls;

	public:
      CLASS_PROTOTYPE( ObstacleAvoidance2 );

                           ObstacleAvoidance2();
      void                 AvoidWalls( qboolean );
      void                 ShowInfo( Actor &self );
		qboolean					Evaluate( Actor &self );
	   virtual void         Archive( Archiver &arc );
      virtual void         Unarchive( Archiver &arc );
	};

inline void ObstacleAvoidance2::Archive
	(
	Archiver &arc
	)

   {
   Steering::Archive( arc );

	arc.WriteBoolean( avoidwalls );
   }

inline void ObstacleAvoidance2::Unarchive
	(
	Archiver &arc
	)

   {
   Steering::Unarchive( arc );

   arc.ReadBoolean( &avoidwalls );
   }

class FollowPath : public Steering
	{
	protected:
		PathPtr					path;
		Seek						seek;
      PathNodePtr          currentNode;

      void                 FindCurrentNode( Actor &self );

	public:
      CLASS_PROTOTYPE( FollowPath );
						
									FollowPath();
									~FollowPath();
		void						SetPath( Path *newpath );
		Path						*SetPath( Actor &self, Vector from, Vector to );
		qboolean					DoneWithPath( Actor &self );
      void                 ShowInfo( Actor &self );
		void						Begin( Actor &self );
		qboolean					Evaluate( Actor &self );
		void						End( Actor &self );
		virtual void			DrawForces( void );
	   virtual void         Archive( Archiver &arc );
      virtual void         Unarchive( Archiver &arc );
	};

inline void FollowPath::Archive
	(
	Archiver &arc
	)

   {
   Steering::Archive( arc );

   arc.WriteSafePointer( path );
   arc.WriteObject( &seek );
   arc.WriteSafePointer( currentNode );
   }

inline void FollowPath::Unarchive
	(
	Archiver &arc
	)

   {
   Steering::Unarchive( arc );

   arc.ReadSafePointer( &path );
   arc.ReadObject( &seek );
   arc.ReadSafePointer( &currentNode );
   }

class Turn : public Steering
	{
	private:
		Seek						seek;
		EntityPtr				ent;
		Vector					dir;
		float						yaw;
		int						mode;

	public:
      CLASS_PROTOTYPE( Turn );

									Turn();
		void						SetDirection( float yaw );
		void						SetTarget( Entity *ent );
      void                 ShowInfo( Actor &self );
		void						Begin( Actor &self );
		qboolean					Evaluate( Actor &self );
		void						End( Actor &self );
	   virtual void         Archive( Archiver &arc );
      virtual void         Unarchive( Archiver &arc );
	};

inline void Turn::Archive
	(
	Archiver &arc
	)

   {
   Steering::Archive( arc );

   arc.WriteObject( &seek );
   arc.WriteSafePointer( ent );
   arc.WriteVector( dir );
   arc.WriteFloat( yaw );
   arc.WriteInteger( mode );
   }

inline void Turn::Unarchive
	(
	Archiver &arc
	)

   {
   Steering::Unarchive( arc );

   arc.ReadObject( &seek );
   arc.ReadSafePointer( &ent );
   arc.ReadVector( &dir );
   arc.ReadFloat( &yaw );
   arc.ReadInteger( &mode );
   }

class Chase : public Steering
	{
	private:
		Seek						seek;
		FollowPath				follow;
		float						nextpathtime;
		PathPtr					path;
		Vector					goal;
		EntityPtr				goalent;
		PathNodePtr          goalnode;
      ObstacleAvoidance		avoid;
		float						avoidtime;
		qboolean					usegoal;
      float                newpathrate;

      Vector               wanderstart;
      int                  wander;
      float                wandertime;
      Turn                 turnto;
      str                  anim;
      int                  stuck;
      Vector               avoidvec;

	public:
      CLASS_PROTOTYPE( Chase );

									Chase();
		void						SetPath( Path *newpath );
		void						SetGoalPos( Vector pos );
		void						SetGoal( PathNode *node );
		void						SetTarget( Entity *ent );
      void                 SetPathRate( float rate );
      void                 ShowInfo( Actor &self );
      Vector               ChooseRandomDirection( Actor &self );
		void						Begin( Actor &self );
		qboolean					Evaluate( Actor &self );
		void						End( Actor &self );
	   virtual void         Archive( Archiver &arc );
      virtual void         Unarchive( Archiver &arc );
	};

inline void Chase::Archive
	(
	Archiver &arc
	)

   {
   Steering::Archive( arc );

   arc.WriteObject( &seek );
   arc.WriteObject( &follow );
   arc.WriteFloat( nextpathtime );
   arc.WriteSafePointer( path );
   arc.WriteVector( goal );
   arc.WriteSafePointer( goalent );
   arc.WriteSafePointer( goalnode );
   arc.WriteObject( &avoid );
   arc.WriteFloat( avoidtime );
   arc.WriteBoolean( usegoal );
   arc.WriteFloat( newpathrate );
   arc.WriteVector( wanderstart );
   arc.WriteInteger( wander );
   arc.WriteFloat( wandertime );
   arc.WriteObject( &turnto );
   arc.WriteString( anim );
   arc.WriteInteger( stuck );
   arc.WriteVector( avoidvec );
   }

inline void Chase::Unarchive
	(
	Archiver &arc
	)

   {
   Steering::Unarchive( arc );

   arc.ReadObject( &seek );
   arc.ReadObject( &follow );
   arc.ReadFloat( &nextpathtime );
   arc.ReadSafePointer( &path );
   arc.ReadVector( &goal );
   arc.ReadSafePointer( &goalent );
   arc.ReadSafePointer( &goalnode );
   arc.ReadObject( &avoid );
   arc.ReadFloat( &avoidtime );
   arc.ReadBoolean( &usegoal );
   arc.ReadFloat( &newpathrate );
   arc.ReadVector( &wanderstart );
   arc.ReadInteger( &wander );
   arc.ReadFloat( &wandertime );
   arc.ReadObject( &turnto );
   arc.ReadString( &anim );
   arc.ReadInteger( &stuck );
   arc.ReadVector( &avoidvec );
   }

#endif /* steering.h */
