/*****************************************************************************
 * $Id: eng_pilot.hh,v 1.1 2006/10/31 04:16:55 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	Pilot, Animation, ChasePlane classes (closely associated with Dyna class).
 * @verbatim
 * ----------------------------------------------------------------------------
 * Relation of Animate() methods:
 *
 * The Engine's timer routine broadcasts an Animate event on the presumption
 * that a listening module will call the Animate() methods of Dyna objects.
 * Animate() methods return true if a redisplay event should be posted to the gfxsys.
 * Both Dyna and Pilot classes have Animate() methods.
 * The Dyna class contains a Pilot object.
 * Dyna::Animate() defers to Pilot::Animate().
 * All Animate() methods share a common set of eAnimate enums.
 * Animate() methods can be chained/hooked either in the Dyna or Pilot class descent.
 * ----------------------------------------------------------------------------
 * @endverbatim
 *//*
 * LEGAL:	COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#ifndef ENG_PILOT_HH
#define ENG_PILOT_HH 1

#include "eng_object.hh"

class Dyna;

////////////////////////////////////////////////////////////////////////////////
/// Animation enums.
/// NOTE: All Animate() methods must define different enums (no overlapping enums).
#undef  eAnimation
#define eAnimation int
enum //eAnimation
{
	eAnimation_NONE,
	eAnimation_AUTO_TRANSLATE, eAnimation_DEFAULT = eAnimation_AUTO_TRANSLATE,
    eAnimation_AUTO_ROTATE,
	eAnimation_CHASE_PLANE,

	// Range reserved for different kinds of collisions
	// (hard crash, minor crash shot-down, skid, spin, etc).
	eAnimation_COLLISION_RANGE_START,
		eAnimation_COLLISION_CRASH_HARD,	// movement stops
		eAnimation_COLLISION_CRASH_SOFT,	// movement stops
		eAnimation_COLLISION_SHOTDOWN_HARD,	// downward movement, destroyed
		eAnimation_COLLISION_SHOTDOWN_SOFT,	// downward movement, damaged but not destroyed
		//eAnimation_COLLISION_SKID,		// broken landing gear
		//eAnimation_COLLISION_TUMBLE,		// wings stalled during takeoff
	eAnimation_COLLISION_RANGE_END = eAnimation_COLLISION_RANGE_START + 20,

	// Other modules should start their enums from this.
	eAnimation_AFTER_DYNA_ENUMS
};

////////////////////////////////////////////////////////////////////////////////
/// Multiple animation states.
/// Think of this as a variable with multiple values.
///
class Animation
{
public:
				Animation( void ) { }
				~Animation() { }

	// Multivar interface (its methods aren't virtual to keep it fast/simple):
	void		Clear( void );
	void		Remove( const eAnimation animation );
	void		Set( const eAnimation animation );
	void		Add( const eAnimation animation );
	void		Toggle( const eAnimation animation );
	bool		Query( const eAnimation animation ) const;

	// Animation interface:
    bool		IfNone( void ) const;
    bool		IfCollision( void ) const;
    static bool IfCollision( const eAnimation animation );

private:
	Multivar	mMultivar;
};

/// Stub.
class ChasePlane
{
PREVENT_COPYING(ChasePlane)
public:
	explicit		ChasePlane( const Dyna& dyna ) : mOwner(dyna) { }
	virtual			~ChasePlane() { }
	virtual void	Reset( void ) { }
	virtual int		Chase( void ) { return false; }
	virtual void	IncRotate( uint axis, int dir ) { }
	virtual void	IncDistance( int dir ) { }
	virtual void	SetDistance( fp dist ) { }
	virtual fp		GetDistance( void ) { return 0.0; }

protected:
    const Dyna&     mOwner;  // the Dyna object that the chase-plane chases.
};

/// Base Pilot class.  All but Pilot::Animate() are stubs.
class Pilot
{
PREVENT_COPYING(Pilot)
public:
	explicit		Pilot( Dyna& owner );
	virtual			~Pilot() { }
    virtual void    Reset( void );

	virtual int		Animate( void );
	virtual	void	ClearAnimation( void ) { mAnimation.Clear(); }
	virtual	void	RemoveAnimation( const eAnimation animation ) { mAnimation.Remove( animation ); }
	virtual void	SetAnimation( const eAnimation animation )    { mAnimation.Set( animation ); }
	virtual void	AddAnimation( const eAnimation animation )    { mAnimation.Add( animation ); }
	virtual void	ToggleAnimation( const eAnimation animation ) { mAnimation.Toggle( animation ); }
	virtual bool	QueryAnimation( const eAnimation animation ) const { return mAnimation.Query( animation ); }

    void            SetAutoRotate( const uint axis, const int dir );
	virtual	void	SetTarget( Dyna& target ) { }
	virtual void	SelectTarget( void ) { }
	virtual bool	IfProbing( void ) { return false; }
    bool            IfDestroyed( void ) const { return mAnimation.IfCollision(); }

protected:  Dyna&		mOwner;
private:    Animation   mAnimation;
protected:  uint        mAutoRotateAxis;
protected:  int         mAutoRotateDir;
};

#endif // ENG_PILOT_HH
