View Single Post
Re: Understanding Waypointing
Old
  (#2)
Cheeseh
[rcbot]
 
Cheeseh's Avatar
 
Status: Offline
Posts: 361
Join Date: Dec 2003
Location: China
Default Re: Understanding Waypointing - 08-09-2008

It depends what part of the waypointing you need to know. e.g.
  • How waypoints are stored in the game
  • How waypoints are stored on a waypoint file
  • How waypoints are added/deleted from the waypoints array
  • How paths are generated for each waypoint
  • How to find the best waypoint path
  • How bots navigate between waypoints
  • How bots move towards its "current waypoint"

Or all of them I had a lot of trouble with waypoints when I started making bots up, I specifically had a hard time figuring out how a bot goes from one waypoint to another for some reason!

How waypoints are stored in the game

All waypoints are stored in a large array e.g. call it "waypoints".

Each waypoints has co-ordinates on the map (x,y,z) (Vector type).

They also have Flags. The flags are a bitmask of additional information that is useful for a bot to navigate properly (Or if it is a special waypoint), for example a crouch waypoint, or a ladder waypoint, or a sniper waypoint. There are also special waypoints in HPB Bot called 'aiming' waypoints, useful for sniper waypoints and sentry waypoints to show the direction of a nearby waypoint. There is another special flag called DELETED that tells the bots that the waypoint in the array is invalid and can be overwritten by a new waypoint.

Each waypoint also has a list of other waypoints that can be reached from the current waypoint. This is used for path finding.

The waypoint code structure looks something like:

Code:
// Example values
#define FL_CROUCH 1
#define FL_LADDER 2
#define FL_AIMING 4
#define FL_SNIPER 8
#define FL_SENTRY 16
#define FL_DELETE 32

#define MAX_WAYPOINTS 1024

#define MAX_PATH 8

int num_waypoints = 0;

typedef struct
{
  Vector origin;
  int flags;
  int path[MAX_PATH]; // Waypoint paths
  short num_path; // number of waypoint paths
}waypoint_t;

waypoint_t waypoints[MAX_WAYPOINTS];

bool waypointHasFlag ( int Index, int Flag )
{
  return (waypoints[Index] & Flag) == Flag;
}
How waypoints are stored on a waypoint file

Waypoints are stored in a file in binary format. First a waypoint header is stored in the file.

Code:
typedef struct
{
   int waypoint_version;
   char map[64];
   char bot[32];
   int num_waypoints;
}waypoint_header;

bool loadwaypoints ( void )
{
  char filename[256];

  char mapname[64];
  char botname[32];

  strncpy(mapname,STRING(gpGlobals->mapname),63);
  mapname[63] = 0;

  strncpy(botname,"he@dsh0t's bot",31);
  botname[31] = 0;

  sprintf(filename,"%s.wpt",STRING(gpGlobals->mapname));

  FILE *bfp = fopen(filename,"rb");

  if ( !bfp )
    return false; // fail

  waypoint_header hdr;

  fread(bfp,&hdr,1,sizeof(waypoint_header));

  if ( hdr.waypoint_version != WAYPOINT_VERSION )
    return false; // wrong waypoint version

  if ( strcmp(hdr.map,mapname) )
   return false; /// wrong map

  if ( strcmp(hdr.bot,botname) )
   return false; // wrong bot

  num_waypoints = hdr.num_waypoints;

  for ( int i = 0; i < num_waypoints; i ++ )
    fread(bfp,&waypoints[i],1,sizeof(waypoint_t));

  fclose(bfp);

   return true; // okay
}

void savewaypoints ( void )
{
  waypoint_header hdr;

  hdr.waypoint_version = WAYPOINT_VERSION;
  strncpy(hdr.map,STRING(gpGlobals->mapname),63);
  hdr.map[63]=0;
  strncpy(hdr.bot,"he@dsh0t's bot",31); 
  hdr.bot[31]=0;
  hdr.num_waypoints = num_waypoints;

  char filename[256];
   
  sprintf(filename,"%s.wpt",STRING(gpGlobals->mapname));

  FILE *bfp = fopen("wb",filename);

  fwrite(bfp,&hdr,1,sizeof(waypoint_header));

  int i;

  for ( i = 0; i < MAX_WAYPOINTS; i ++ )
  {
    if ( !waypointHasFlag(i,FL_DELETED) )
       fwrite(bfp,&waypoints[i],sizeof(waypoint_t));
  }

  fclose(bfp);
}
When saving the header is simply setup with the correct values put in the waypoint_version, current map and your bot name, and the number of waypoints on the map. The header is simply written to the binary file first and then there is a loop that loops from 0 to num_waypoints.

When loading the waypoints the header is read first and the header is checked for its validity, if it is valid then all waypoints are read sequentially.

How waypoints are added/deleted from the waypoints array

Code:
void addWaypoint ( edict_t *pEdict, int flags )
{
   if ( pEdict->v.flags & FLAGS_CROUCH )
        flags |= FL_CROUCH;

   if ( pEdict->v.movetype = MOVETYPE_FLY )
       flags |= FL_LADDER;

   // find a waypoint

   for ( int i = 0; i < MAX_WAYPOINTS; i ++ )
  {
     if ( waypoints[i].flags & FL_DELETED )
     {
          waypoints[i].flags = flags;
          waypoints[i].origin = pEdict->v.origin;

          // Find nearby reachable waypoints!!
          findPathsForWaypoint(i);

          num_waypoints++; // one new waypoint
          break;
     } 
  }
}

void deleteWaypoint ( int index )
{
   waypoints[i].flags |= FL_DELETED;
}
I'll write more later, please ask which area you need help with
  
Reply With Quote