//------------------------------ RequestPathToItem -----------------------------
//
// Given an item type, this method determines the closest reachable graph node
// to the bot's position and then creates a instance of the time-sliced
// Dijkstra's algorithm, which it registers with the search manager
//
//-----------------------------------------------------------------------------
bool CActor_PathPlanner::RequestPathToItem( unsigned int ItemType )
{
  //clear the waypoint list and delete any active search
  GetReadyForNewSearch();

  //find the closest visible node to the bots position
  int ClosestNodeToBot = GetClosestNodeToPosition( m_pOwner->Pos() );

  //remove the destination node from the list and return false if no visible
  //node found. This will occur if the navgraph is badly designed or if the bot
  //has managed to get itself *inside* the geometry (surrounded by walls),
  //or an obstacle
  if ( ClosestNodeToBot == no_closest_node_found ) {
#ifdef SHOW_NAVINFO
    debug_con << "No closest node to bot found!" << "";
#endif

    return false;
  }

  //create an instance of the search algorithm
  typedef FindActiveTrigger < Trigger < CActorMapa > > t_con;
  typedef Graph_SearchDijkstras_TS < PlayModel::NavGraph, t_con > DijSearch;

  m_pCurrentSearch = new DijSearch( m_NavGraph,
                                    ClosestNodeToBot,
                                    ItemType );

  //register the search with the path manager
  m_pOwner->World()->GetPathManager()->Register( this );

  return true;
}
//---------------------------- GetCostToNode ----------------------------------
//
//  returns the cost to travel from the bot's current position to a specific 
 // graph node. This method makes use of the pre-calculated lookup table
//-----------------------------------------------------------------------------
double Raven_PathPlanner::GetCostToNode(unsigned int NodeIdx)const
{
  //find the closest visible node to the bots position
  int nd = GetClosestNodeToPosition(m_pOwner->Pos());

  //add the cost to this node
  double cost =Vec2DDistance(m_pOwner->Pos(),
                            m_NavGraph.GetNode(nd).Pos());

  //add the cost to the target node and return
  return cost + m_pOwner->GetWorld()->GetMap()->CalculateCostToTravelBetweenNodes(nd, NodeIdx);
}
//----------------------------- GetPath ------------------------------------
//
//  called by an agent after it has been notified that a search has terminated
//  successfully. The method extracts the path from m_pCurrentSearch, adds
//  additional edges appropriate to the search type and returns it as a list of
//  PathEdges.
//-----------------------------------------------------------------------------
CActor_PathPlanner::Path CActor_PathPlanner::GetPath()
{
  assert( m_pCurrentSearch && "<CActor_PathPlanner::GetPathAsNodes>: no current search" );

  Path path = m_pCurrentSearch->GetPathAsPathEdges();

  int closest = GetClosestNodeToPosition( m_pOwner->Pos() );

  path.push_front( PathEdge( m_pOwner->Pos(),
                             GetNodePosition( closest ),
                             NavGraphEdge::normal ) );

  //if the bot requested a path to a location then an edge leading to the
  //destination must be added
  if ( m_pCurrentSearch->GetType()
      == Graph_SearchTimeSliced < EdgeType >::AStar ) {

    int idx =
        m_pOwner->World()->GetCellSpace()->PositionToIndex( m_vDestinationPos );
    if ( invalid_node_index
        != m_pOwner->World()->GetNavGraph().GetNode( idx ).Index() ) {

      path.push_back( PathEdge( path.back().Destination(),
                                m_vDestinationPos,
                                NavGraphEdge::normal ) );
    }
  }

  //smooth paths if required
  if ( script->GetBool( "SmoothPathsQuick" ) ) {
    SmoothPathEdgesQuick( path );
  }

  if ( script->GetBool( "SmoothPathsPrecise" ) ) {
    SmoothPathEdgesPrecise( path );
  }

  return path;
}
//------------------------ GetCostToClosestItem ---------------------------
//
//  returns the cost to the closest instance of the giver type. This method
//  makes use of the pre-calculated lookup table. Returns -1 if no active
//  trigger found
//-----------------------------------------------------------------------------
double Raven_PathPlanner::GetCostToClosestItem(unsigned int GiverType)const
{
  //find the closest visible node to the bots position
  int nd = GetClosestNodeToPosition(m_pOwner->Pos());

  //if no closest node found return failure
  if (nd == invalid_node_index) return -1;

  double ClosestSoFar = MaxDouble;

  //iterate through all the triggers to find the closest *active* trigger of 
  //type GiverType
  const Raven_Map::TriggerSystem::TriggerList& triggers = m_pOwner->GetWorld()->GetMap()->GetTriggers();

  Raven_Map::TriggerSystem::TriggerList::const_iterator it;
  for (it = triggers.begin(); it != triggers.end(); ++it)
  {
    if ( ((*it)->EntityType() == GiverType) && (*it)->isActive())
    {
      double cost = 
      m_pOwner->GetWorld()->GetMap()->CalculateCostToTravelBetweenNodes(nd,
                                                      (*it)->GraphNodeIndex());

      if (cost < ClosestSoFar)
      {
        ClosestSoFar = cost;
      }
    }
  }

  //return a negative value if no active trigger of the type found
  if (isEqual(ClosestSoFar, MaxDouble))
  {
    return -1;
  }

  return ClosestSoFar;
}
//----------------------------- GetPath ------------------------------------
//
//  called by an agent after it has been notified that a search has terminated
//  successfully. The method extracts the path from m_pCurrentSearch, adds
//  additional edges appropriate to the search type and returns it as a list of
//  PathEdges.
//-----------------------------------------------------------------------------
Raven_PathPlanner::Path Raven_PathPlanner::GetPath()
{
  assert (m_pCurrentSearch && 
          "<Raven_PathPlanner::GetPathAsNodes>: no current search");

  Path path =  m_pCurrentSearch->GetPathAsPathEdges();

  int closest = GetClosestNodeToPosition(m_pOwner->Pos());

  path.push_front(PathEdge(m_pOwner->Pos(),
                            GetNodePosition(closest),
                            NavGraphEdge::normal));

  
  //if the bot requested a path to a location then an edge leading to the
  //destination must be added
  if (m_pCurrentSearch->GetType() == Graph_SearchTimeSliced<EdgeType>::AStar)
  {   
    path.push_back(PathEdge(path.back().Destination(),
                            m_vDestinationPos,
                            NavGraphEdge::normal));
  }

  //smooth paths if required
  if (UserOptions->m_bSmoothPathsQuick)
  {
    SmoothPathEdgesQuick(path);
  }

  if (UserOptions->m_bSmoothPathsPrecise)
  {
    SmoothPathEdgesPrecise(path);
  }

  return path;
}
//--------------------------- RequestPathToPosition ------------------------------
//
//  Given a target, this method first determines if nodes can be reached from
//  the  bot's current position and the target position. If either end point
//  is unreachable the method returns false.
//
//  If nodes are reachable from both positions then an instance of the time-
//  sliced A* search is created and registered with the search manager. the
//  method then returns true.
//
//-----------------------------------------------------------------------------
bool CActor_PathPlanner::RequestPathToPosition( Vector2D TargetPos )
{
#ifdef SHOW_NAVINFO
  debug_con << "------------------------------------------------" << "";
#endif
  GetReadyForNewSearch();

  //make a note of the target position.
  m_vDestinationPos = TargetPos;

  //find the closest visible node to the bots position
  int ClosestNodeToBot = GetClosestNodeToPosition( m_pOwner->Pos() );

  //remove the destination node from the list and return false if no visible
  //node found. This will occur if the navgraph is badly designed or if the bot
  //has managed to get itself *inside* the geometry (surrounded by walls),
  //or an obstacle.
  if ( ClosestNodeToBot == no_closest_node_found ) {
#ifdef SHOW_NAVINFO
    debug_con << "No closest node to bot found!" << "";
#endif

    return false;
  }

#ifdef SHOW_NAVINFO
  debug_con << "Closest node to bot is " << ClosestNodeToBot << "";
#endif

  //find the closest visible node to the target position
  int ClosestNodeToTarget = GetClosestNodeToPosition( TargetPos );

  //return false if there is a problem locating a visible node from the target.
  //This sort of thing occurs much more frequently than the above. For
  //example, if the user clicks inside an area bounded by walls or inside an
  //object.
  if ( ClosestNodeToTarget == no_closest_node_found ) {
#ifdef SHOW_NAVINFO
    debug_con << "No closest node to target (" << ClosestNodeToTarget << ") found!" << "";
#endif

    return false;
  }

#ifdef SHOW_NAVINFO
  debug_con << "Closest node to target is " << ClosestNodeToTarget << "";
#endif

  //create an instance of a the distributed A* search class
  typedef Graph_SearchAStar_TS < PlayModel::NavGraph, Heuristic_Euclid > AStar;

  m_pCurrentSearch =
      new AStar( m_NavGraph,
                 ClosestNodeToBot,
                 ClosestNodeToTarget,
                 static_cast < ModifierGoalBase* >( m_pOwner->GetModifierGoal() ) ); // NULL?
  //TODO Modificador objetivos...							static_cast < ModifierGoalBase* > ( m_pOwner->GetModifierGoal() ) );

  //and register the search with the path manager
  m_pOwner->World()->GetPathManager()->Register( this );

  return true;
}
//--------------------------- RequestPathToPosition ------------------------------
//
//  Given a target, this method first determines if nodes can be reached from 
//  the  bot's current position and the target position. If either end point
//  is unreachable the method returns false. 
//
//  If nodes are reachable from both positions then an instance of the time-
//  sliced A* search is created and registered with the search manager. the
//  method then returns true.
//        
//-----------------------------------------------------------------------------
bool Raven_PathPlanner::RequestPathToPosition(Vector2D TargetPos)
{ 
  #ifdef SHOW_NAVINFO
    debug_con << "------------------------------------------------" << "";
#endif
  GetReadyForNewSearch();

  //make a note of the target position.
  m_vDestinationPos = TargetPos;

  //if the target is walkable from the bot's position a path does not need to
  //be calculated, the bot can go straight to the position by ARRIVING at
  //the current waypoint
  if (m_pOwner->canWalkTo(TargetPos))
  { 
    return true;
  }
  
  //find the closest visible node to the bots position
  int ClosestNodeToBot = GetClosestNodeToPosition(m_pOwner->Pos());

  //remove the destination node from the list and return false if no visible
  //node found. This will occur if the navgraph is badly designed or if the bot
  //has managed to get itself *inside* the geometry (surrounded by walls),
  //or an obstacle.
  if (ClosestNodeToBot == no_closest_node_found)
  { 
#ifdef SHOW_NAVINFO
    debug_con << "No closest node to bot found!" << "";
#endif

    return false; 
  }

  #ifdef SHOW_NAVINFO
    debug_con << "Closest node to bot is " << ClosestNodeToBot << "";
#endif

  //find the closest visible node to the target position
  int ClosestNodeToTarget = GetClosestNodeToPosition(TargetPos);
  
  //return false if there is a problem locating a visible node from the target.
  //This sort of thing occurs much more frequently than the above. For
  //example, if the user clicks inside an area bounded by walls or inside an
  //object.
  if (ClosestNodeToTarget == no_closest_node_found)
  { 
#ifdef SHOW_NAVINFO
    debug_con << "No closest node to target (" << ClosestNodeToTarget << ") found!" << "";
#endif

    return false; 
  }

  #ifdef SHOW_NAVINFO
    debug_con << "Closest node to target is " << ClosestNodeToTarget << "";
#endif

  //create an instance of a the distributed A* search class
  typedef Graph_SearchAStar_TS<Raven_Map::NavGraph, Heuristic_Euclid> AStar;
   
  m_pCurrentSearch = new AStar(m_NavGraph,
                               ClosestNodeToBot,
                               ClosestNodeToTarget);

  //and register the search with the path manager
  m_pOwner->GetWorld()->GetPathManager()->Register(this);

  return true;
}
Beispiel #8
0
bool PathPlanner::CreatePathToPosition(vec2 TargetPos, std::list<vec2> &path) {
	//Flush any current nodes in the path
	path.clear();

	//Make a note of the target position
	vDestPos = TargetPos;

	//If the target is unobstructed from the bot's pos, a path does not need to
	//be calculated, and the bot can ARRIVE directly at the destination.
	//isPathObstructed is a method that takes a start position, a target position,
	//and an entity radius and determines if an agent of that size is able
	//to move unobstructed between the two positions. It is used here to determine
	//if the bot can move directly to the target location without the need
	//for planning a path.
	//mEnt->fRadius is broken, using hard value of 4.099 (from enemy npc radius)

	/*if (!isPathObstructed(pEnt->pos, vDestPos, 4.099)) {
		path.push_back(vDestPos);
		return true;
	}*/

	//Find the closest unobstructed node to the bot's position
	//GetClosestNodeToPosition is a method that queries the nav graph nodes (NO
	//NAV GRAPH ATM) nodes to determine the closest unobstructed node to the given
	//position vector. It is used here to find the closest unobstructed node
	//to the bot's current location.

	
	int ClosestNodeToBot = GetClosestNodeToPosition(pEnt->pos);

	//If no visible node found return failure.
	if (ClosestNodeToBot == no_closest_node_found) {
		return false;
	}

	//Find the closest visible unobstructed node to the target position
	int ClosestNodeToTarget = GetClosestNodeToPosition(vDestPos);
	if (ClosestNodeToTarget == no_closest_node_found) {
		return false;
	}

	//Create an instance of the A* search class to search for a path between
	//the closest node to the bot and the closest node to the target position.
	//This A* search will utilize the Euclidean straight heuristic
	
	AStar astar(*pWorldInfo, ClosestNodeToBot, ClosestNodeToTarget);
	path = astar.GetPathToTarget();

	//Convert to indices to vectors
	/*if (!pathIndices.empty()){
		for (std::list<int>::const_iterator nodeIndex = pathIndices.begin(), end = pathIndices.end(); nodeIndex != end; ++nodeIndex) {
			path.push_back(astar.INDEX_NODE_POINTERS[(*nodeIndex)]->vPos);
		}
		path.push_back(TargetPos);
	}
	else {
		return false;
	}*/

	path.push_back(vDestPos);
	
	return true;
}