//-----------------------------------------------------------------------------
//
//  $Logfile:: /2015/behavior.h                                               $
// $Revision:: 1                                                              $
//   $Author:: Burgermac                                                      $
//     $Date:: 12/27/00 5:20 PM                                               $
//
// 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.
//
// DESCRIPTION:
// Standard class for creating AI behaviors
//

#ifndef __BEHAVIOR_H__
#define __BEHAVIOR_H__

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

extern Event EV_Behavior_Args;
extern Event EV_Behavior_AnimDone;

class Actor;

class Behavior : public Listener
{
protected:
	PathNodePtr movegoal;

public:
	CLASS_PROTOTYPE( Behavior );

	Behavior();

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

inline void Behavior::Archive( Archiver& arc )
{
	Listener::Archive( arc );

	arc.WriteSafePointer( movegoal );
}

inline void Behavior::Unarchive( Archiver& arc )
{
	Listener::Unarchive( arc );

	arc.ReadSafePointer( &movegoal );
}

typedef SafePtr<Behavior> BehaviorPtr;

class Idle : public Behavior
{
private:
	float nexttwitch;
	str anim;

public:
	CLASS_PROTOTYPE( Idle );

	void                        SetArgs( Event* ev );
	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 Idle::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteFloat( nexttwitch );
	arc.WriteString( anim );
}

inline void Idle::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	nexttwitch = arc.ReadFloat();
	arc.ReadString( &anim );
}

class Aim : public Behavior
{
private:
	Seek seek;
	EntityPtr target;

public:
	CLASS_PROTOTYPE( Aim );

	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 Aim::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &seek );
	arc.WriteSafePointer( target );
}

inline void Aim::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &seek );
	arc.ReadSafePointer( &target );
}

class FireOnSight : public Behavior
{
private:
	Chase chase;
	Aim aim;
	int mode;
	str anim;

public:
	CLASS_PROTOTYPE( FireOnSight );

	void                        SetArgs( Event* ev );
	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 FireOnSight::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &chase );
	arc.WriteObject( &aim );
	arc.WriteInteger( mode );
	arc.WriteString( anim );
}

inline void FireOnSight::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &chase );
	arc.ReadObject( &aim );
	mode = arc.ReadInteger();
	arc.ReadString( &anim );
}

class TurnTo : public Behavior
{
private:
	Seek seek;
	EntityPtr ent;
	Vector dir;
	float yaw;
	int mode;
	int tolerance; //### facing tolerance

public:
	CLASS_PROTOTYPE( TurnTo );

	TurnTo();
	void                        SetDirection( float yaw );
	void                        SetTarget( Entity* ent );
	void                        SetTolerance( float tol ); //###
	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 TurnTo::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

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

inline void TurnTo::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

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

class Jump : public Behavior
{
	friend class Jump2; //### for Splitter bug's jump

private:
	float endtime;
	float speed;
	str anim;
	int state;
	qboolean animdone;
	Vector goal;

public:
	CLASS_PROTOTYPE( Jump );

	Jump();
	void                        SetArgs( Event* ev );
	void                 ShowInfo( Actor& self );
	void                        Begin( Actor& self );
	qboolean                    Evaluate( Actor& self );
	void                        End( Actor& self );
	void                        AnimDone( Event* ev );
	virtual void         Archive( Archiver& arc );
	virtual void         Unarchive( Archiver& arc );
};

inline void Jump::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteFloat( endtime );
	arc.WriteFloat( speed );
	arc.WriteString( anim );
	arc.WriteInteger( state );
	arc.WriteBoolean( animdone );
	arc.WriteVector( goal );
}

inline void Jump::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	endtime = arc.ReadFloat();
	speed = arc.ReadFloat();
	arc.ReadString( &anim );
	state = arc.ReadInteger();
	animdone = arc.ReadBoolean();
	arc.ReadVector( &goal );
}


class GotoPathNode : public Behavior
{
private:
	TurnTo turnto;
	Chase chase;
	int state;
	qboolean usevec;
	float time;
	str anim;
	EntityPtr goalent;
	Vector goal;

public:
	CLASS_PROTOTYPE( GotoPathNode );

	GotoPathNode();
	void                        SetArgs( Event* ev );
	void                        SetGoal( PathNode* node );
	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 GotoPathNode::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &turnto );
	arc.WriteObject( &chase );
	arc.WriteInteger( state );
	arc.WriteBoolean( usevec );
	arc.WriteFloat( time );
	arc.WriteString( anim );
	arc.WriteSafePointer( goalent );
	arc.WriteVector( goal );
}

inline void GotoPathNode::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &turnto );
	arc.ReadObject( &chase );
	state = arc.ReadInteger();
	usevec = arc.ReadBoolean();
	time = arc.ReadFloat();
	arc.ReadString( &anim );
	arc.ReadSafePointer( &goalent );
	arc.ReadVector( &goal );
}

class Investigate : public Behavior
{
private:
	Chase chase;
	str anim;
	Vector goal;
	float curioustime;

	qboolean                    Done( Actor& self );

public:
	CLASS_PROTOTYPE( Investigate );

	void                        SetArgs( Event* ev );
	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 Investigate::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &chase );
	arc.WriteString( anim );
	arc.WriteVector( goal );
	arc.WriteFloat( curioustime );
}

inline void Investigate::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &chase );
	arc.ReadString( &anim );
	arc.ReadVector( &goal );
	curioustime = arc.ReadFloat();
}

class Flee : public Behavior
{
private:
	FollowPath follow;
	PathPtr path;
	ObstacleAvoidance avoid;
	float avoidtime;
	str anim;

public:
	CLASS_PROTOTYPE( Flee );

	void                        SetArgs( Event* ev );
	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 Flee::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &follow );
	arc.WriteSafePointer( path );
	arc.WriteObject( &avoid );
	arc.WriteFloat( avoidtime );
	arc.WriteString( anim );
}

inline void Flee::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &follow );
	arc.ReadSafePointer( &path );
	arc.ReadObject( &avoid );
	avoidtime = arc.ReadFloat();
	arc.ReadString( &anim );
}

class OpenDoor : public Behavior
{
private:
	float time;
	float endtime;
	qboolean usedir;
	Vector dir;

public:
	CLASS_PROTOTYPE( OpenDoor );

	OpenDoor();
	void                        SetArgs( Event* ev );
	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 OpenDoor::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteFloat( time );
	arc.WriteFloat( endtime );
	arc.WriteBoolean( usedir );
	arc.WriteVector( dir );
}

inline void OpenDoor::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	time = arc.ReadFloat();
	endtime = arc.ReadFloat();
	usedir = arc.ReadBoolean();
	arc.ReadVector( &dir );
}

class PlayAnim : public Behavior
{
private:
	str anim;

public:
	CLASS_PROTOTYPE( PlayAnim );

	void                        SetArgs( Event* ev );
	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 PlayAnim::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteString( anim );
}

inline void PlayAnim::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadString( &anim );
}

class FindCover : public Behavior
{
private:
	str anim;
	Chase chase;
	int state;
	float nextsearch;

public:
	CLASS_PROTOTYPE( FindCover );

	void                        SetArgs( Event* ev );
	PathNode*                   FindCoverNode( Actor& self );
	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 FindCover::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteString( anim );
	arc.WriteObject( &chase );
	arc.WriteInteger( state );
	arc.WriteFloat( nextsearch );
}

inline void FindCover::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadString( &anim );
	arc.ReadObject( &chase );
	state = arc.ReadInteger();
	nextsearch = arc.ReadFloat();
}

class FindFlee : public Behavior
{
private:
	str anim;
	Chase chase;
	int state;
	float nextsearch;

public:
	CLASS_PROTOTYPE( FindFlee );

	void                        SetArgs( Event* ev );
	PathNode*                   FindFleeNode( Actor& self );
	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 FindFlee::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteString( anim );
	arc.WriteObject( &chase );
	arc.WriteInteger( state );
	arc.WriteFloat( nextsearch );
}

inline void FindFlee::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadString( &anim );
	arc.ReadObject( &chase );
	state = arc.ReadInteger();
	nextsearch = arc.ReadFloat();
}

class FindEnemy : public Behavior
{
private:
	str anim;
	Chase chase;
	int state;
	float nextsearch;
	PathNodePtr lastSearchNode;
	Vector lastSearchPos;

public:
	CLASS_PROTOTYPE( FindEnemy );

	PathNode*                   FindClosestSightNode( Actor& self );
	void                        SetArgs( Event* ev );
	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 FindEnemy::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteString( anim );
	arc.WriteObject( &chase );
	arc.WriteInteger( state );
	arc.WriteFloat( nextsearch );
	arc.WriteSafePointer( lastSearchNode );
	arc.WriteVector( lastSearchPos );
}

inline void FindEnemy::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadString( &anim );
	arc.ReadObject( &chase );
	state = arc.ReadInteger();
	nextsearch = arc.ReadFloat();
	arc.ReadSafePointer( &lastSearchNode );
	arc.ReadVector( &lastSearchPos );
}

class Hide : public Behavior
{
private:
	FindCover hide;
	str anim;
	int state;
	float checktime;

public:
	CLASS_PROTOTYPE( Hide );

	void                        SetArgs( Event* ev );
	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 Hide::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &hide );
	arc.WriteString( anim );
	arc.WriteInteger( state );
	arc.WriteFloat( checktime );
}

inline void Hide::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &hide );
	arc.ReadString( &anim );
	state = arc.ReadInteger();
	checktime = arc.ReadFloat();
}


class FleeAndRemove : public Behavior
{
private:
	FindFlee flee;
	str anim;
	int state;
	float checktime;

public:
	CLASS_PROTOTYPE( FleeAndRemove );

	void                        SetArgs( Event* ev );
	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 FleeAndRemove::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &flee );
	arc.WriteString( anim );
	arc.WriteInteger( state );
	arc.WriteFloat( checktime );
}

inline void FleeAndRemove::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &flee );
	arc.ReadString( &anim );
	state = arc.ReadInteger();
	checktime = arc.ReadFloat();
}


class AimAndShoot : public Behavior
{
private:
	Aim aim;
	int mode;
	int maxshots;
	int numshots;
	qboolean animdone;
	float enemy_health;
	float aim_time;
	str animprefix;
	str readyfireanim;
	str aimanim;
	str fireanim;

public:
	CLASS_PROTOTYPE( AimAndShoot );

	AimAndShoot();
	void                        SetMaxShots( int num );
	void                        SetArgs( Event* ev );
	void                        AnimDone( Event* ev );
	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 AimAndShoot::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &aim );
	arc.WriteInteger( mode );
	arc.WriteInteger( maxshots );
	arc.WriteInteger( numshots );
	arc.WriteBoolean( animdone );
	arc.WriteFloat( enemy_health );
	arc.WriteFloat( aim_time );
	arc.WriteString( animprefix );
	arc.WriteString( readyfireanim );
	arc.WriteString( aimanim );
	arc.WriteString( fireanim );
}

inline void AimAndShoot::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &aim );
	mode = arc.ReadInteger();
	maxshots = arc.ReadInteger();
	numshots = arc.ReadInteger();
	animdone = arc.ReadBoolean();
	enemy_health = arc.ReadFloat();
	aim_time = arc.ReadFloat();
	arc.ReadString( &animprefix );
	arc.ReadString( &readyfireanim );
	arc.ReadString( &aimanim );
	arc.ReadString( &fireanim );
}

class AimAndMelee : public Behavior
{
private:
	Aim aim;
	int mode;
	int maxshots;
	int numshots;
	qboolean animdone;

public:
	CLASS_PROTOTYPE( AimAndMelee );

	AimAndMelee();
	void                        SetArgs( Event* ev );
	void                        AnimDone( Event* ev );
	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 AimAndMelee::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &aim );
	arc.WriteInteger( mode );
	arc.WriteInteger( maxshots );
	arc.WriteInteger( numshots );
	arc.WriteBoolean( animdone );
}

inline void AimAndMelee::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &aim );
	mode = arc.ReadInteger();
	maxshots = arc.ReadInteger();
	numshots = arc.ReadInteger();
	animdone = arc.ReadBoolean();
}


class Melee : public Behavior
{
private:
	int mode;
	qboolean animdone;

public:
	CLASS_PROTOTYPE( Melee );

	Melee();
	void                        SetArgs( Event* ev );
	void                        AnimDone( Event* ev );
	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 Melee::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteInteger( mode );
	arc.WriteBoolean( animdone );
}

inline void Melee::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	mode = arc.ReadInteger();
	animdone = arc.ReadBoolean();
}

class Repel : public Behavior
{
private:
	str anim;
	float dist;
	float len;
	float speed;
	Vector goal;
	Vector start;
	Vector dir;

public:
	CLASS_PROTOTYPE( Repel );

	void                        SetArgs( Event* ev );
	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 Repel::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteString( anim );
	arc.WriteFloat( dist );
	arc.WriteFloat( len );
	arc.WriteFloat( speed );
	arc.WriteVector( goal );
	arc.WriteVector( start );
	arc.WriteVector( dir );
}

inline void Repel::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadString( &anim );
	dist = arc.ReadFloat();
	len = arc.ReadFloat();
	speed = arc.ReadFloat();
	arc.ReadVector( &goal );
	arc.ReadVector( &start );
	arc.ReadVector( &dir );
}


class PickupAndThrow : public Behavior
{
private:
	Aim aim;
	int mode;
	qboolean animdone;
	EntityPtr pickup_target;


public:
	CLASS_PROTOTYPE( PickupAndThrow );

	PickupAndThrow();
	void                        SetArgs( Event* ev );
	void                        AnimDone( Event* ev );
	void                        Pickup( Event* ev );
	void                        Throw( Event* ev );
	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 PickupAndThrow::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &aim );
	arc.WriteInteger( mode );
	arc.WriteBoolean( animdone );
	arc.WriteSafePointer( pickup_target );
}

inline void PickupAndThrow::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &aim );
	mode = arc.ReadInteger();
	animdone = arc.ReadBoolean();
	arc.ReadSafePointer( &pickup_target );
}

class StrafeAttack : public Behavior
{
private:
	int state;
	TurnTo turn;

public:
	CLASS_PROTOTYPE( StrafeAttack );

	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 StrafeAttack::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteInteger( state );
	arc.WriteObject( &turn );
}

inline void StrafeAttack::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	state = arc.ReadInteger();
	arc.ReadObject( &turn );
}

class StrafeTo : public Behavior
{
private:
	Vector goal;
	Seek seek;
	int fail;

public:
	CLASS_PROTOTYPE( StrafeTo );

	void                 ShowInfo( Actor& self );
	void                        SetArgs( Event* ev );
	void                        Begin( Actor& self );
	qboolean                    Evaluate( Actor& self );
	void                        End( Actor& self );
	virtual void         Archive( Archiver& arc );
	virtual void         Unarchive( Archiver& arc );
};

inline void StrafeTo::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteVector( goal );
	arc.WriteObject( &seek );
	arc.WriteInteger( fail );
}

inline void StrafeTo::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadVector( &goal );
	arc.ReadObject( &seek );
	fail = arc.ReadInteger();
}

class Swim : public Behavior
{
private:
	Seek seek;
	ObstacleAvoidance2 avoid;
	str anim;
	float avoidtime;
	Vector avoidvec;

public:
	CLASS_PROTOTYPE( Swim );

	void                        SetArgs( Event* ev );
	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 Swim::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &seek );
	arc.WriteObject( &avoid );
	arc.WriteString( anim );
	arc.WriteFloat( avoidtime );
	arc.WriteVector( avoidvec );
}

inline void Swim::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &seek );
	arc.ReadObject( &avoid );
	arc.ReadString( &anim );
	avoidtime = arc.ReadFloat();
	arc.ReadVector( &avoidvec );
}

class SwimCloseAttack : public Behavior
{
private:
	Seek seek;
	ObstacleAvoidance2 avoid;
	qboolean avoiding;
	str anim;
	float avoidtime;
	Vector avoidvec;

public:
	CLASS_PROTOTYPE( SwimCloseAttack );

	void                        SetArgs( Event* ev );
	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 SwimCloseAttack::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &seek );
	arc.WriteObject( &avoid );
	arc.WriteBoolean( avoiding );
	arc.WriteString( anim );
	arc.WriteFloat( avoidtime );
	arc.WriteVector( avoidvec );
}

inline void SwimCloseAttack::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &seek );
	arc.ReadObject( &avoid );
	avoiding = arc.ReadBoolean();
	arc.ReadString( &anim );
	avoidtime = arc.ReadFloat();
	arc.ReadVector( &avoidvec );
}

class Fly : public Behavior
{
private:
	Seek seek;
	ObstacleAvoidance2 avoid;
	str anim;
	float avoidtime;
	Vector avoidvec;

public:
	CLASS_PROTOTYPE( Fly );

	void                        SetArgs( Event* ev );
	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 Fly::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &seek );
	arc.WriteObject( &avoid );
	arc.WriteString( anim );
	arc.WriteFloat( avoidtime );
	arc.WriteVector( avoidvec );
}

inline void Fly::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &seek );
	arc.ReadObject( &avoid );
	arc.ReadString( &anim );
	avoidtime = arc.ReadFloat();
	arc.ReadVector( &avoidvec );
}

class FlyCloseAttack : public Behavior
{
private:
	Seek seek;
	ObstacleAvoidance2 avoid;
	qboolean avoiding;
	str anim;
	float avoidtime;
	Vector avoidvec;

public:
	CLASS_PROTOTYPE( FlyCloseAttack );

	void                        SetArgs( Event* ev );
	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 FlyCloseAttack::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &seek );
	arc.WriteObject( &avoid );
	arc.WriteBoolean( avoiding );
	arc.WriteString( anim );
	arc.WriteFloat( avoidtime );
	arc.WriteVector( avoidvec );
}

inline void FlyCloseAttack::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &seek );
	arc.ReadObject( &avoid );
	avoiding = arc.ReadBoolean();
	arc.ReadString( &anim );
	avoidtime = arc.ReadFloat();
	arc.ReadVector( &avoidvec );
}

class Wander : public Behavior
{
private:
	Seek seek;
	ObstacleAvoidance2 avoid;
	str anim;
	float avoidtime;
	Vector avoidvec;

public:
	CLASS_PROTOTYPE( Wander );

	void                        SetArgs( Event* ev );
	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 Wander::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &seek );
	arc.WriteObject( &avoid );
	arc.WriteString( anim );
	arc.WriteFloat( avoidtime );
	arc.WriteVector( avoidvec );
}

inline void Wander::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &seek );
	arc.ReadObject( &avoid );
	arc.ReadString( &anim );
	avoidtime = arc.ReadFloat();
	arc.ReadVector( &avoidvec );
}


class WanderCloseAttack : public Behavior
{
private:
	Seek seek;
	ObstacleAvoidance2 avoid;
	qboolean avoiding;
	str anim;
	float avoidtime;
	Vector avoidvec;

public:
	CLASS_PROTOTYPE( WanderCloseAttack );

	void                        SetArgs( Event* ev );
	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 WanderCloseAttack::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &seek );
	arc.WriteObject( &avoid );
	arc.WriteBoolean( avoiding );
	arc.WriteString( anim );
	arc.WriteFloat( avoidtime );
	arc.WriteVector( avoidvec );
}

inline void WanderCloseAttack::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &seek );
	arc.ReadObject( &avoid );
	avoiding = arc.ReadBoolean();
	arc.ReadString( &anim );
	avoidtime = arc.ReadFloat();
	arc.ReadVector( &avoidvec );
}

class GetCloseToEnemy : public Behavior
{
private:
	float howclose;
	str anim;
	Chase chase;
	int state;
	float nextsearch;

public:
	CLASS_PROTOTYPE( GetCloseToEnemy );

	GetCloseToEnemy();
	void                        SetArgs( Event* ev );
	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 GetCloseToEnemy::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteFloat( howclose );
	arc.WriteString( anim );
	arc.WriteObject( &chase );
	arc.WriteInteger( state );
	arc.WriteFloat( nextsearch );
}

inline void GetCloseToEnemy::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	howclose = arc.ReadFloat();
	arc.ReadString( &anim );
	arc.ReadObject( &chase );
	state = arc.ReadInteger();
	nextsearch = arc.ReadFloat();
}

class PlayAnimSeekEnemy : public Behavior
{
private:
	Aim aim;
	int mode;
	qboolean animdone;
	str anim;
	str oldanim;

public:
	CLASS_PROTOTYPE( PlayAnimSeekEnemy );

	void                        SetArgs( Event* ev );
	void                        AnimDone( Event* ev );
	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 PlayAnimSeekEnemy::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteObject( &aim );
	arc.WriteInteger( mode );
	arc.WriteBoolean( animdone );
	arc.WriteString( anim );
	arc.WriteString( oldanim );
}

inline void PlayAnimSeekEnemy::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	arc.ReadObject( &aim );
	mode = arc.ReadInteger();
	animdone = arc.ReadBoolean();
	arc.ReadString( &anim );
	arc.ReadString( &oldanim );
}

//### 2015 added stuff
class GetCloseToObject : public Behavior
{
private:
	float howclose;
	str anim;
	Chase chase;
	int state;
	float nextsearch;
	EntityPtr targetobject;

public:
	CLASS_PROTOTYPE( GetCloseToObject );

	GetCloseToObject();
	void SetArgs( Event* ev );
	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 GetCloseToObject::Archive( Archiver& arc )
{
	Behavior::Archive( arc );

	arc.WriteFloat( howclose );
	arc.WriteString( anim );
	arc.WriteObject( &chase );
	arc.WriteInteger( state );
	arc.WriteFloat( nextsearch );
	arc.WriteSafePointer( targetobject );
}

inline void GetCloseToObject::Unarchive( Archiver& arc )
{
	Behavior::Unarchive( arc );

	howclose = arc.ReadFloat();
	arc.ReadString( &anim );
	arc.ReadObject( &chase );
	state = arc.ReadInteger();
	nextsearch = arc.ReadFloat();
	arc.ReadSafePointer( &targetobject );
}
//###

#endif /* behavior.h */
