int Export_BotLibLoadMap( const char *mapname ) { #ifdef DEBUG int starttime = Sys_MilliSeconds(); #endif int errnum; if ( !BotLibSetup( "BotLoadMap" ) ) { return BLERR_LIBRARYNOTSETUP; } // #if defined RTCW_ET // if the mapname is NULL, then this is a restart if ( !mapname ) { // START Arnout changes, 29-08-2002. // don't init the heap if no aas loaded, causes "SV_Bot_HunkAlloc: Alloc with marks already set" if ( ( *aasworld ).loaded ) { AAS_InitAASLinkHeap(); AAS_EnableAllAreas(); } // END Arnout changes, 29-08-2002. ( *aasworld ).numframes = 0; memset( ( *aasworld ).arealinkedentities, 0, ( *aasworld ).numareas * sizeof( aas_link_t * ) ); memset( ( *aasworld ).entities, 0, ( *aasworld ).maxentities * sizeof( aas_entity_t ) ); return BLERR_NOERROR; } // #endif // RTCW_XX botimport.Print( PRT_MESSAGE, "------------ Map Loading ------------\n" ); //startup AAS for the current map, model and sound index errnum = AAS_LoadMap( mapname ); if ( errnum != BLERR_NOERROR ) { return errnum; } //initialize the items in the level BotInitLevelItems(); //be_ai_goal.h BotSetBrushModelTypes(); //be_ai_move.h // botimport.Print( PRT_MESSAGE, "-------------------------------------\n" ); #ifdef DEBUG botimport.Print( PRT_MESSAGE, "map loaded in %d msec\n", Sys_MilliSeconds() - starttime ); #endif // return BLERR_NOERROR; } //end of the function Export_BotLibLoadMap
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int Export_BotLibLoadMap(const char *mapname) { #ifdef DEBUG int starttime = Sys_MilliSeconds(); #endif int errnum; if (!BotLibSetup("BotLoadMap")) return BLERR_LIBRARYNOTSETUP; // botimport.Print(PRT_MESSAGE, "------------ Map Loading ------------\n"); //startup AAS for the current map, model and sound index errnum = AAS_LoadMap(mapname); if (errnum != BLERR_NOERROR) return errnum; //initialize the items in the level BotInitLevelItems(); //be_ai_goal.h BotSetBrushModelTypes(); //be_ai_move.h // botimport.Print(PRT_MESSAGE, "-------------------------------------\n"); #ifdef DEBUG botimport.Print(PRT_MESSAGE, "map loaded in %d msec\n", Sys_MilliSeconds() - starttime); #endif // return BLERR_NOERROR; } //end of the function Export_BotLibLoadMap
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== weightconfig_t *ReadWeightConfig( char *filename ) { int newindent, avail = 0, n; token_t token; source_t *source; fuzzyseperator_t *fs; weightconfig_t *config = NULL; #ifdef DEBUG int starttime; starttime = Sys_MilliSeconds(); #endif //DEBUG if ( !LibVarGetValue( "bot_reloadcharacters" ) ) { avail = -1; for ( n = 0; n < MAX_WEIGHT_FILES; n++ ) { config = weightFileList[n]; if ( !config ) { if ( avail == -1 ) { avail = n; } //end if continue; } //end if if ( strcmp( filename, config->filename ) == 0 ) { //botimport.Print( PRT_MESSAGE, "retained %s\n", filename ); return config; } //end if } //end for if ( avail == -1 ) { botimport.Print( PRT_ERROR, "weightFileList was full trying to load %s\n", filename ); return NULL; } //end if } //end if source = LoadSourceFile( filename ); if ( !source ) { botimport.Print( PRT_ERROR, "counldn't load %s\n", filename ); return NULL; } //end if // config = (weightconfig_t *) GetClearedMemory( sizeof( weightconfig_t ) ); config->numweights = 0; Q_strncpyz( config->filename, filename, sizeof( config->filename ) ); //parse the item config file while ( PC_ReadToken( source, &token ) ) { if ( !strcmp( token.string, "weight" ) ) { if ( config->numweights >= MAX_WEIGHTS ) { SourceWarning( source, "too many fuzzy weights" ); break; } //end if if ( !PC_ExpectTokenType( source, TT_STRING, 0, &token ) ) { FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if StripDoubleQuotes( token.string ); config->weights[config->numweights].name = (char *) GetClearedMemory( strlen( token.string ) + 1 ); strcpy( config->weights[config->numweights].name, token.string ); if ( !PC_ExpectAnyToken( source, &token ) ) { FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if newindent = qfalse; if ( !strcmp( token.string, "{" ) ) { newindent = qtrue; if ( !PC_ExpectAnyToken( source, &token ) ) { FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if } //end if if ( !strcmp( token.string, "switch" ) ) { fs = ReadFuzzySeperators_r( source ); if ( !fs ) { FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if config->weights[config->numweights].firstseperator = fs; } //end if else if ( !strcmp( token.string, "return" ) ) { fs = (fuzzyseperator_t *) GetClearedMemory( sizeof( fuzzyseperator_t ) ); fs->index = 0; fs->value = MAX_INVENTORYVALUE; fs->next = NULL; fs->child = NULL; if ( !ReadFuzzyWeight( source, fs ) ) { FreeMemory( fs ); FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if config->weights[config->numweights].firstseperator = fs; } //end else if else { SourceError( source, "invalid name %s", token.string ); FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end else if ( newindent ) { if ( !PC_ExpectTokenString( source, "}" ) ) { FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end if } //end if config->numweights++; } //end if else { SourceError( source, "invalid name %s", token.string ); FreeWeightConfig( config ); FreeSource( source ); return NULL; } //end else } //end while //free the source at the end of a pass FreeSource( source ); //if the file was located in a pak file botimport.Print( PRT_MESSAGE, "loaded %s\n", filename ); #ifdef DEBUG if ( botDeveloper ) { botimport.Print( PRT_MESSAGE, "weights loaded in %d msec\n", Sys_MilliSeconds() - starttime ); } //end if #endif //DEBUG // if ( !LibVarGetValue( "bot_reloadcharacters" ) ) { weightFileList[avail] = config; } //end if // return config; } //end of the function ReadWeightConfig
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int AAS_AlternativeRouteGoals(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags, aas_altroutegoal_t *altroutegoals, int maxaltroutegoals, int type) { #ifndef ENABLE_ALTROUTING return 0; #else int i, j, bestareanum; int numaltroutegoals, nummidrangeareas; int starttime, goaltime, goaltraveltime; float dist, bestdist; vec3_t mid, dir; #ifdef ALTROUTE_DEBUG int startmillisecs; startmillisecs = Sys_MilliSeconds(); #endif if (!startareanum || !goalareanum) return 0; //travel time towards the goal area goaltraveltime = AAS_AreaTravelTimeToGoalArea(startareanum, start, goalareanum, travelflags); //clear the midrange areas Com_Memset(midrangeareas, 0, aasworld.numareas * sizeof(midrangearea_t)); numaltroutegoals = 0; // nummidrangeareas = 0; // for (i = 1; i < aasworld.numareas; i++) { // if (!(type & ALTROUTEGOAL_ALL)) { if (!(type & ALTROUTEGOAL_CLUSTERPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL))) { if (!(type & ALTROUTEGOAL_VIEWPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_VIEWPORTAL))) { continue; } //end if } //end if } //end if //if the area has no reachabilities if (!AAS_AreaReachability(i)) continue; //tavel time from the area to the start area starttime = AAS_AreaTravelTimeToGoalArea(startareanum, start, i, travelflags); if (!starttime) continue; //if the travel time from the start to the area is greater than the shortest goal travel time if (starttime > (float) 1.1 * goaltraveltime) continue; //travel time from the area to the goal area goaltime = AAS_AreaTravelTimeToGoalArea(i, NULL, goalareanum, travelflags); if (!goaltime) continue; //if the travel time from the area to the goal is greater than the shortest goal travel time if (goaltime > (float) 0.8 * goaltraveltime) continue; //this is a mid range area midrangeareas[i].valid = qtrue; midrangeareas[i].starttime = starttime; midrangeareas[i].goaltime = goaltime; Log_Write("%d midrange area %d", nummidrangeareas, i); nummidrangeareas++; } //end for // for (i = 1; i < aasworld.numareas; i++) { if (!midrangeareas[i].valid) continue; //get the areas in one cluster numclusterareas = 0; AAS_AltRoutingFloodCluster_r(i); //now we've got a cluster with areas through which an alternative route could go //get the 'center' of the cluster VectorClear(mid); for (j = 0; j < numclusterareas; j++) { VectorAdd(mid, aasworld.areas[clusterareas[j]].center, mid); } //end for VectorScale(mid, 1.0 / numclusterareas, mid); //get the area closest to the center of the cluster bestdist = 999999; bestareanum = 0; for (j = 0; j < numclusterareas; j++) { VectorSubtract(mid, aasworld.areas[clusterareas[j]].center, dir); dist = VectorLength(dir); if (dist < bestdist) { bestdist = dist; bestareanum = clusterareas[j]; } //end if } //end for //now we've got an area for an alternative route //FIXME: add alternative goal origin VectorCopy(aasworld.areas[bestareanum].center, altroutegoals[numaltroutegoals].origin); altroutegoals[numaltroutegoals].areanum = bestareanum; altroutegoals[numaltroutegoals].starttraveltime = midrangeareas[bestareanum].starttime; altroutegoals[numaltroutegoals].goaltraveltime = midrangeareas[bestareanum].goaltime; altroutegoals[numaltroutegoals].extratraveltime = (midrangeareas[bestareanum].starttime + midrangeareas[bestareanum].goaltime) - goaltraveltime; numaltroutegoals++; // #ifdef ALTROUTE_DEBUG AAS_ShowAreaPolygons(bestareanum, 1, qtrue); #endif //don't return more than the maximum alternative route goals if (numaltroutegoals >= maxaltroutegoals) break; } //end for #ifdef ALTROUTE_DEBUG botimport.Print(PRT_MESSAGE, "alternative route goals in %d msec\n", Sys_MilliSeconds() - startmillisecs); #endif return numaltroutegoals; #endif } //end of the function AAS_AlternativeRouteGoals
qboolean AAS_RT_ReadRouteTable(fileHandle_t fp) { int ident, version, i; unsigned short int crc, crc_aas; aas_rt_t *routetable; aas_rt_child_t *child; aas_rt_parent_t *parent; aas_rt_parent_link_t *plink; unsigned short int *psi; qboolean doswap; #ifdef DEBUG_READING_TIME int pretime; pretime = Sys_MilliSeconds(); #endif routetable = (*aasworld).routetable; doswap = (LittleLong(1) != 1); // check ident AAS_RT_DBG_Read(&ident, sizeof(ident), fp); ident = LittleLong(ident); if (ident != RTBID) { AAS_Error("File is not an RTB file\n"); botimport.FS_FCloseFile(fp); return qfalse; } // check version AAS_RT_DBG_Read(&version, sizeof(version), fp); version = LittleLong(version); if (version != RTBVERSION) { AAS_Error("File is version %i not %i\n", version, RTBVERSION); botimport.FS_FCloseFile(fp); return qfalse; } // read the CRC check on the AAS data AAS_RT_DBG_Read(&crc, sizeof(crc), fp); crc = LittleShort(crc); // calculate a CRC on the AAS areas crc_aas = CRC_ProcessString((unsigned char *)(*aasworld).areas, sizeof(aas_area_t) * (*aasworld).numareas); if (crc != crc_aas) { AAS_Error("Route-table is from different AAS file, ignoring.\n"); botimport.FS_FCloseFile(fp); return qfalse; } // read the route-table // children botimport.FS_Read(&routetable->numChildren, sizeof(int), fp); routetable->numChildren = LittleLong(routetable->numChildren); routetable->children = (aas_rt_child_t *) AAS_RT_GetClearedMemory(routetable->numChildren * sizeof(aas_rt_child_t)); botimport.FS_Read(routetable->children, routetable->numChildren * sizeof(aas_rt_child_t), fp); child = &routetable->children[0]; if (doswap) { for (i = 0; i < routetable->numChildren; i++, child++) { child->areanum = LittleShort(child->areanum); child->numParentLinks = LittleLong(child->numParentLinks); child->startParentLinks = LittleLong(child->startParentLinks); } } // parents botimport.FS_Read(&routetable->numParents, sizeof(int), fp); routetable->numParents = LittleLong(routetable->numParents); routetable->parents = (aas_rt_parent_t *) AAS_RT_GetClearedMemory(routetable->numParents * sizeof(aas_rt_parent_t)); botimport.FS_Read(routetable->parents, routetable->numParents * sizeof(aas_rt_parent_t), fp); parent = &routetable->parents[0]; if (doswap) { for (i = 0; i < routetable->numParents; i++, parent++) { parent->areanum = LittleShort(parent->areanum); parent->numParentChildren = LittleLong(parent->numParentChildren); parent->startParentChildren = LittleLong(parent->startParentChildren); parent->numVisibleParents = LittleLong(parent->numVisibleParents); parent->startVisibleParents = LittleLong(parent->startVisibleParents); } } // parentChildren botimport.FS_Read(&routetable->numParentChildren, sizeof(int), fp); routetable->numParentChildren = LittleLong(routetable->numParentChildren); routetable->parentChildren = (unsigned short int *) AAS_RT_GetClearedMemory(routetable->numParentChildren * sizeof(unsigned short int)); botimport.FS_Read(routetable->parentChildren, routetable->numParentChildren * sizeof(unsigned short int), fp); psi = &routetable->parentChildren[0]; if (doswap) { for (i = 0; i < routetable->numParentChildren; i++, psi++) { *psi = LittleShort(*psi); } } // visibleParents botimport.FS_Read(&routetable->numVisibleParents, sizeof(int), fp); routetable->numVisibleParents = LittleLong(routetable->numVisibleParents); routetable->visibleParents = (unsigned short int *) AAS_RT_GetClearedMemory(routetable->numVisibleParents * sizeof(unsigned short int)); botimport.FS_Read(routetable->visibleParents, routetable->numVisibleParents * sizeof(unsigned short int), fp); psi = &routetable->visibleParents[0]; if (doswap) { for (i = 0; i < routetable->numVisibleParents; i++, psi++) { *psi = LittleShort(*psi); } } // parentLinks botimport.FS_Read(&routetable->numParentLinks, sizeof(int), fp); routetable->numParentLinks = LittleLong(routetable->numParentLinks); routetable->parentLinks = (aas_rt_parent_link_t *) AAS_RT_GetClearedMemory(routetable->numParentLinks * sizeof(aas_rt_parent_link_t)); botimport.FS_Read(routetable->parentLinks, routetable->numParentLinks * sizeof(aas_parent_link_t), fp); plink = &routetable->parentLinks[0]; if (doswap) { for (i = 0; i < routetable->numParentLinks; i++, plink++) { plink->childIndex = LittleShort(plink->childIndex); plink->parent = LittleShort(plink->parent); } } // build the areaChildIndexes routetable->areaChildIndexes = (unsigned short int *) AAS_RT_GetClearedMemory((*aasworld).numareas * sizeof(unsigned short int)); child = routetable->children; for (i = 0; i < routetable->numChildren; i++, child++) { routetable->areaChildIndexes[child->areanum] = i + 1; } botimport.Print(PRT_MESSAGE, "Total Parents: %d\n", routetable->numParents); botimport.Print(PRT_MESSAGE, "Total Children: %d\n", routetable->numChildren); botimport.Print(PRT_MESSAGE, "Total Memory Used: %d\n", memorycount); #ifdef DEBUG_READING_TIME botimport.Print(PRT_MESSAGE, "Route-Table read time: %i\n", Sys_MilliSeconds() - pretime); #endif botimport.FS_FCloseFile(fp); return qtrue; }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int BotLoadCachedCharacter( char *charfile, int skill, int reload ) { int handle, cachedhandle; bot_character_t *ch = NULL; #ifdef DEBUG int starttime; starttime = Sys_MilliSeconds(); #endif //DEBUG //find a free spot for a character for ( handle = 1; handle <= MAX_CLIENTS; handle++ ) { if ( !botcharacters[ handle ] ) { break; } } //end for if ( handle > MAX_CLIENTS ) { return 0; } //try to load a cached character with the given skill if ( !reload ) { cachedhandle = BotFindCachedCharacter( charfile, skill ); if ( cachedhandle ) { //botimport.Print(PRT_MESSAGE, "loaded cached skill %d from %s\n", skill, charfile); return cachedhandle; } //end if } //end else //try to load the character with the given skill ch = BotLoadCharacterFromFile( charfile, skill ); if ( ch ) { botcharacters[ handle ] = ch; // //botimport.Print(PRT_MESSAGE, "loaded skill %d from %s\n", skill, charfile); #ifdef DEBUG if ( bot_developer ) { botimport.Print( PRT_MESSAGE, "skill %d loaded in %d msec from %s\n", skill, Sys_MilliSeconds() - starttime, charfile ); } //end if #endif //DEBUG return handle; } //end if // botimport.Print( PRT_WARNING, "couldn't find skill %d in %s\n", skill, charfile ); // if ( !reload ) { //try to load a cached default character with the given skill cachedhandle = BotFindCachedCharacter( "bots/default_c.c", skill ); if ( cachedhandle ) { botimport.Print( PRT_MESSAGE, "loaded cached default skill %d from %s\n", skill, charfile ); return cachedhandle; } //end if } //end if //try to load the default character with the given skill ch = BotLoadCharacterFromFile( DEFAULT_CHARACTER, skill ); if ( ch ) { botcharacters[ handle ] = ch; //botimport.Print(PRT_MESSAGE, "loaded default skill %d from %s\n", skill, charfile); return handle; } //end if // if ( !reload ) { //try to load a cached character with any skill cachedhandle = BotFindCachedCharacter( charfile, -1 ); if ( cachedhandle ) { //botimport.Print(PRT_MESSAGE, "loaded cached skill %d from %s\n", botcharacters[cachedhandle]->skill, charfile); return cachedhandle; } //end if } //end if //try to load a character with any skill ch = BotLoadCharacterFromFile( charfile, -1 ); if ( ch ) { botcharacters[ handle ] = ch; //botimport.Print(PRT_MESSAGE, "loaded skill %d from %s\n", ch->skill, charfile); return handle; } //end if // if ( !reload ) { //try to load a cached character with any skill cachedhandle = BotFindCachedCharacter( DEFAULT_CHARACTER, -1 ); if ( cachedhandle ) { botimport.Print( PRT_MESSAGE, "loaded cached default skill %d from %s\n", botcharacters[ cachedhandle ]->skill, charfile ); return cachedhandle; } //end if } //end if //try to load a character with any skill ch = BotLoadCharacterFromFile( DEFAULT_CHARACTER, -1 ); if ( ch ) { botcharacters[ handle ] = ch; botimport.Print( PRT_MESSAGE, "loaded default skill %d from %s\n", ch->skill, charfile ); return handle; } //end if // botimport.Print( PRT_WARNING, "couldn't load any skill from %s\n", charfile ); //couldn't load any character return 0; } //end of the function BotLoadCachedCharacter
qboolean AAS_RT_GetHidePos( vec3_t srcpos, int srcnum, int srcarea, vec3_t destpos, int destnum, int destarea, vec3_t returnPos ) { static int tfl = TFL_DEFAULT & ~( TFL_JUMPPAD | TFL_ROCKETJUMP | TFL_BFGJUMP | TFL_GRAPPLEHOOK | TFL_DOUBLEJUMP | TFL_RAMPJUMP | TFL_STRAFEJUMP | TFL_LAVA ); //----(SA) modified since slime is no longer deadly // static int tfl = TFL_DEFAULT & ~(TFL_JUMPPAD|TFL_ROCKETJUMP|TFL_BFGJUMP|TFL_GRAPPLEHOOK|TFL_DOUBLEJUMP|TFL_RAMPJUMP|TFL_STRAFEJUMP|TFL_SLIME|TFL_LAVA); #if 1 // use MrE's breadth first method int hideareanum; // int pretime; // disabled this so grenade hiding works //if (!srcarea || !destarea) // return qfalse; // pretime = -Sys_MilliSeconds(); hideareanum = AAS_NearestHideArea( srcnum, srcpos, srcarea, destnum, destpos, destarea, tfl ); if ( !hideareanum ) { // botimport.Print(PRT_MESSAGE, "Breadth First HidePos FAILED: %i ms\n", pretime + Sys_MilliSeconds()); return qfalse; } // we found a valid hiding area VectorCopy( ( *aasworld ).areawaypoints[hideareanum], returnPos ); // botimport.Print(PRT_MESSAGE, "Breadth First HidePos: %i ms\n", pretime + Sys_MilliSeconds()); return qtrue; #else // look around at random parent areas, if any of them have a center point // that isn't visible from "destpos", then return it's position in returnPos int i, j, pathArea, dir; unsigned short int destTravelTime; aas_rt_parent_t *srcParent, *travParent, *destParent; aas_rt_child_t *srcChild, *destChild, *travChild; aas_rt_route_t *route; vec3_t destVec; float destTravelDist; static float lastTime; static int frameCount, maxPerFrame = 2; int firstreach; aas_reachability_t *reachability, *reach; qboolean startVisible; unsigned short int bestTravelTime, thisTravelTime, elapsedTravelTime; #define MAX_HIDE_TRAVELTIME 1000 // 10 seconds is a very long way away unsigned char destVisLookup[MAX_PARENTS]; unsigned short int *destVisTrav; aas_rt_t *rt; const int MAX_CHECK_VISPARENTS = 100; int visparents_count, total_parents_checked; int thisParentIndex; int pretime; if ( !( rt = aasworld->routetable ) ) { // no route table present return qfalse; } /* if (lastTime > (AAS_Time() - 0.1)) { if (frameCount++ > maxPerFrame) { return qfalse; } } else { frameCount = 0; lastTime = AAS_Time(); } */ pretime = -Sys_MilliSeconds(); // is the src area grounded? if ( !( srcChild = AAS_RT_GetChild( srcarea ) ) ) { return qfalse; } // does it have a parent? // all valid areas have a parent // if (!srcChild->numParentLinks) { // return qfalse; // } // get the dest (enemy) area if ( !( destChild = AAS_RT_GetChild( destarea ) ) ) { return qfalse; } destParent = &rt->parents[ rt->parentLinks[destChild->startParentLinks].parent ]; // // populate the destVisAreas memset( destVisLookup, 0, sizeof( destVisLookup ) ); destVisTrav = rt->visibleParents + destParent->startVisibleParents; for ( i = 0; i < destParent->numVisibleParents; i++, destVisTrav++ ) { destVisLookup[*destVisTrav] = 1; } // // use the first parent to source the vis areas from srcParent = &rt->parents[ rt->parentLinks[srcChild->startParentLinks].parent ]; // // set the destTravelTime if ( route = AAS_RT_GetRoute( srcarea, srcpos, destarea ) ) { destTravelTime = route->travel_time; } else { destTravelTime = 0; } bestTravelTime = MAX_HIDE_TRAVELTIME; // ignore any routes longer than 10 seconds away // set the destVec VectorSubtract( destpos, srcpos, destVec ); destTravelDist = VectorNormalize( destVec ); // // randomize the direction we traverse the list, so the hiding spot isn't always the same if ( rand() % 2 ) { dir = 1; // forward } else { dir = -1; // reverse } // randomize the starting area if ( srcParent->numVisibleParents ) { i = rand() % srcParent->numVisibleParents; } else { // prevent divide by zero i = 0; } // // setup misc stuff reachability = ( *aasworld ).reachability; startVisible = botimport.AICast_VisibleFromPos( destpos, destnum, srcpos, srcnum, qfalse ); // // set the firstreach to prevent having to do an array and pointer lookup for each destination firstreach = ( *aasworld ).areasettings[srcarea].firstreachablearea; // // just check random parent areas, traversing the route until we find an area that can't be seen from the dest area for ( visparents_count = 0, total_parents_checked = 0; visparents_count < MAX_CHECK_VISPARENTS && total_parents_checked < rt->numParents; total_parents_checked++ ) { thisParentIndex = rand() % rt->numParents; travParent = &rt->parents[ thisParentIndex ]; // // never go to the enemy's areas if ( travParent->areanum == destarea ) { continue; } // // if it's visible from dest, ignore it if ( destVisLookup[thisParentIndex] ) { continue; } // visparents_count++; // they might be visible, check to see if the path to the area, takes us towards the // enemy we are trying to hide from { qboolean invalidRoute; vec3_t curPos, lastVec; #define GETHIDE_MAX_CHECK_PATHS 15 // invalidRoute = qfalse; // initialize the pathArea pathArea = srcarea; VectorCopy( srcpos, curPos ); // now evaluate the path for ( j = 0; j < GETHIDE_MAX_CHECK_PATHS; j++ ) { // get the reachability to the travParent if ( !( route = AAS_RT_GetRoute( pathArea, curPos, travParent->areanum ) ) ) { // we can't get to the travParent, so don't bother checking it invalidRoute = qtrue; break; } // set the pathArea reach = &reachability[route->reachable_index]; // how far have we travelled so far? elapsedTravelTime = AAS_AreaTravelTimeToGoalArea( pathArea, curPos, reach->areanum, tfl ); // add the travel to the center of the area elapsedTravelTime += AAS_AreaTravelTime( reach->areanum, reach->end, ( *aasworld ).areas[reach->areanum].center ); // have we gone too far already? if ( elapsedTravelTime > bestTravelTime ) { invalidRoute = qtrue; break; } else { thisTravelTime = route->travel_time; } // // if this travel would have us do something wierd if ( ( reach->traveltype == TRAVEL_WALKOFFLEDGE ) && ( reach->traveltime > 500 ) ) { invalidRoute = qtrue; break; } // pathArea = reach->areanum; VectorCopy( reach->end, curPos ); // // if this moves us into the enemies area, skip it if ( pathArea == destarea ) { invalidRoute = qtrue; break; } // if we are very close, don't get any closer under any circumstances { vec3_t vec; float dist; // VectorSubtract( destpos, reachability[firstreach + route->reachable_index].end, vec ); dist = VectorNormalize( vec ); // if ( destTravelTime < 400 ) { if ( dist < destTravelDist ) { invalidRoute = qtrue; break; } if ( DotProduct( destVec, vec ) < 0.2 ) { invalidRoute = qtrue; break; } } else { if ( dist < destTravelDist * 0.7 ) { invalidRoute = qtrue; break; } } // // check the directions to make sure we're not trying to run through them if ( j > 0 ) { if ( DotProduct( vec, lastVec ) < 0.2 ) { invalidRoute = qtrue; break; } } else if ( DotProduct( destVec, vec ) < 0.2 ) { invalidRoute = qtrue; break; } // VectorCopy( vec, lastVec ); } // // if this area isn't in the visible list for the enemy's area, it's a good hiding spot if ( !( travChild = AAS_RT_GetChild( pathArea ) ) ) { invalidRoute = qtrue; break; } if ( !destVisLookup[rt->parentLinks[travChild->startParentLinks].parent] ) { // success ? if ( !botimport.AICast_VisibleFromPos( destpos, destnum, ( *aasworld ).areas[pathArea].center, srcnum, qfalse ) ) { // SUCESS !! travParent = &rt->parents[rt->parentLinks[travChild->startParentLinks].parent]; break; } } else { // if we weren't visible when starting, make sure we don't move into their view if ( !startVisible ) { //botimport.AICast_VisibleFromPos( destpos, destnum, reachability[firstreach + route->reachable_index].end, srcnum, qfalse )) { invalidRoute = qtrue; break; } } // // if this is the travParent, then stop checking if ( pathArea == travParent->areanum ) { invalidRoute = qtrue; // we didn't find a hiding spot break; } } // end for areas in route // // if the route is invalid, skip this travParent if ( invalidRoute ) { continue; } } // // now last of all, check that this area is a safe hiding spot // if (botimport.AICast_VisibleFromPos( destpos, destnum, (*aasworld).areas[travParent->areanum].center, srcnum, qfalse )) { // continue; // } // // we've found a good hiding spot, so use it VectorCopy( ( *aasworld ).areas[travParent->areanum].center, returnPos ); bestTravelTime = elapsedTravelTime; // if ( thisTravelTime < 300 ) { botimport.Print( PRT_MESSAGE, "Fuzzy RT HidePos: %i ms\n", pretime + Sys_MilliSeconds() ); return qtrue; } } // // did we find something? if ( bestTravelTime < MAX_HIDE_TRAVELTIME ) { botimport.Print( PRT_MESSAGE, "Fuzzy RT HidePos: %i ms\n", pretime + Sys_MilliSeconds() ); return qtrue; } // // couldn't find anything botimport.Print( PRT_MESSAGE, "Fuzzy RT HidePos FAILED: %i ms\n", pretime + Sys_MilliSeconds() ); return qfalse; #endif }
int BotLoadCachedCharacter(char *charfile, float skill, int reload) { int handle, cachedhandle, intskill; bot_character_t *ch = NULL; #ifdef DEBUG int starttime; starttime = Sys_MilliSeconds(); #endif /* DEBUG */ /* find a free spot for a character */ for(handle = 1; handle <= MAX_CLIENTS; handle++) if(!botcharacters[handle]) break; if(handle > MAX_CLIENTS) return 0; /* try to load a cached character with the given skill */ if(!reload){ cachedhandle = BotFindCachedCharacter(charfile, skill); if(cachedhandle){ botimport.Print(PRT_MESSAGE, "loaded cached skill %f from %s\n", skill, charfile); return cachedhandle; } } intskill = (int)(skill + 0.5); /* try to load the character with the given skill */ ch = BotLoadCharacterFromFile(charfile, intskill); if(ch){ botcharacters[handle] = ch; botimport.Print(PRT_MESSAGE, "loaded skill %d from %s\n", intskill, charfile); #ifdef DEBUG if(botDeveloper) botimport.Print(PRT_MESSAGE, "skill %d loaded in %d msec from %s\n", intskill, Sys_MilliSeconds() - starttime, charfile); #endif /* DEBUG */ return handle; } botimport.Print(PRT_WARNING, "couldn't find skill %d in %s\n", intskill, charfile); if(!reload){ /* try to load a cached default character with the given skill */ cachedhandle = BotFindCachedCharacter(DEFAULT_CHARACTER, skill); if(cachedhandle){ botimport.Print( PRT_MESSAGE, "loaded cached default skill %d from %s\n", intskill, charfile); return cachedhandle; } } /* try to load the default character with the given skill */ ch = BotLoadCharacterFromFile(DEFAULT_CHARACTER, intskill); if(ch){ botcharacters[handle] = ch; botimport.Print(PRT_MESSAGE, "loaded default skill %d from %s\n", intskill, charfile); return handle; } if(!reload){ /* try to load a cached character with any skill */ cachedhandle = BotFindCachedCharacter(charfile, -1); if(cachedhandle){ botimport.Print(PRT_MESSAGE, "loaded cached skill %f from %s\n", botcharacters[cachedhandle]->skill, charfile); return cachedhandle; } } /* try to load a character with any skill */ ch = BotLoadCharacterFromFile(charfile, -1); if(ch){ botcharacters[handle] = ch; botimport.Print(PRT_MESSAGE, "loaded skill %f from %s\n", ch->skill, charfile); return handle; } if(!reload){ /* try to load a cached character with any skill */ cachedhandle = BotFindCachedCharacter(DEFAULT_CHARACTER, -1); if(cachedhandle){ botimport.Print( PRT_MESSAGE, "loaded cached default skill %f from %s\n", botcharacters[cachedhandle]->skill, charfile); return cachedhandle; } } /* try to load a character with any skill */ ch = BotLoadCharacterFromFile(DEFAULT_CHARACTER, -1); if(ch){ botcharacters[handle] = ch; botimport.Print(PRT_MESSAGE, "loaded default skill %f from %s\n", ch->skill, charfile); return handle; } botimport.Print(PRT_WARNING, "couldn't load any skill from %s\n", charfile); /* couldn't load any character */ return 0; }