Paths are required to allow bots to know what other waypoints are reachable from a selected waypoint.
for example, one waypoint will have a list of waypoint indexes to all other waypoints it can go to.
waypoint index,
0 : 1
1 : 2 // this waypoint goes to 2
2 : 3,4 // this waypoint goes to either 3 or 4
3 : 1 // this waypoint goes back to 1
4 : 1
paths can usually be symmetric i.e. if a waypoint is reachable in one direction then it is reachable in the other. But this may not be the case in some situations such as a waypoint on the top of a ledge and a waypoint on the ground. The waypoint on the ledge will have a path to the waypoint on the ground, but the waypoint on the ground should not have a path to the waypoint on the ledge,
unless the waypoint has a special type (e.g. FL_FLY) and the mod allows players to fly!
How paths are generated for each waypoint
Paths are generated by looping through each waypoint in the "waypoints" array and using things called tracelines that trace a line, funnily enough
, from one waypoint to another to determine if it is visible.
Code:
#define REACHABLE_RANGE 500 // 500 units away
void findPathsForWaypoint ( int index )
{
short paths = 0; // paths found so far for this waypoint
traceResult tr;
for ( i = 0; i < MAX_WAYPOINTS; i ++ )
{
if ( i == index )
continue; // skip the waypoint we are already looking at!!!
if ( waypoints[i].flags & FL_DELETED )
continue; // invalid waypoint!
if ( (waypoints[index].origin - waypoints[i].origin).Length() < REACHABLE_RANGE ) // waypoint within a small range
{
UTIL_TraceLine(&tr,waypoints[index].origin,waypoints[i].origin,...); // more parameters needed in here but u should get an example from somewhere
if ( tr.flFraction >= 1.0 )
{
// Visible
if ( paths < MAX_PATH )
{
waypoints[index].path[paths++] = i; // add this waypoint to a path
}
}
}
}
}
Similalry the pathwaypoint create1/remove1 and create2/remove2 commands will add/remove a path from one waypoint to another.
How bots move towards its "current waypoint"
The bot needs to find the
waypoint index in the waypoint array of the nearest waypoint first. The waypoint index is stored as its "current waypoint index". To do this it must loop through all waypoints in the waypoint array.
Code:
int findNearestWaypoint ( edict_t *pEdict )
{
int wptindex = -1; // -1 = invalid waypoint index!!!
int distance=REACHABLE_RANGE;
for ( int i = 0; i < MAX_WAYPOINTS; i ++ )
{
if ( waypoints[i].flags & FL_DELETED ) // invalid waypoint!
continue; // skip
// within range!?
if ( (waypoints[i].origin - pEdict->v.origin).Length() <= distance )
{
traceResult tr; // check if its visible (and not through a wall!!!)
UTIL_TraceLine(&tr,pEdict->v.origin,waypoints[i].origin,...); // more parameters needed in here but u should get an example from somewhere
if ( tr.flFraction >= 1.0 )
{
// Visible
wptindex = i; // new nearest waypoint!
}
}
}
}
Once the bot has a current waypoint, it must walk towards it
Code:
// find a waypoint
if ( pBot->current_waypoint_index == -1 )
pBot->current_waypoint_index = findNearestWaypoint(pBot->pEdict);
else // we've already got one!
walkTowardsWaypoint();
The bot must continuously check if it has reached the current waypoint.
To do this there is a function in HPBBot i think called BotNavigate(), this is called every frame.
It always checks if
Code:
#define WAYPOINT_TOUCH_DISTANCE 32
...
if ( (waypoints[pBot->current_waypoint_index].origin - pBot->pEdict->v.origin).Length() < WAYPOINT_TOUCH_DISTANCE )
{
pBot->current_waypoint_index = NextWaypointInPath(pBot);
}
else
{
//doNothing... or check if stuck
int wptflags = waypoints[pBot->current_waypoint_index].flags;
if ( wptflags & FL_CROUCH )
pBot->v.button |= IN_DUCK; /// crouch!! we are going towards a crouch waypoint !!
}
How to find the best waypoint path
The bot must find a path from one place to another , for xample, in TFC the bot might want to find a flag and return it to the base. To do this, in the HPB_BOT, there are special flags called
Code:
FL_CAPTURE_POINT
FL_FLAG
There is also a special function, something like this which searchs for a random waypoint with these properties.
Code:
#define MAX_RAND_ARRAY 8
int findRandomWaypointWithFlags ( int Flags )
{
int i;
int numwpt = 0;
int randomArray[MAX_RAND_ARRAY];
randomArray[0] = -1; // set as invalid just now
for ( i = 0 ; i < MAX_WAYPOINTS; i ++ )
{
if ( waypoints[i].flags & FL_DELETED)
continue; // skip
if ( waypoints[i].flags & Flags )
{
if ( numwpt < MAX_RAND_ARRAY )
randomArray[numwpt++] = i;
}
}
return randomArray[RANDOM_LONG(0,numwpt)];
}
When it finds a destination waypoint to go to by using this function, the bot should use a path finding algorithm to find a route from its current waypoint (nearest waypoint) to its goal.
See the wiki on path-finding
http://wiki.bots-united.com (username : wiki , password: nospam)
Using certain types of path finding algorithms can be intensive to CPU so usually a path is generated and the result of waypoint indexes the bot should go to in sequence is stored in the bot. Whenever the bot reaches its next waypoint, the bots new waypoint becomes the next waypoint in the path list.
retreating, cover waypoints, camping
The HPB Bots dont retreat. Some bots do, its a heavier subject. This requires extra information, such as a waypoint visibility table, which tells the bot which waypoints are visible from another. Just like the findRandomWaypointWithFlags function, we could loop though all waypoints again and see which one is not visible from a threat. and get the nearest one, then make that our goal, and run towards it for cover, when the bot reaches the goal, maybe it should crouch too!
Some bots have special camping
flags that tell the bot to crouch and wait for a while before moving off again.
hope it helps