Here's some of my old code from foxbot. If you want to see more you can download the source at foxbot.net
Code:
struct teleport_info_t {
int iEntranceWaypointIndex;
int iExitWaypointIndex;
int iFinalGoal;
edict_t *pEntrance;
edict_t *pExit;
edict_t *pOwner;
bool bIsUsed;
};
bool BotFindTeleportShortCut(bot_t *pBot)
{
// This bots team.
int team = UTIL_GetTeam(pBot->pEdict);
edict_t *pent = NULL;
bool bExists;
// List of friendly teleport owners to this bot.
std::list<teleport_info_t> teleportOwners;
std::list<teleport_info_t>::iterator iter;
teleport_info_t tempTPinfo;
// Don't do this if the bot has the flag.
if(pBot->bot_has_flag)
return false;
// Search for teleporters.
while ((pent = FIND_ENTITY_BY_CLASSNAME(pent, "building_teleporter")) && !FNullEnt(pent))
{
bExists = false;
// Look to see if there is already a teleport_info for this owner.
for (iter = teleportOwners.begin(); iter != teleportOwners.end(); ++iter)
{
// Already exists?
if ((*iter).pOwner == pent->v.euser1)
{
// It's already been made.
bExists = true;
// Fill in the appropriate slot
if(pent->v.iuser1 == W_FL_TFC_TELEPORTER_ENTRANCE)
{
iter->pEntrance = pent;
iter->iEntranceWaypointIndex = WaypointFindNearest(pent, 300, -1);
}
else if(pent->v.iuser1 == W_FL_TFC_TELEPORTER_EXIT)
{
iter->pExit = pent;
iter->iExitWaypointIndex = WaypointFindNearest(pent, 300, -1);
}
}
}
// Only if it wasn't found above.
if(!bExists)
{
// Set tp info to initial state
tempTPinfo.bIsUsed = false;
tempTPinfo.iEntranceWaypointIndex = tempTPinfo.iExitWaypointIndex = -1;
tempTPinfo.pEntrance = tempTPinfo.pExit = NULL;
// Make sure the owner is the proper team.
if (team != UTIL_GetTeam(pent->v.euser1))
continue;
// Fill in the appropriate slot
if(pent->v.iuser1 == W_FL_TFC_TELEPORTER_ENTRANCE)
{
tempTPinfo.pOwner = pent->v.euser1;
tempTPinfo.pEntrance = pent;
tempTPinfo.iEntranceWaypointIndex = WaypointFindNearest(pent, 500, -1);
}
else if(pent->v.iuser1 == W_FL_TFC_TELEPORTER_EXIT)
{
tempTPinfo.pOwner = pent->v.euser1;
tempTPinfo.pExit = pent;
tempTPinfo.iExitWaypointIndex = WaypointFindNearest(pent, 500, -1);
}
// Add this to the list of found teleporters.
teleportOwners.push_back(tempTPinfo);
}
}
// Tag all slots as used that have both entrance and exit
for (iter = teleportOwners.begin(); iter != teleportOwners.end(); )
{
if(iter->pEntrance && iter->pExit)
{
++iter;
continue;
}
else
iter = teleportOwners.erase(iter);
}
// We now have only valid teleporters.
float shortestDistance = 99999.0f;
teleport_info_t *bestTP = NULL;
float totalDistance;
for (iter = teleportOwners.begin(); iter != teleportOwners.end(); ++iter)
{
// Find the teleporter which results in the shortest path to goal.
totalDistance = WaypointDistanceFromTo(pBot->curr_waypoint_index, iter->iEntranceWaypointIndex, team)
+ WaypointDistanceFromTo(iter->iExitWaypointIndex, pBot->goto_wp, team);
if(totalDistance < shortestDistance)
{
shortestDistance = totalDistance;
bestTP = &(*iter);
}
}
// Got the best saving teleporter, now see if it saves us distance to our goal without taking it.
if(shortestDistance < WaypointDistanceFromTo(pBot->curr_waypoint_index, pBot->goto_wp, team))
{
// Copy this teleporters information into the bot struct.
bestTP->bIsUsed = true;
pBot->teleportInfo = *bestTP;
}
// Clear the remaining entries.
teleportOwners.clear();
if(pBot->teleportInfo.bIsUsed)
{
pBot->teleportInfo.iFinalGoal = pBot->goto_wp;
pBot->goto_wp = pBot->teleportInfo.iEntranceWaypointIndex;
return true;
}
return false;
}