//----------------------------------------------------------------------------- // // $Logfile:: /Code/DLLs/game/FollowPath.h $ // $Revision:: 20 $ // $Author:: Steven $ // $Date:: 10/13/03 8:53a $ // // 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: // Provides base functionality for path following with avoidance // #ifndef __FOLLOW_PATH_H__ #define __FOLLOW_PATH_H__ #include "g_local.h" #include "entity.h" #include "path.h" #include "steering.h" class Actor; //------------------------- CLASS ------------------------------ // // Name: FollowNode // Base Class: Class // // Description: FollowNodes are a lightweight class meant to // store translation information for the FollowNodePath class // // Method of Use: FollowNodes should only be created by // FollowNodePaths but other classes my need access a node's // translation. // //-------------------------------------------------------------- class FollowNode : public Class { public: CLASS_PROTOTYPE( FollowNode ); FollowNode( void ); FollowNode( const Vector &position, const bool isTemporary=false, const bool isJumpNode=false, const float jumpAngle=45.0f ); Vector const & GetPosition( void ) const { return _position; } const bool GetIsTemporary( void ) const { return _isTemporary; } const bool GetIsJumpNode( void ) const { return _isJumpNode; } void SetIsJumpNode( const bool isJumpNode ) { _isJumpNode = isJumpNode; } const float GetJumpAngle( void ) const { return _jumpAngle; } void SetJumpAngle( const float jumpAngle ) { _jumpAngle = jumpAngle; } virtual void Archive( Archiver &arc ); private: Vector _position; bool _isTemporary; bool _isJumpNode; float _jumpAngle; }; inline void FollowNode::Archive( Archiver &arc ) { Class::Archive( arc ); arc.ArchiveVector( &_position ); arc.ArchiveBool( &_isTemporary ); arc.ArchiveBool( &_isJumpNode ); arc.ArchiveFloat( &_jumpAngle ); } typedef SafePtr FollowNodePtr; //------------------------- CLASS ------------------------------ // // Name: FollowNodePath // Base Class: Class // // Description: FollowNodePaths are simple paths that support the // concept of temporary path nodes (allowing temporary insertion // nodes into the path). // // Method of Use: FollowNodePaths should primarily be used by // FollowPath classes, although other classes may need access to // most of the members of the class // //-------------------------------------------------------------- enum PathCreationReturnCodes { PATH_CREATION_SUCCESS, PATH_CREATION_FAILED_DEGENERATE_PATH, PATH_CREATION_FAILED_NODES_NOT_CONNECTED, PATH_CREATION_FAILED_START_NODE_NOT_FOUND, PATH_CREATION_FAILED_END_NODE_NOT_FOUND, }; class FollowNodePath : public Class { public: CLASS_PROTOTYPE( FollowNodePath ); FollowNodePath(); ~FollowNodePath() { Clear(); } void AddNode(FollowNodePtr node) { _nodes.AddObject(node); } void RemoveNode(FollowNodePtr node); void InsertNode(FollowNodePtr node, const int index); FollowNodePtr GetPreviousNode(const FollowNodePtr node) const; FollowNodePtr GetNextNode(const FollowNodePtr node) const; const Steering::ReturnValue Evaluate( Actor &self, const Vector &goalPosition ); unsigned int const SetPath( Actor &self, const Vector &from, const Vector &to ); void Clear(); void Draw( void ) const; void SetCurrentNode(FollowNodePtr node) { _currentNode = node; } FollowNodePtr GetCurrentNode(void) const { return _currentNode; } int GetCurrentNodeIndex(void) const { return GetNodeIndex( GetCurrentNode() ); } FollowNodePtr GetNodeAt(const int index) const { return _nodes.ObjectAt(index); } int const GetNodeIndex(const FollowNodePtr node) const { return _nodes.IndexOfObject(node); } FollowNodePtr FirstNode(void) const { return _nodes.ObjectAt(1); } FollowNodePtr LastNode(void) const { return _nodes.ObjectAt(NumNodes()); } int const NumNodes(void) const { return _nodes.NumObjects(); } virtual void Archive( Archiver &arc ); private: void BuildFromPathNodes(Path *path, const Actor &self); const bool FindNewCurrentNode( const Actor &self ); const Steering::ReturnValue AdvanceCurrentNode( const Actor &self ); const Steering::ReturnValue RetreatCurrentNode( Actor &self, const Vector &goalPosition ); Container _nodes; FollowNodePtr _currentNode; }; inline void FollowNodePath::Archive( Archiver &arc ) { Class::Archive( arc ); int i; int num; FollowNode *followNode; if ( arc.Saving() ) { num = _nodes.NumObjects(); arc.ArchiveInteger( &num ); for( i = 1 ; i <= num ; i++ ) { followNode = _nodes.ObjectAt( i ); arc.ArchiveObject( followNode ); } } else { arc.ArchiveInteger( &num ); _nodes.ClearObjectList(); _nodes.Resize( num ); for( i = 1 ; i <= num ; i++ ) { followNode = new FollowNode; _nodes.AddObject( followNode ); arc.ArchiveObject( followNode ); } } arc.ArchiveSafePointer( &_currentNode ); } //------------------------- CLASS ------------------------------ // // Name: FollowPath // Base Class: Steering // // Description: FollowPath is the base class for and Steering // classes that need to navigate any significant distance through // the level. // // Method of Use: Never instantiate an object of type FollowPath. // If the TikiEngine architecture allowed, this cless would be an // interface class. If you need FollowPath behavior either use an // existing FollowPath subclass or derive a new class from a // FollowPath class. // //-------------------------------------------------------------- class FollowPath : public Steering { public: CLASS_PROTOTYPE( FollowPath ); FollowPath(); virtual ~FollowPath() { DeleteTemporaryPathNodes(); } virtual const Vector & GetGoalPosition(void) const { assert (false); return vec_zero; } virtual const float GetGoalRadius(void) const { assert (false); return 0.0f; } virtual FollowNodePath & GetPath(void) { return _path; } virtual const float GetRadius (void) const { return _radius; } virtual void SetRadius (const float radius) { _radius = radius; } virtual const float GetAvoidanceDistance (void) const { return _avoidanceDistance; } virtual void SetAvoidanceDistance (const float avoidanceDistance) { _avoidanceDistance = avoidanceDistance; } virtual void SetSteeringForceAndDesiredHeading( Actor &self, const Vector &steeringForce ); virtual void Begin( Actor &self ); virtual const ReturnValue Evaluate( Actor &self ); virtual void ShowInfo( Actor &self ); virtual void Archive( Archiver &arc ); protected: virtual void DeleteTemporaryPathNodes(void); virtual const bool ClearTraceToGoal( Actor &self, const trace_t &traceToGoal, const float radius ) const; virtual const bool DoneTurning( Actor &self ) const; virtual const ReturnValue GotoCurrentNode( Actor &self ); virtual const ReturnValue GotoGoal( Actor &self ); virtual const bool BuildAvoidancePath(Actor &self, const bool passOnTheLeft, const Vector &obstaclePosition, const float avoidanceRadius, const bool pursueGoal ); virtual const ReturnValue AvoidObstacle( Actor &self, const trace_t & trace, const bool pursueGoal=false ); virtual const bool TraceBlockedByEntity(Actor &self, const trace_t & trace ) const; virtual const bool CheckBlocked(Actor &self); virtual const ReturnValue ReturnBlockingObject(const trace_t &trace) const; virtual const bool AtDestination(Actor &self) const; virtual void SteerToCurrentNode(Actor &self); virtual void SteerToGoal( Actor &self ); virtual void FreePath( void ) { _path.Clear(); } virtual void AddPathNode(FollowNodePtr node) { GetPath().AddNode( node ); } virtual void InsertPathNode(FollowNodePtr node, const int index) { GetPath().InsertNode(node, index); SetCurrentNode(node); } virtual FollowNodePtr GetCurrentNode(void) const { return _path.GetCurrentNode(); } virtual void SetCurrentNode(FollowNodePtr node) { _path.SetCurrentNode(node); } private: float _radius; FollowNodePath _path; float _avoidanceDistance; Vector _desiredHeading; Jump _jump; qboolean _jumping; str _oldAnim; }; inline void FollowPath::Archive ( Archiver &arc ) { Steering::Archive( arc ); arc.ArchiveFloat( &_radius ); arc.ArchiveObject( &_path ); arc.ArchiveFloat( &_avoidanceDistance ); arc.ArchiveVector( &_desiredHeading ); arc.ArchiveObject( &_jump ); arc.ArchiveBoolean( &_jumping ); arc.ArchiveString( &_oldAnim ); } #endif // FollowPath