diff options
Diffstat (limited to 'ioq3-r437/src/botlib/be_aas_route.c')
-rw-r--r-- | ioq3-r437/src/botlib/be_aas_route.c | 2210 |
1 files changed, 0 insertions, 2210 deletions
diff --git a/ioq3-r437/src/botlib/be_aas_route.c b/ioq3-r437/src/botlib/be_aas_route.c deleted file mode 100644 index e31202b0..00000000 --- a/ioq3-r437/src/botlib/be_aas_route.c +++ /dev/null @@ -1,2210 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quake III Arena source code; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -/***************************************************************************** - * name: be_aas_route.c - * - * desc: AAS - * - * $Archive: /MissionPack/code/botlib/be_aas_route.c $ - * - *****************************************************************************/ - -#include "../qcommon/q_shared.h" -#include "l_utils.h" -#include "l_memory.h" -#include "l_log.h" -#include "l_crc.h" -#include "l_libvar.h" -#include "l_script.h" -#include "l_precomp.h" -#include "l_struct.h" -#include "aasfile.h" -#include "botlib.h" -#include "be_aas.h" -#include "be_aas_funcs.h" -#include "be_interface.h" -#include "be_aas_def.h" - -#define ROUTING_DEBUG - -//travel time in hundreths of a second = distance * 100 / speed -#define DISTANCEFACTOR_CROUCH 1.3f //crouch speed = 100 -#define DISTANCEFACTOR_SWIM 1 //should be 0.66, swim speed = 150 -#define DISTANCEFACTOR_WALK 0.33f //walk speed = 300 - -//cache refresh time -#define CACHE_REFRESHTIME 15.0f //15 seconds refresh time - -//maximum number of routing updates each frame -#define MAX_FRAMEROUTINGUPDATES 10 - - -/* - - area routing cache: - stores the distances within one cluster to a specific goal area - this goal area is in this same cluster and could be a cluster portal - for every cluster there's a list with routing cache for every area - in that cluster (including the portals of that cluster) - area cache stores aasworld.clusters[?].numreachabilityareas travel times - - portal routing cache: - stores the distances of all portals to a specific goal area - this goal area could be in any cluster and could also be a cluster portal - for every area (aasworld.numareas) the portal cache stores - aasworld.numportals travel times - -*/ - -#ifdef ROUTING_DEBUG -int numareacacheupdates; -int numportalcacheupdates; -#endif //ROUTING_DEBUG - -int routingcachesize; -int max_routingcachesize; - -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -#ifdef ROUTING_DEBUG -void AAS_RoutingInfo(void) -{ - botimport.Print(PRT_MESSAGE, "%d area cache updates\n", numareacacheupdates); - botimport.Print(PRT_MESSAGE, "%d portal cache updates\n", numportalcacheupdates); - botimport.Print(PRT_MESSAGE, "%d bytes routing cache\n", routingcachesize); -} //end of the function AAS_RoutingInfo -#endif //ROUTING_DEBUG -//=========================================================================== -// returns the number of the area in the cluster -// assumes the given area is in the given cluster or a portal of the cluster -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -ID_INLINE int AAS_ClusterAreaNum(int cluster, int areanum) -{ - int side, areacluster; - - areacluster = aasworld.areasettings[areanum].cluster; - if (areacluster > 0) return aasworld.areasettings[areanum].clusterareanum; - else - { -/*#ifdef ROUTING_DEBUG - if (aasworld.portals[-areacluster].frontcluster != cluster && - aasworld.portals[-areacluster].backcluster != cluster) - { - botimport.Print(PRT_ERROR, "portal %d: does not belong to cluster %d\n" - , -areacluster, cluster); - } //end if -#endif //ROUTING_DEBUG*/ - side = aasworld.portals[-areacluster].frontcluster != cluster; - return aasworld.portals[-areacluster].clusterareanum[side]; - } //end else -} //end of the function AAS_ClusterAreaNum -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_InitTravelFlagFromType(void) -{ - int i; - - for (i = 0; i < MAX_TRAVELTYPES; i++) - { - aasworld.travelflagfortype[i] = TFL_INVALID; - } //end for - aasworld.travelflagfortype[TRAVEL_INVALID] = TFL_INVALID; - aasworld.travelflagfortype[TRAVEL_WALK] = TFL_WALK; - aasworld.travelflagfortype[TRAVEL_CROUCH] = TFL_CROUCH; - aasworld.travelflagfortype[TRAVEL_BARRIERJUMP] = TFL_BARRIERJUMP; - aasworld.travelflagfortype[TRAVEL_JUMP] = TFL_JUMP; - aasworld.travelflagfortype[TRAVEL_LADDER] = TFL_LADDER; - aasworld.travelflagfortype[TRAVEL_WALKOFFLEDGE] = TFL_WALKOFFLEDGE; - aasworld.travelflagfortype[TRAVEL_SWIM] = TFL_SWIM; - aasworld.travelflagfortype[TRAVEL_WATERJUMP] = TFL_WATERJUMP; - aasworld.travelflagfortype[TRAVEL_TELEPORT] = TFL_TELEPORT; - aasworld.travelflagfortype[TRAVEL_ELEVATOR] = TFL_ELEVATOR; - aasworld.travelflagfortype[TRAVEL_ROCKETJUMP] = TFL_ROCKETJUMP; - aasworld.travelflagfortype[TRAVEL_BFGJUMP] = TFL_BFGJUMP; - aasworld.travelflagfortype[TRAVEL_GRAPPLEHOOK] = TFL_GRAPPLEHOOK; - aasworld.travelflagfortype[TRAVEL_DOUBLEJUMP] = TFL_DOUBLEJUMP; - aasworld.travelflagfortype[TRAVEL_RAMPJUMP] = TFL_RAMPJUMP; - aasworld.travelflagfortype[TRAVEL_STRAFEJUMP] = TFL_STRAFEJUMP; - aasworld.travelflagfortype[TRAVEL_JUMPPAD] = TFL_JUMPPAD; - aasworld.travelflagfortype[TRAVEL_FUNCBOB] = TFL_FUNCBOB; -} //end of the function AAS_InitTravelFlagFromType -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -ID_INLINE int AAS_TravelFlagForType_inline(int traveltype) -{ - int tfl; - - tfl = 0; - if (tfl & TRAVELFLAG_NOTTEAM1) - tfl |= TFL_NOTTEAM1; - if (tfl & TRAVELFLAG_NOTTEAM2) - tfl |= TFL_NOTTEAM2; - traveltype &= TRAVELTYPE_MASK; - if (traveltype < 0 || traveltype >= MAX_TRAVELTYPES) - return TFL_INVALID; - tfl |= aasworld.travelflagfortype[traveltype]; - return tfl; -} //end of the function AAS_TravelFlagForType_inline -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_TravelFlagForType(int traveltype) -{ - return AAS_TravelFlagForType_inline(traveltype); -} //end of the function AAS_TravelFlagForType_inline -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_UnlinkCache(aas_routingcache_t *cache) -{ - if (cache->time_next) cache->time_next->time_prev = cache->time_prev; - else aasworld.newestcache = cache->time_prev; - if (cache->time_prev) cache->time_prev->time_next = cache->time_next; - else aasworld.oldestcache = cache->time_next; - cache->time_next = NULL; - cache->time_prev = NULL; -} //end of the function AAS_UnlinkCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_LinkCache(aas_routingcache_t *cache) -{ - if (aasworld.newestcache) - { - aasworld.newestcache->time_next = cache; - cache->time_prev = aasworld.newestcache; - } //end if - else - { - aasworld.oldestcache = cache; - cache->time_prev = NULL; - } //end else - cache->time_next = NULL; - aasworld.newestcache = cache; -} //end of the function AAS_LinkCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_FreeRoutingCache(aas_routingcache_t *cache) -{ - AAS_UnlinkCache(cache); - routingcachesize -= cache->size; - FreeMemory(cache); -} //end of the function AAS_FreeRoutingCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_RemoveRoutingCacheInCluster( int clusternum ) -{ - int i; - aas_routingcache_t *cache, *nextcache; - aas_cluster_t *cluster; - - if (!aasworld.clusterareacache) - return; - cluster = &aasworld.clusters[clusternum]; - for (i = 0; i < cluster->numareas; i++) - { - for (cache = aasworld.clusterareacache[clusternum][i]; cache; cache = nextcache) - { - nextcache = cache->next; - AAS_FreeRoutingCache(cache); - } //end for - aasworld.clusterareacache[clusternum][i] = NULL; - } //end for -} //end of the function AAS_RemoveRoutingCacheInCluster -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_RemoveRoutingCacheUsingArea( int areanum ) -{ - int i, clusternum; - aas_routingcache_t *cache, *nextcache; - - clusternum = aasworld.areasettings[areanum].cluster; - if (clusternum > 0) - { - //remove all the cache in the cluster the area is in - AAS_RemoveRoutingCacheInCluster( clusternum ); - } //end if - else - { - // if this is a portal remove all cache in both the front and back cluster - AAS_RemoveRoutingCacheInCluster( aasworld.portals[-clusternum].frontcluster ); - AAS_RemoveRoutingCacheInCluster( aasworld.portals[-clusternum].backcluster ); - } //end else - // remove all portal cache - for (i = 0; i < aasworld.numareas; i++) - { - //refresh portal cache - for (cache = aasworld.portalcache[i]; cache; cache = nextcache) - { - nextcache = cache->next; - AAS_FreeRoutingCache(cache); - } //end for - aasworld.portalcache[i] = NULL; - } //end for -} //end of the function AAS_RemoveRoutingCacheUsingArea -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_EnableRoutingArea(int areanum, int enable) -{ - int flags; - - if (areanum <= 0 || areanum >= aasworld.numareas) - { - if (bot_developer) - { - botimport.Print(PRT_ERROR, "AAS_EnableRoutingArea: areanum %d out of range\n", areanum); - } //end if - return 0; - } //end if - flags = aasworld.areasettings[areanum].areaflags & AREA_DISABLED; - if (enable < 0) - return !flags; - - if (enable) - aasworld.areasettings[areanum].areaflags &= ~AREA_DISABLED; - else - aasworld.areasettings[areanum].areaflags |= AREA_DISABLED; - // if the status of the area changed - if ( (flags & AREA_DISABLED) != (aasworld.areasettings[areanum].areaflags & AREA_DISABLED) ) - { - //remove all routing cache involving this area - AAS_RemoveRoutingCacheUsingArea( areanum ); - } //end if - return !flags; -} //end of the function AAS_EnableRoutingArea -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -ID_INLINE float AAS_RoutingTime(void) -{ - return AAS_Time(); -} //end of the function AAS_RoutingTime -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_GetAreaContentsTravelFlags(int areanum) -{ - int contents, tfl; - - contents = aasworld.areasettings[areanum].contents; - tfl = 0; - if (contents & AREACONTENTS_WATER) - tfl |= TFL_WATER; - else if (contents & AREACONTENTS_SLIME) - tfl |= TFL_SLIME; - else if (contents & AREACONTENTS_LAVA) - tfl |= TFL_LAVA; - else - tfl |= TFL_AIR; - if (contents & AREACONTENTS_DONOTENTER) - tfl |= TFL_DONOTENTER; - if (contents & AREACONTENTS_NOTTEAM1) - tfl |= TFL_NOTTEAM1; - if (contents & AREACONTENTS_NOTTEAM2) - tfl |= TFL_NOTTEAM2; - if (aasworld.areasettings[areanum].areaflags & AREA_BRIDGE) - tfl |= TFL_BRIDGE; - return tfl; -} //end of the function AAS_GetAreaContentsTravelFlags -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -ID_INLINE int AAS_AreaContentsTravelFlags_inline(int areanum) -{ - return aasworld.areacontentstravelflags[areanum]; -} //end of the function AAS_AreaContentsTravelFlags -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_AreaContentsTravelFlags(int areanum) -{ - return aasworld.areacontentstravelflags[areanum]; -} //end of the function AAS_AreaContentsTravelFlags -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_InitAreaContentsTravelFlags(void) -{ - int i; - - if (aasworld.areacontentstravelflags) FreeMemory(aasworld.areacontentstravelflags); - aasworld.areacontentstravelflags = (int *) GetClearedMemory(aasworld.numareas * sizeof(int)); - // - for (i = 0; i < aasworld.numareas; i++) { - aasworld.areacontentstravelflags[i] = AAS_GetAreaContentsTravelFlags(i); - } -} //end of the function AAS_InitAreaContentsTravelFlags -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_CreateReversedReachability(void) -{ - int i, n; - aas_reversedlink_t *revlink; - aas_reachability_t *reach; - aas_areasettings_t *settings; - char *ptr; -#ifdef DEBUG - int starttime; - - starttime = Sys_MilliSeconds(); -#endif - //free reversed links that have already been created - if (aasworld.reversedreachability) FreeMemory(aasworld.reversedreachability); - //allocate memory for the reversed reachability links - ptr = (char *) GetClearedMemory(aasworld.numareas * sizeof(aas_reversedreachability_t) + - aasworld.reachabilitysize * sizeof(aas_reversedlink_t)); - // - aasworld.reversedreachability = (aas_reversedreachability_t *) ptr; - //pointer to the memory for the reversed links - ptr += aasworld.numareas * sizeof(aas_reversedreachability_t); - //check all reachabilities of all areas - for (i = 1; i < aasworld.numareas; i++) - { - //settings of the area - settings = &aasworld.areasettings[i]; - // - if (settings->numreachableareas >= 128) - botimport.Print(PRT_WARNING, "area %d has more than 128 reachabilities\n", i); - //create reversed links for the reachabilities - for (n = 0; n < settings->numreachableareas && n < 128; n++) - { - //reachability link - reach = &aasworld.reachability[settings->firstreachablearea + n]; - // - revlink = (aas_reversedlink_t *) ptr; - ptr += sizeof(aas_reversedlink_t); - // - revlink->areanum = i; - revlink->linknum = settings->firstreachablearea + n; - revlink->next = aasworld.reversedreachability[reach->areanum].first; - aasworld.reversedreachability[reach->areanum].first = revlink; - aasworld.reversedreachability[reach->areanum].numlinks++; - } //end for - } //end for -#ifdef DEBUG - botimport.Print(PRT_MESSAGE, "reversed reachability %d msec\n", Sys_MilliSeconds() - starttime); -#endif -} //end of the function AAS_CreateReversedReachability -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -unsigned short int AAS_AreaTravelTime(int areanum, vec3_t start, vec3_t end) -{ - int intdist; - float dist; - vec3_t dir; - - VectorSubtract(start, end, dir); - dist = VectorLength(dir); - //if crouch only area - if (AAS_AreaCrouch(areanum)) dist *= DISTANCEFACTOR_CROUCH; - //if swim area - else if (AAS_AreaSwim(areanum)) dist *= DISTANCEFACTOR_SWIM; - //normal walk area - else dist *= DISTANCEFACTOR_WALK; - // - intdist = (int) dist; - //make sure the distance isn't zero - if (intdist <= 0) intdist = 1; - return intdist; -} //end of the function AAS_AreaTravelTime -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_CalculateAreaTravelTimes(void) -{ - int i, l, n, size; - char *ptr; - vec3_t end; - aas_reversedreachability_t *revreach; - aas_reversedlink_t *revlink; - aas_reachability_t *reach; - aas_areasettings_t *settings; - int starttime; - - starttime = Sys_MilliSeconds(); - //if there are still area travel times, free the memory - if (aasworld.areatraveltimes) FreeMemory(aasworld.areatraveltimes); - //get the total size of all the area travel times - size = aasworld.numareas * sizeof(unsigned short **); - for (i = 0; i < aasworld.numareas; i++) - { - revreach = &aasworld.reversedreachability[i]; - //settings of the area - settings = &aasworld.areasettings[i]; - // - size += settings->numreachableareas * sizeof(unsigned short *); - // - size += settings->numreachableareas * - PAD(revreach->numlinks, sizeof(long)) * sizeof(unsigned short); - } //end for - //allocate memory for the area travel times - ptr = (char *) GetClearedMemory(size); - aasworld.areatraveltimes = (unsigned short ***) ptr; - ptr += aasworld.numareas * sizeof(unsigned short **); - //calcluate the travel times for all the areas - for (i = 0; i < aasworld.numareas; i++) - { - //reversed reachabilities of this area - revreach = &aasworld.reversedreachability[i]; - //settings of the area - settings = &aasworld.areasettings[i]; - // - aasworld.areatraveltimes[i] = (unsigned short **) ptr; - ptr += settings->numreachableareas * sizeof(unsigned short *); - // - for (l = 0; l < settings->numreachableareas; l++) - { - aasworld.areatraveltimes[i][l] = (unsigned short *) ptr; - ptr += PAD(revreach->numlinks, sizeof(long)) * sizeof(unsigned short); - //reachability link - reach = &aasworld.reachability[settings->firstreachablearea + l]; - // - for (n = 0, revlink = revreach->first; revlink; revlink = revlink->next, n++) - { - VectorCopy(aasworld.reachability[revlink->linknum].end, end); - // - aasworld.areatraveltimes[i][l][n] = AAS_AreaTravelTime(i, end, reach->start); - } //end for - } //end for - } //end for -#ifdef DEBUG - botimport.Print(PRT_MESSAGE, "area travel times %d msec\n", Sys_MilliSeconds() - starttime); -#endif -} //end of the function AAS_CalculateAreaTravelTimes -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_PortalMaxTravelTime(int portalnum) -{ - int l, n, t, maxt; - aas_portal_t *portal; - aas_reversedreachability_t *revreach; - aas_reversedlink_t *revlink; - aas_areasettings_t *settings; - - portal = &aasworld.portals[portalnum]; - //reversed reachabilities of this portal area - revreach = &aasworld.reversedreachability[portal->areanum]; - //settings of the portal area - settings = &aasworld.areasettings[portal->areanum]; - // - maxt = 0; - for (l = 0; l < settings->numreachableareas; l++) - { - for (n = 0, revlink = revreach->first; revlink; revlink = revlink->next, n++) - { - t = aasworld.areatraveltimes[portal->areanum][l][n]; - if (t > maxt) - { - maxt = t; - } //end if - } //end for - } //end for - return maxt; -} //end of the function AAS_PortalMaxTravelTime -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_InitPortalMaxTravelTimes(void) -{ - int i; - - if (aasworld.portalmaxtraveltimes) FreeMemory(aasworld.portalmaxtraveltimes); - - aasworld.portalmaxtraveltimes = (int *) GetClearedMemory(aasworld.numportals * sizeof(int)); - - for (i = 0; i < aasworld.numportals; i++) - { - aasworld.portalmaxtraveltimes[i] = AAS_PortalMaxTravelTime(i); - //botimport.Print(PRT_MESSAGE, "portal %d max tt = %d\n", i, aasworld.portalmaxtraveltimes[i]); - } //end for -} //end of the function AAS_InitPortalMaxTravelTimes -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -/* -int AAS_FreeOldestCache(void) -{ - int i, j, bestcluster, bestarea, freed; - float besttime; - aas_routingcache_t *cache, *bestcache; - - freed = qfalse; - besttime = 999999999; - bestcache = NULL; - bestcluster = 0; - bestarea = 0; - //refresh cluster cache - for (i = 0; i < aasworld.numclusters; i++) - { - for (j = 0; j < aasworld.clusters[i].numareas; j++) - { - for (cache = aasworld.clusterareacache[i][j]; cache; cache = cache->next) - { - //never remove cache leading towards a portal - if (aasworld.areasettings[cache->areanum].cluster < 0) continue; - //if this cache is older than the cache we found so far - if (cache->time < besttime) - { - bestcache = cache; - bestcluster = i; - bestarea = j; - besttime = cache->time; - } //end if - } //end for - } //end for - } //end for - if (bestcache) - { - cache = bestcache; - if (cache->prev) cache->prev->next = cache->next; - else aasworld.clusterareacache[bestcluster][bestarea] = cache->next; - if (cache->next) cache->next->prev = cache->prev; - AAS_FreeRoutingCache(cache); - freed = qtrue; - } //end if - besttime = 999999999; - bestcache = NULL; - bestarea = 0; - for (i = 0; i < aasworld.numareas; i++) - { - //refresh portal cache - for (cache = aasworld.portalcache[i]; cache; cache = cache->next) - { - if (cache->time < besttime) - { - bestcache = cache; - bestarea = i; - besttime = cache->time; - } //end if - } //end for - } //end for - if (bestcache) - { - cache = bestcache; - if (cache->prev) cache->prev->next = cache->next; - else aasworld.portalcache[bestarea] = cache->next; - if (cache->next) cache->next->prev = cache->prev; - AAS_FreeRoutingCache(cache); - freed = qtrue; - } //end if - return freed; -} //end of the function AAS_FreeOldestCache -*/ -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_FreeOldestCache(void) -{ - int clusterareanum; - aas_routingcache_t *cache; - - for (cache = aasworld.oldestcache; cache; cache = cache->time_next) { - // never free area cache leading towards a portal - if (cache->type == CACHETYPE_AREA && aasworld.areasettings[cache->areanum].cluster < 0) { - continue; - } - break; - } - if (cache) { - // unlink the cache - if (cache->type == CACHETYPE_AREA) { - //number of the area in the cluster - clusterareanum = AAS_ClusterAreaNum(cache->cluster, cache->areanum); - // unlink from cluster area cache - if (cache->prev) cache->prev->next = cache->next; - else aasworld.clusterareacache[cache->cluster][clusterareanum] = cache->next; - if (cache->next) cache->next->prev = cache->prev; - } - else { - // unlink from portal cache - if (cache->prev) cache->prev->next = cache->next; - else aasworld.portalcache[cache->areanum] = cache->next; - if (cache->next) cache->next->prev = cache->prev; - } - AAS_FreeRoutingCache(cache); - return qtrue; - } - return qfalse; -} //end of the function AAS_FreeOldestCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -aas_routingcache_t *AAS_AllocRoutingCache(int numtraveltimes) -{ - aas_routingcache_t *cache; - int size; - - // - size = sizeof(aas_routingcache_t) - + numtraveltimes * sizeof(unsigned short int) - + numtraveltimes * sizeof(unsigned char); - // - routingcachesize += size; - // - cache = (aas_routingcache_t *) GetClearedMemory(size); - cache->reachabilities = (unsigned char *) cache + sizeof(aas_routingcache_t) - + numtraveltimes * sizeof(unsigned short int); - cache->size = size; - return cache; -} //end of the function AAS_AllocRoutingCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_FreeAllClusterAreaCache(void) -{ - int i, j; - aas_routingcache_t *cache, *nextcache; - aas_cluster_t *cluster; - - //free all cluster cache if existing - if (!aasworld.clusterareacache) return; - //free caches - for (i = 0; i < aasworld.numclusters; i++) - { - cluster = &aasworld.clusters[i]; - for (j = 0; j < cluster->numareas; j++) - { - for (cache = aasworld.clusterareacache[i][j]; cache; cache = nextcache) - { - nextcache = cache->next; - AAS_FreeRoutingCache(cache); - } //end for - aasworld.clusterareacache[i][j] = NULL; - } //end for - } //end for - //free the cluster cache array - FreeMemory(aasworld.clusterareacache); - aasworld.clusterareacache = NULL; -} //end of the function AAS_FreeAllClusterAreaCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_InitClusterAreaCache(void) -{ - int i, size; - char *ptr; - - // - for (size = 0, i = 0; i < aasworld.numclusters; i++) - { - size += aasworld.clusters[i].numareas; - } //end for - //two dimensional array with pointers for every cluster to routing cache - //for every area in that cluster - ptr = (char *) GetClearedMemory( - aasworld.numclusters * sizeof(aas_routingcache_t **) + - size * sizeof(aas_routingcache_t *)); - aasworld.clusterareacache = (aas_routingcache_t ***) ptr; - ptr += aasworld.numclusters * sizeof(aas_routingcache_t **); - for (i = 0; i < aasworld.numclusters; i++) - { - aasworld.clusterareacache[i] = (aas_routingcache_t **) ptr; - ptr += aasworld.clusters[i].numareas * sizeof(aas_routingcache_t *); - } //end for -} //end of the function AAS_InitClusterAreaCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_FreeAllPortalCache(void) -{ - int i; - aas_routingcache_t *cache, *nextcache; - - //free all portal cache if existing - if (!aasworld.portalcache) return; - //free portal caches - for (i = 0; i < aasworld.numareas; i++) - { - for (cache = aasworld.portalcache[i]; cache; cache = nextcache) - { - nextcache = cache->next; - AAS_FreeRoutingCache(cache); - } //end for - aasworld.portalcache[i] = NULL; - } //end for - FreeMemory(aasworld.portalcache); - aasworld.portalcache = NULL; -} //end of the function AAS_FreeAllPortalCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_InitPortalCache(void) -{ - // - aasworld.portalcache = (aas_routingcache_t **) GetClearedMemory( - aasworld.numareas * sizeof(aas_routingcache_t *)); -} //end of the function AAS_InitPortalCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_InitRoutingUpdate(void) -{ - int i, maxreachabilityareas; - - //free routing update fields if already existing - if (aasworld.areaupdate) FreeMemory(aasworld.areaupdate); - // - maxreachabilityareas = 0; - for (i = 0; i < aasworld.numclusters; i++) - { - if (aasworld.clusters[i].numreachabilityareas > maxreachabilityareas) - { - maxreachabilityareas = aasworld.clusters[i].numreachabilityareas; - } //end if - } //end for - //allocate memory for the routing update fields - aasworld.areaupdate = (aas_routingupdate_t *) GetClearedMemory( - maxreachabilityareas * sizeof(aas_routingupdate_t)); - // - if (aasworld.portalupdate) FreeMemory(aasworld.portalupdate); - //allocate memory for the portal update fields - aasworld.portalupdate = (aas_routingupdate_t *) GetClearedMemory( - (aasworld.numportals+1) * sizeof(aas_routingupdate_t)); -} //end of the function AAS_InitRoutingUpdate -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_CreateAllRoutingCache(void) -{ - int i, j, t; - - aasworld.initialized = qtrue; - botimport.Print(PRT_MESSAGE, "AAS_CreateAllRoutingCache\n"); - for (i = 1; i < aasworld.numareas; i++) - { - if (!AAS_AreaReachability(i)) continue; - for (j = 1; j < aasworld.numareas; j++) - { - if (i == j) continue; - if (!AAS_AreaReachability(j)) continue; - t = AAS_AreaTravelTimeToGoalArea(i, aasworld.areas[i].center, j, TFL_DEFAULT); - //Log_Write("traveltime from %d to %d is %d", i, j, t); - } //end for - } //end for - aasworld.initialized = qfalse; -} //end of the function AAS_CreateAllRoutingCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== - -//the route cache header -//this header is followed by numportalcache + numareacache aas_routingcache_t -//structures that store routing cache -typedef struct routecacheheader_s -{ - int ident; - int version; - int numareas; - int numclusters; - int areacrc; - int clustercrc; - int numportalcache; - int numareacache; -} routecacheheader_t; - -#define RCID (('C'<<24)+('R'<<16)+('E'<<8)+'M') -#define RCVERSION 2 - -//void AAS_DecompressVis(byte *in, int numareas, byte *decompressed); -//int AAS_CompressVis(byte *vis, int numareas, byte *dest); - -void AAS_WriteRouteCache(void) -{ - int i, j, numportalcache, numareacache, totalsize; - aas_routingcache_t *cache; - aas_cluster_t *cluster; - fileHandle_t fp; - char filename[MAX_QPATH]; - routecacheheader_t routecacheheader; - - numportalcache = 0; - for (i = 0; i < aasworld.numareas; i++) - { - for (cache = aasworld.portalcache[i]; cache; cache = cache->next) - { - numportalcache++; - } //end for - } //end for - numareacache = 0; - for (i = 0; i < aasworld.numclusters; i++) - { - cluster = &aasworld.clusters[i]; - for (j = 0; j < cluster->numareas; j++) - { - for (cache = aasworld.clusterareacache[i][j]; cache; cache = cache->next) - { - numareacache++; - } //end for - } //end for - } //end for - // open the file for writing - Com_sprintf(filename, MAX_QPATH, "maps/%s.rcd", aasworld.mapname); - botimport.FS_FOpenFile( filename, &fp, FS_WRITE ); - if (!fp) - { - AAS_Error("Unable to open file: %s\n", filename); - return; - } //end if - //create the header - routecacheheader.ident = RCID; - routecacheheader.version = RCVERSION; - routecacheheader.numareas = aasworld.numareas; - routecacheheader.numclusters = aasworld.numclusters; - routecacheheader.areacrc = CRC_ProcessString( (unsigned char *)aasworld.areas, sizeof(aas_area_t) * aasworld.numareas ); - routecacheheader.clustercrc = CRC_ProcessString( (unsigned char *)aasworld.clusters, sizeof(aas_cluster_t) * aasworld.numclusters ); - routecacheheader.numportalcache = numportalcache; - routecacheheader.numareacache = numareacache; - //write the header - botimport.FS_Write(&routecacheheader, sizeof(routecacheheader_t), fp); - // - totalsize = 0; - //write all the cache - for (i = 0; i < aasworld.numareas; i++) - { - for (cache = aasworld.portalcache[i]; cache; cache = cache->next) - { - botimport.FS_Write(cache, cache->size, fp); - totalsize += cache->size; - } //end for - } //end for - for (i = 0; i < aasworld.numclusters; i++) - { - cluster = &aasworld.clusters[i]; - for (j = 0; j < cluster->numareas; j++) - { - for (cache = aasworld.clusterareacache[i][j]; cache; cache = cache->next) - { - botimport.FS_Write(cache, cache->size, fp); - totalsize += cache->size; - } //end for - } //end for - } //end for - // write the visareas - /* - for (i = 0; i < aasworld.numareas; i++) - { - if (!aasworld.areavisibility[i]) { - size = 0; - botimport.FS_Write(&size, sizeof(int), fp); - continue; - } - AAS_DecompressVis( aasworld.areavisibility[i], aasworld.numareas, aasworld.decompressedvis ); - size = AAS_CompressVis( aasworld.decompressedvis, aasworld.numareas, aasworld.decompressedvis ); - botimport.FS_Write(&size, sizeof(int), fp); - botimport.FS_Write(aasworld.decompressedvis, size, fp); - } - */ - // - botimport.FS_FCloseFile(fp); - botimport.Print(PRT_MESSAGE, "\nroute cache written to %s\n", filename); - botimport.Print(PRT_MESSAGE, "written %d bytes of routing cache\n", totalsize); -} //end of the function AAS_WriteRouteCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -aas_routingcache_t *AAS_ReadCache(fileHandle_t fp) -{ - int size; - aas_routingcache_t *cache; - - botimport.FS_Read(&size, sizeof(size), fp); - cache = (aas_routingcache_t *) GetMemory(size); - cache->size = size; - botimport.FS_Read((unsigned char *)cache + sizeof(size), size - sizeof(size), fp); - cache->reachabilities = (unsigned char *) cache + sizeof(aas_routingcache_t) - sizeof(unsigned short) + - (size - sizeof(aas_routingcache_t) + sizeof(unsigned short)) / 3 * 2; - return cache; -} //end of the function AAS_ReadCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_ReadRouteCache(void) -{ - int i, clusterareanum;//, size; - fileHandle_t fp; - char filename[MAX_QPATH]; - routecacheheader_t routecacheheader; - aas_routingcache_t *cache; - - Com_sprintf(filename, MAX_QPATH, "maps/%s.rcd", aasworld.mapname); - botimport.FS_FOpenFile( filename, &fp, FS_READ ); - if (!fp) - { - return qfalse; - } //end if - botimport.FS_Read(&routecacheheader, sizeof(routecacheheader_t), fp ); - if (routecacheheader.ident != RCID) - { - AAS_Error("%s is not a route cache dump\n"); - return qfalse; - } //end if - if (routecacheheader.version != RCVERSION) - { - AAS_Error("route cache dump has wrong version %d, should be %d", routecacheheader.version, RCVERSION); - return qfalse; - } //end if - if (routecacheheader.numareas != aasworld.numareas) - { - //AAS_Error("route cache dump has wrong number of areas\n"); - return qfalse; - } //end if - if (routecacheheader.numclusters != aasworld.numclusters) - { - //AAS_Error("route cache dump has wrong number of clusters\n"); - return qfalse; - } //end if - if (routecacheheader.areacrc != - CRC_ProcessString( (unsigned char *)aasworld.areas, sizeof(aas_area_t) * aasworld.numareas )) - { - //AAS_Error("route cache dump area CRC incorrect\n"); - return qfalse; - } //end if - if (routecacheheader.clustercrc != - CRC_ProcessString( (unsigned char *)aasworld.clusters, sizeof(aas_cluster_t) * aasworld.numclusters )) - { - //AAS_Error("route cache dump cluster CRC incorrect\n"); - return qfalse; - } //end if - //read all the portal cache - for (i = 0; i < routecacheheader.numportalcache; i++) - { - cache = AAS_ReadCache(fp); - cache->next = aasworld.portalcache[cache->areanum]; - cache->prev = NULL; - if (aasworld.portalcache[cache->areanum]) - aasworld.portalcache[cache->areanum]->prev = cache; - aasworld.portalcache[cache->areanum] = cache; - } //end for - //read all the cluster area cache - for (i = 0; i < routecacheheader.numareacache; i++) - { - cache = AAS_ReadCache(fp); - clusterareanum = AAS_ClusterAreaNum(cache->cluster, cache->areanum); - cache->next = aasworld.clusterareacache[cache->cluster][clusterareanum]; - cache->prev = NULL; - if (aasworld.clusterareacache[cache->cluster][clusterareanum]) - aasworld.clusterareacache[cache->cluster][clusterareanum]->prev = cache; - aasworld.clusterareacache[cache->cluster][clusterareanum] = cache; - } //end for - // read the visareas - /* - aasworld.areavisibility = (byte **) GetClearedMemory(aasworld.numareas * sizeof(byte *)); - aasworld.decompressedvis = (byte *) GetClearedMemory(aasworld.numareas * sizeof(byte)); - for (i = 0; i < aasworld.numareas; i++) - { - botimport.FS_Read(&size, sizeof(size), fp ); - if (size) { - aasworld.areavisibility[i] = (byte *) GetMemory(size); - botimport.FS_Read(aasworld.areavisibility[i], size, fp ); - } - } - */ - // - botimport.FS_FCloseFile(fp); - return qtrue; -} //end of the function AAS_ReadRouteCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -#define MAX_REACHABILITYPASSAREAS 32 - -void AAS_InitReachabilityAreas(void) -{ - int i, j, numareas, areas[MAX_REACHABILITYPASSAREAS]; - int numreachareas; - aas_reachability_t *reach; - vec3_t start, end; - - if (aasworld.reachabilityareas) - FreeMemory(aasworld.reachabilityareas); - if (aasworld.reachabilityareaindex) - FreeMemory(aasworld.reachabilityareaindex); - - aasworld.reachabilityareas = (aas_reachabilityareas_t *) - GetClearedMemory(aasworld.reachabilitysize * sizeof(aas_reachabilityareas_t)); - aasworld.reachabilityareaindex = (int *) - GetClearedMemory(aasworld.reachabilitysize * MAX_REACHABILITYPASSAREAS * sizeof(int)); - numreachareas = 0; - for (i = 0; i < aasworld.reachabilitysize; i++) - { - reach = &aasworld.reachability[i]; - numareas = 0; - switch(reach->traveltype & TRAVELTYPE_MASK) - { - //trace areas from start to end - case TRAVEL_BARRIERJUMP: - case TRAVEL_WATERJUMP: - VectorCopy(reach->start, end); - end[2] = reach->end[2]; - numareas = AAS_TraceAreas(reach->start, end, areas, NULL, MAX_REACHABILITYPASSAREAS); - break; - case TRAVEL_WALKOFFLEDGE: - VectorCopy(reach->end, start); - start[2] = reach->start[2]; - numareas = AAS_TraceAreas(start, reach->end, areas, NULL, MAX_REACHABILITYPASSAREAS); - break; - case TRAVEL_GRAPPLEHOOK: - numareas = AAS_TraceAreas(reach->start, reach->end, areas, NULL, MAX_REACHABILITYPASSAREAS); - break; - - //trace arch - case TRAVEL_JUMP: break; - case TRAVEL_ROCKETJUMP: break; - case TRAVEL_BFGJUMP: break; - case TRAVEL_JUMPPAD: break; - - //trace from reach->start to entity center, along entity movement - //and from entity center to reach->end - case TRAVEL_ELEVATOR: break; - case TRAVEL_FUNCBOB: break; - - //no areas in between - case TRAVEL_WALK: break; - case TRAVEL_CROUCH: break; - case TRAVEL_LADDER: break; - case TRAVEL_SWIM: break; - case TRAVEL_TELEPORT: break; - default: break; - } //end switch - aasworld.reachabilityareas[i].firstarea = numreachareas; - aasworld.reachabilityareas[i].numareas = numareas; - for (j = 0; j < numareas; j++) - { - aasworld.reachabilityareaindex[numreachareas++] = areas[j]; - } //end for - } //end for -} //end of the function AAS_InitReachabilityAreas -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_InitRouting(void) -{ - AAS_InitTravelFlagFromType(); - // - AAS_InitAreaContentsTravelFlags(); - //initialize the routing update fields - AAS_InitRoutingUpdate(); - //create reversed reachability links used by the routing update algorithm - AAS_CreateReversedReachability(); - //initialize the cluster cache - AAS_InitClusterAreaCache(); - //initialize portal cache - AAS_InitPortalCache(); - //initialize the area travel times - AAS_CalculateAreaTravelTimes(); - //calculate the maximum travel times through portals - AAS_InitPortalMaxTravelTimes(); - //get the areas reachabilities go through - AAS_InitReachabilityAreas(); - // -#ifdef ROUTING_DEBUG - numareacacheupdates = 0; - numportalcacheupdates = 0; -#endif //ROUTING_DEBUG - // - routingcachesize = 0; - max_routingcachesize = 1024 * (int) LibVarValue("max_routingcache", "4096"); - // read any routing cache if available - AAS_ReadRouteCache(); -} //end of the function AAS_InitRouting -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_FreeRoutingCaches(void) -{ - // free all the existing cluster area cache - AAS_FreeAllClusterAreaCache(); - // free all the existing portal cache - AAS_FreeAllPortalCache(); - // free cached travel times within areas - if (aasworld.areatraveltimes) FreeMemory(aasworld.areatraveltimes); - aasworld.areatraveltimes = NULL; - // free cached maximum travel time through cluster portals - if (aasworld.portalmaxtraveltimes) FreeMemory(aasworld.portalmaxtraveltimes); - aasworld.portalmaxtraveltimes = NULL; - // free reversed reachability links - if (aasworld.reversedreachability) FreeMemory(aasworld.reversedreachability); - aasworld.reversedreachability = NULL; - // free routing algorithm memory - if (aasworld.areaupdate) FreeMemory(aasworld.areaupdate); - aasworld.areaupdate = NULL; - if (aasworld.portalupdate) FreeMemory(aasworld.portalupdate); - aasworld.portalupdate = NULL; - // free lists with areas the reachabilities go through - if (aasworld.reachabilityareas) FreeMemory(aasworld.reachabilityareas); - aasworld.reachabilityareas = NULL; - // free the reachability area index - if (aasworld.reachabilityareaindex) FreeMemory(aasworld.reachabilityareaindex); - aasworld.reachabilityareaindex = NULL; - // free area contents travel flags look up table - if (aasworld.areacontentstravelflags) FreeMemory(aasworld.areacontentstravelflags); - aasworld.areacontentstravelflags = NULL; -} //end of the function AAS_FreeRoutingCaches -//=========================================================================== -// update the given routing cache -// -// Parameter: areacache : routing cache to update -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_UpdateAreaRoutingCache(aas_routingcache_t *areacache) -{ - int i, nextareanum, cluster, badtravelflags, clusterareanum, linknum; - int numreachabilityareas; - unsigned short int t, startareatraveltimes[128]; //NOTE: not more than 128 reachabilities per area allowed - aas_routingupdate_t *updateliststart, *updatelistend, *curupdate, *nextupdate; - aas_reachability_t *reach; - aas_reversedreachability_t *revreach; - aas_reversedlink_t *revlink; - -#ifdef ROUTING_DEBUG - numareacacheupdates++; -#endif //ROUTING_DEBUG - //number of reachability areas within this cluster - numreachabilityareas = aasworld.clusters[areacache->cluster].numreachabilityareas; - // - aasworld.frameroutingupdates++; - //clear the routing update fields -// Com_Memset(aasworld.areaupdate, 0, aasworld.numareas * sizeof(aas_routingupdate_t)); - // - badtravelflags = ~areacache->travelflags; - // - clusterareanum = AAS_ClusterAreaNum(areacache->cluster, areacache->areanum); - if (clusterareanum >= numreachabilityareas) return; - // - Com_Memset(startareatraveltimes, 0, sizeof(startareatraveltimes)); - // - curupdate = &aasworld.areaupdate[clusterareanum]; - curupdate->areanum = areacache->areanum; - //VectorCopy(areacache->origin, curupdate->start); - curupdate->areatraveltimes = startareatraveltimes; - curupdate->tmptraveltime = areacache->starttraveltime; - // - areacache->traveltimes[clusterareanum] = areacache->starttraveltime; - //put the area to start with in the current read list - curupdate->next = NULL; - curupdate->prev = NULL; - updateliststart = curupdate; - updatelistend = curupdate; - //while there are updates in the current list - while (updateliststart) - { - curupdate = updateliststart; - // - if (curupdate->next) curupdate->next->prev = NULL; - else updatelistend = NULL; - updateliststart = curupdate->next; - // - curupdate->inlist = qfalse; - //check all reversed reachability links - revreach = &aasworld.reversedreachability[curupdate->areanum]; - // - for (i = 0, revlink = revreach->first; revlink; revlink = revlink->next, i++) - { - linknum = revlink->linknum; - reach = &aasworld.reachability[linknum]; - //if there is used an undesired travel type - if (AAS_TravelFlagForType_inline(reach->traveltype) & badtravelflags) continue; - //if not allowed to enter the next area - if (aasworld.areasettings[reach->areanum].areaflags & AREA_DISABLED) continue; - //if the next area has a not allowed travel flag - if (AAS_AreaContentsTravelFlags_inline(reach->areanum) & badtravelflags) continue; - //number of the area the reversed reachability leads to - nextareanum = revlink->areanum; - //get the cluster number of the area - cluster = aasworld.areasettings[nextareanum].cluster; - //don't leave the cluster - if (cluster > 0 && cluster != areacache->cluster) continue; - //get the number of the area in the cluster - clusterareanum = AAS_ClusterAreaNum(areacache->cluster, nextareanum); - if (clusterareanum >= numreachabilityareas) continue; - //time already travelled plus the traveltime through - //the current area plus the travel time from the reachability - t = curupdate->tmptraveltime + - //AAS_AreaTravelTime(curupdate->areanum, curupdate->start, reach->end) + - curupdate->areatraveltimes[i] + - reach->traveltime; - // - if (!areacache->traveltimes[clusterareanum] || - areacache->traveltimes[clusterareanum] > t) - { - areacache->traveltimes[clusterareanum] = t; - areacache->reachabilities[clusterareanum] = linknum - aasworld.areasettings[nextareanum].firstreachablearea; - nextupdate = &aasworld.areaupdate[clusterareanum]; - nextupdate->areanum = nextareanum; - nextupdate->tmptraveltime = t; - //VectorCopy(reach->start, nextupdate->start); - nextupdate->areatraveltimes = aasworld.areatraveltimes[nextareanum][linknum - - aasworld.areasettings[nextareanum].firstreachablearea]; - if (!nextupdate->inlist) - { - // we add the update to the end of the list - // we could also use a B+ tree to have a real sorted list - // on travel time which makes for faster routing updates - nextupdate->next = NULL; - nextupdate->prev = updatelistend; - if (updatelistend) updatelistend->next = nextupdate; - else updateliststart = nextupdate; - updatelistend = nextupdate; - nextupdate->inlist = qtrue; - } //end if - } //end if - } //end for - } //end while -} //end of the function AAS_UpdateAreaRoutingCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -aas_routingcache_t *AAS_GetAreaRoutingCache(int clusternum, int areanum, int travelflags) -{ - int clusterareanum; - aas_routingcache_t *cache, *clustercache; - - //number of the area in the cluster - clusterareanum = AAS_ClusterAreaNum(clusternum, areanum); - //pointer to the cache for the area in the cluster - clustercache = aasworld.clusterareacache[clusternum][clusterareanum]; - //find the cache without undesired travel flags - for (cache = clustercache; cache; cache = cache->next) - { - //if there aren't used any undesired travel types for the cache - if (cache->travelflags == travelflags) break; - } //end for - //if there was no cache - if (!cache) - { - cache = AAS_AllocRoutingCache(aasworld.clusters[clusternum].numreachabilityareas); - cache->cluster = clusternum; - cache->areanum = areanum; - VectorCopy(aasworld.areas[areanum].center, cache->origin); - cache->starttraveltime = 1; - cache->travelflags = travelflags; - cache->prev = NULL; - cache->next = clustercache; - if (clustercache) clustercache->prev = cache; - aasworld.clusterareacache[clusternum][clusterareanum] = cache; - AAS_UpdateAreaRoutingCache(cache); - } //end if - else - { - AAS_UnlinkCache(cache); - } //end else - //the cache has been accessed - cache->time = AAS_RoutingTime(); - cache->type = CACHETYPE_AREA; - AAS_LinkCache(cache); - return cache; -} //end of the function AAS_GetAreaRoutingCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_UpdatePortalRoutingCache(aas_routingcache_t *portalcache) -{ - int i, portalnum, clusterareanum, clusternum; - unsigned short int t; - aas_portal_t *portal; - aas_cluster_t *cluster; - aas_routingcache_t *cache; - aas_routingupdate_t *updateliststart, *updatelistend, *curupdate, *nextupdate; - -#ifdef ROUTING_DEBUG - numportalcacheupdates++; -#endif //ROUTING_DEBUG - //clear the routing update fields -// Com_Memset(aasworld.portalupdate, 0, (aasworld.numportals+1) * sizeof(aas_routingupdate_t)); - // - curupdate = &aasworld.portalupdate[aasworld.numportals]; - curupdate->cluster = portalcache->cluster; - curupdate->areanum = portalcache->areanum; - curupdate->tmptraveltime = portalcache->starttraveltime; - //if the start area is a cluster portal, store the travel time for that portal - clusternum = aasworld.areasettings[portalcache->areanum].cluster; - if (clusternum < 0) - { - portalcache->traveltimes[-clusternum] = portalcache->starttraveltime; - } //end if - //put the area to start with in the current read list - curupdate->next = NULL; - curupdate->prev = NULL; - updateliststart = curupdate; - updatelistend = curupdate; - //while there are updates in the current list - while (updateliststart) - { - curupdate = updateliststart; - //remove the current update from the list - if (curupdate->next) curupdate->next->prev = NULL; - else updatelistend = NULL; - updateliststart = curupdate->next; - //current update is removed from the list - curupdate->inlist = qfalse; - // - cluster = &aasworld.clusters[curupdate->cluster]; - // - cache = AAS_GetAreaRoutingCache(curupdate->cluster, - curupdate->areanum, portalcache->travelflags); - //take all portals of the cluster - for (i = 0; i < cluster->numportals; i++) - { - portalnum = aasworld.portalindex[cluster->firstportal + i]; - portal = &aasworld.portals[portalnum]; - //if this is the portal of the current update continue - if (portal->areanum == curupdate->areanum) continue; - // - clusterareanum = AAS_ClusterAreaNum(curupdate->cluster, portal->areanum); - if (clusterareanum >= cluster->numreachabilityareas) continue; - // - t = cache->traveltimes[clusterareanum]; - if (!t) continue; - t += curupdate->tmptraveltime; - // - if (!portalcache->traveltimes[portalnum] || - portalcache->traveltimes[portalnum] > t) - { - portalcache->traveltimes[portalnum] = t; - nextupdate = &aasworld.portalupdate[portalnum]; - if (portal->frontcluster == curupdate->cluster) - { - nextupdate->cluster = portal->backcluster; - } //end if - else - { - nextupdate->cluster = portal->frontcluster; - } //end else - nextupdate->areanum = portal->areanum; - //add travel time through the actual portal area for the next update - nextupdate->tmptraveltime = t + aasworld.portalmaxtraveltimes[portalnum]; - if (!nextupdate->inlist) - { - // we add the update to the end of the list - // we could also use a B+ tree to have a real sorted list - // on travel time which makes for faster routing updates - nextupdate->next = NULL; - nextupdate->prev = updatelistend; - if (updatelistend) updatelistend->next = nextupdate; - else updateliststart = nextupdate; - updatelistend = nextupdate; - nextupdate->inlist = qtrue; - } //end if - } //end if - } //end for - } //end while -} //end of the function AAS_UpdatePortalRoutingCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -aas_routingcache_t *AAS_GetPortalRoutingCache(int clusternum, int areanum, int travelflags) -{ - aas_routingcache_t *cache; - - //find the cached portal routing if existing - for (cache = aasworld.portalcache[areanum]; cache; cache = cache->next) - { - if (cache->travelflags == travelflags) break; - } //end for - //if the portal routing isn't cached - if (!cache) - { - cache = AAS_AllocRoutingCache(aasworld.numportals); - cache->cluster = clusternum; - cache->areanum = areanum; - VectorCopy(aasworld.areas[areanum].center, cache->origin); - cache->starttraveltime = 1; - cache->travelflags = travelflags; - //add the cache to the cache list - cache->prev = NULL; - cache->next = aasworld.portalcache[areanum]; - if (aasworld.portalcache[areanum]) aasworld.portalcache[areanum]->prev = cache; - aasworld.portalcache[areanum] = cache; - //update the cache - AAS_UpdatePortalRoutingCache(cache); - } //end if - else - { - AAS_UnlinkCache(cache); - } //end else - //the cache has been accessed - cache->time = AAS_RoutingTime(); - cache->type = CACHETYPE_PORTAL; - AAS_LinkCache(cache); - return cache; -} //end of the function AAS_GetPortalRoutingCache -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_AreaRouteToGoalArea(int areanum, vec3_t origin, int goalareanum, int travelflags, int *traveltime, int *reachnum) -{ - int clusternum, goalclusternum, portalnum, i, clusterareanum, bestreachnum; - unsigned short int t, besttime; - aas_portal_t *portal; - aas_cluster_t *cluster; - aas_routingcache_t *areacache, *portalcache; - aas_reachability_t *reach; - - if (!aasworld.initialized) return qfalse; - - if (areanum == goalareanum) - { - *traveltime = 1; - *reachnum = 0; - return qtrue; - } - // - if (areanum <= 0 || areanum >= aasworld.numareas) - { - if (bot_developer) - { - botimport.Print(PRT_ERROR, "AAS_AreaTravelTimeToGoalArea: areanum %d out of range\n", areanum); - } //end if - return qfalse; - } //end if - if (goalareanum <= 0 || goalareanum >= aasworld.numareas) - { - if (bot_developer) - { - botimport.Print(PRT_ERROR, "AAS_AreaTravelTimeToGoalArea: goalareanum %d out of range\n", goalareanum); - } //end if - return qfalse; - } //end if - // make sure the routing cache doesn't grow to large - while(AvailableMemory() < 1 * 1024 * 1024) { - if (!AAS_FreeOldestCache()) break; - } - // - if (AAS_AreaDoNotEnter(areanum) || AAS_AreaDoNotEnter(goalareanum)) - { - travelflags |= TFL_DONOTENTER; - } //end if - //NOTE: the number of routing updates is limited per frame - /* - if (aasworld.frameroutingupdates > MAX_FRAMEROUTINGUPDATES) - { -#ifdef DEBUG - //Log_Write("WARNING: AAS_AreaTravelTimeToGoalArea: frame routing updates overflowed"); -#endif - return 0; - } //end if - */ - // - clusternum = aasworld.areasettings[areanum].cluster; - goalclusternum = aasworld.areasettings[goalareanum].cluster; - //check if the area is a portal of the goal area cluster - if (clusternum < 0 && goalclusternum > 0) - { - portal = &aasworld.portals[-clusternum]; - if (portal->frontcluster == goalclusternum || - portal->backcluster == goalclusternum) - { - clusternum = goalclusternum; - } //end if - } //end if - //check if the goalarea is a portal of the area cluster - else if (clusternum > 0 && goalclusternum < 0) - { - portal = &aasworld.portals[-goalclusternum]; - if (portal->frontcluster == clusternum || - portal->backcluster == clusternum) - { - goalclusternum = clusternum; - } //end if - } //end if - //if both areas are in the same cluster - //NOTE: there might be a shorter route via another cluster!!! but we don't care - if (clusternum > 0 && goalclusternum > 0 && clusternum == goalclusternum) - { - // - areacache = AAS_GetAreaRoutingCache(clusternum, goalareanum, travelflags); - //the number of the area in the cluster - clusterareanum = AAS_ClusterAreaNum(clusternum, areanum); - //the cluster the area is in - cluster = &aasworld.clusters[clusternum]; - //if the area is NOT a reachability area - if (clusterareanum >= cluster->numreachabilityareas) return 0; - //if it is possible to travel to the goal area through this cluster - if (areacache->traveltimes[clusterareanum] != 0) - { - *reachnum = aasworld.areasettings[areanum].firstreachablearea + - areacache->reachabilities[clusterareanum]; - if (!origin) { - *traveltime = areacache->traveltimes[clusterareanum]; - return qtrue; - } - reach = &aasworld.reachability[*reachnum]; - *traveltime = areacache->traveltimes[clusterareanum] + - AAS_AreaTravelTime(areanum, origin, reach->start); - // - return qtrue; - } //end if - } //end if - // - clusternum = aasworld.areasettings[areanum].cluster; - goalclusternum = aasworld.areasettings[goalareanum].cluster; - //if the goal area is a portal - if (goalclusternum < 0) - { - //just assume the goal area is part of the front cluster - portal = &aasworld.portals[-goalclusternum]; - goalclusternum = portal->frontcluster; - } //end if - //get the portal routing cache - portalcache = AAS_GetPortalRoutingCache(goalclusternum, goalareanum, travelflags); - //if the area is a cluster portal, read directly from the portal cache - if (clusternum < 0) - { - *traveltime = portalcache->traveltimes[-clusternum]; - *reachnum = aasworld.areasettings[areanum].firstreachablearea + - portalcache->reachabilities[-clusternum]; - return qtrue; - } //end if - // - besttime = 0; - bestreachnum = -1; - //the cluster the area is in - cluster = &aasworld.clusters[clusternum]; - //find the portal of the area cluster leading towards the goal area - for (i = 0; i < cluster->numportals; i++) - { - portalnum = aasworld.portalindex[cluster->firstportal + i]; - //if the goal area isn't reachable from the portal - if (!portalcache->traveltimes[portalnum]) continue; - // - portal = &aasworld.portals[portalnum]; - //get the cache of the portal area - areacache = AAS_GetAreaRoutingCache(clusternum, portal->areanum, travelflags); - //current area inside the current cluster - clusterareanum = AAS_ClusterAreaNum(clusternum, areanum); - //if the area is NOT a reachability area - if (clusterareanum >= cluster->numreachabilityareas) continue; - //if the portal is NOT reachable from this area - if (!areacache->traveltimes[clusterareanum]) continue; - //total travel time is the travel time the portal area is from - //the goal area plus the travel time towards the portal area - t = portalcache->traveltimes[portalnum] + areacache->traveltimes[clusterareanum]; - //FIXME: add the exact travel time through the actual portal area - //NOTE: for now we just add the largest travel time through the portal area - // because we can't directly calculate the exact travel time - // to be more specific we don't know which reachability was used to travel - // into the portal area - t += aasworld.portalmaxtraveltimes[portalnum]; - // - if (origin) - { - *reachnum = aasworld.areasettings[areanum].firstreachablearea + - areacache->reachabilities[clusterareanum]; - reach = aasworld.reachability + *reachnum; - t += AAS_AreaTravelTime(areanum, origin, reach->start); - } //end if - //if the time is better than the one already found - if (!besttime || t < besttime) - { - bestreachnum = *reachnum; - besttime = t; - } //end if - } //end for - if (bestreachnum < 0) { - return qfalse; - } - *reachnum = bestreachnum; - *traveltime = besttime; - return qtrue; -} //end of the function AAS_AreaRouteToGoalArea -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_AreaTravelTimeToGoalArea(int areanum, vec3_t origin, int goalareanum, int travelflags) -{ - int traveltime, reachnum; - - if (AAS_AreaRouteToGoalArea(areanum, origin, goalareanum, travelflags, &traveltime, &reachnum)) - { - return traveltime; - } - return 0; -} //end of the function AAS_AreaTravelTimeToGoalArea -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_AreaReachabilityToGoalArea(int areanum, vec3_t origin, int goalareanum, int travelflags) -{ - int traveltime, reachnum; - - if (AAS_AreaRouteToGoalArea(areanum, origin, goalareanum, travelflags, &traveltime, &reachnum)) - { - return reachnum; - } - return 0; -} //end of the function AAS_AreaReachabilityToGoalArea -//=========================================================================== -// predict the route and stop on one of the stop events -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_PredictRoute(struct aas_predictroute_s *route, int areanum, vec3_t origin, - int goalareanum, int travelflags, int maxareas, int maxtime, - int stopevent, int stopcontents, int stoptfl, int stopareanum) -{ - int curareanum, reachnum, i, j, testareanum; - vec3_t curorigin; - aas_reachability_t *reach; - aas_reachabilityareas_t *reachareas; - - //init output - route->stopevent = RSE_NONE; - route->endarea = goalareanum; - route->endcontents = 0; - route->endtravelflags = 0; - VectorCopy(origin, route->endpos); - route->time = 0; - - curareanum = areanum; - VectorCopy(origin, curorigin); - - for (i = 0; curareanum != goalareanum && (!maxareas || i < maxareas) && i < aasworld.numareas; i++) - { - reachnum = AAS_AreaReachabilityToGoalArea(curareanum, curorigin, goalareanum, travelflags); - if (!reachnum) - { - route->stopevent = RSE_NOROUTE; - return qfalse; - } //end if - reach = &aasworld.reachability[reachnum]; - // - if (stopevent & RSE_USETRAVELTYPE) - { - if (AAS_TravelFlagForType_inline(reach->traveltype) & stoptfl) - { - route->stopevent = RSE_USETRAVELTYPE; - route->endarea = curareanum; - route->endcontents = aasworld.areasettings[curareanum].contents; - route->endtravelflags = AAS_TravelFlagForType_inline(reach->traveltype); - VectorCopy(reach->start, route->endpos); - return qtrue; - } //end if - if (AAS_AreaContentsTravelFlags_inline(reach->areanum) & stoptfl) - { - route->stopevent = RSE_USETRAVELTYPE; - route->endarea = reach->areanum; - route->endcontents = aasworld.areasettings[reach->areanum].contents; - route->endtravelflags = AAS_AreaContentsTravelFlags_inline(reach->areanum); - VectorCopy(reach->end, route->endpos); - route->time += AAS_AreaTravelTime(areanum, origin, reach->start); - route->time += reach->traveltime; - return qtrue; - } //end if - } //end if - reachareas = &aasworld.reachabilityareas[reachnum]; - for (j = 0; j < reachareas->numareas + 1; j++) - { - if (j >= reachareas->numareas) - testareanum = reach->areanum; - else - testareanum = aasworld.reachabilityareaindex[reachareas->firstarea + j]; - if (stopevent & RSE_ENTERCONTENTS) - { - if (aasworld.areasettings[testareanum].contents & stopcontents) - { - route->stopevent = RSE_ENTERCONTENTS; - route->endarea = testareanum; - route->endcontents = aasworld.areasettings[testareanum].contents; - VectorCopy(reach->end, route->endpos); - route->time += AAS_AreaTravelTime(areanum, origin, reach->start); - route->time += reach->traveltime; - return qtrue; - } //end if - } //end if - if (stopevent & RSE_ENTERAREA) - { - if (testareanum == stopareanum) - { - route->stopevent = RSE_ENTERAREA; - route->endarea = testareanum; - route->endcontents = aasworld.areasettings[testareanum].contents; - VectorCopy(reach->start, route->endpos); - return qtrue; - } //end if - } //end if - } //end for - - route->time += AAS_AreaTravelTime(areanum, origin, reach->start); - route->time += reach->traveltime; - route->endarea = reach->areanum; - route->endcontents = aasworld.areasettings[reach->areanum].contents; - route->endtravelflags = AAS_TravelFlagForType_inline(reach->traveltype); - VectorCopy(reach->end, route->endpos); - // - curareanum = reach->areanum; - VectorCopy(reach->end, curorigin); - // - if (maxtime && route->time > maxtime) - break; - } //end while - if (curareanum != goalareanum) - return qfalse; - return qtrue; -} //end of the function AAS_PredictRoute -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_BridgeWalkable(int areanum) -{ - return qfalse; -} //end of the function AAS_BridgeWalkable -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -void AAS_ReachabilityFromNum(int num, struct aas_reachability_s *reach) -{ - if (!aasworld.initialized) - { - Com_Memset(reach, 0, sizeof(aas_reachability_t)); - return; - } //end if - if (num < 0 || num >= aasworld.reachabilitysize) - { - Com_Memset(reach, 0, sizeof(aas_reachability_t)); - return; - } //end if - Com_Memcpy(reach, &aasworld.reachability[num], sizeof(aas_reachability_t));; -} //end of the function AAS_ReachabilityFromNum -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_NextAreaReachability(int areanum, int reachnum) -{ - aas_areasettings_t *settings; - - if (!aasworld.initialized) return 0; - - if (areanum <= 0 || areanum >= aasworld.numareas) - { - botimport.Print(PRT_ERROR, "AAS_NextAreaReachability: areanum %d out of range\n", areanum); - return 0; - } //end if - - settings = &aasworld.areasettings[areanum]; - if (!reachnum) - { - return settings->firstreachablearea; - } //end if - if (reachnum < settings->firstreachablearea) - { - botimport.Print(PRT_FATAL, "AAS_NextAreaReachability: reachnum < settings->firstreachableara"); - return 0; - } //end if - reachnum++; - if (reachnum >= settings->firstreachablearea + settings->numreachableareas) - { - return 0; - } //end if - return reachnum; -} //end of the function AAS_NextAreaReachability -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_NextModelReachability(int num, int modelnum) -{ - int i; - - if (num <= 0) num = 1; - else if (num >= aasworld.reachabilitysize) return 0; - else num++; - // - for (i = num; i < aasworld.reachabilitysize; i++) - { - if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == TRAVEL_ELEVATOR) - { - if (aasworld.reachability[i].facenum == modelnum) return i; - } //end if - else if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == TRAVEL_FUNCBOB) - { - if ((aasworld.reachability[i].facenum & 0x0000FFFF) == modelnum) return i; - } //end if - } //end for - return 0; -} //end of the function AAS_NextModelReachability -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_RandomGoalArea(int areanum, int travelflags, int *goalareanum, vec3_t goalorigin) -{ - int i, n, t; - vec3_t start, end; - aas_trace_t trace; - - //if the area has no reachabilities - if (!AAS_AreaReachability(areanum)) return qfalse; - // - n = aasworld.numareas * random(); - for (i = 0; i < aasworld.numareas; i++) - { - if (n <= 0) n = 1; - if (n >= aasworld.numareas) n = 1; - if (AAS_AreaReachability(n)) - { - t = AAS_AreaTravelTimeToGoalArea(areanum, aasworld.areas[areanum].center, n, travelflags); - //if the goal is reachable - if (t > 0) - { - if (AAS_AreaSwim(n)) - { - *goalareanum = n; - VectorCopy(aasworld.areas[n].center, goalorigin); - //botimport.Print(PRT_MESSAGE, "found random goal area %d\n", *goalareanum); - return qtrue; - } //end if - VectorCopy(aasworld.areas[n].center, start); - if (!AAS_PointAreaNum(start)) - Log_Write("area %d center %f %f %f in solid?", n, start[0], start[1], start[2]); - VectorCopy(start, end); - end[2] -= 300; - trace = AAS_TraceClientBBox(start, end, PRESENCE_CROUCH, -1); - if (!trace.startsolid && trace.fraction < 1 && AAS_PointAreaNum(trace.endpos) == n) - { - if (AAS_AreaGroundFaceArea(n) > 300) - { - *goalareanum = n; - VectorCopy(trace.endpos, goalorigin); - //botimport.Print(PRT_MESSAGE, "found random goal area %d\n", *goalareanum); - return qtrue; - } //end if - } //end if - } //end if - } //end if - n++; - } //end for - return qfalse; -} //end of the function AAS_RandomGoalArea -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_AreaVisible(int srcarea, int destarea) -{ - return qfalse; -} //end of the function AAS_AreaVisible -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -float DistancePointToLine(vec3_t v1, vec3_t v2, vec3_t point) -{ - vec3_t vec, p2; - - AAS_ProjectPointOntoVector(point, v1, v2, p2); - VectorSubtract(point, p2, vec); - return VectorLength(vec); -} //end of the function DistancePointToLine -//=========================================================================== -// -// Parameter: - -// Returns: - -// Changes Globals: - -//=========================================================================== -int AAS_NearestHideArea(int srcnum, vec3_t origin, int areanum, int enemynum, vec3_t enemyorigin, int enemyareanum, int travelflags) -{ - int i, j, nextareanum, badtravelflags, numreach, bestarea; - unsigned short int t, besttraveltime; - static unsigned short int *hidetraveltimes; - aas_routingupdate_t *updateliststart, *updatelistend, *curupdate, *nextupdate; - aas_reachability_t *reach; - float dist1, dist2; - vec3_t v1, v2, p; - qboolean startVisible; - - // - if (!hidetraveltimes) - { - hidetraveltimes = (unsigned short int *) GetClearedMemory(aasworld.numareas * sizeof(unsigned short int)); - } //end if - else - { - Com_Memset(hidetraveltimes, 0, aasworld.numareas * sizeof(unsigned short int)); - } //end else - besttraveltime = 0; - bestarea = 0; - //assume visible - startVisible = qtrue; - // - badtravelflags = ~travelflags; - // - curupdate = &aasworld.areaupdate[areanum]; - curupdate->areanum = areanum; - VectorCopy(origin, curupdate->start); - curupdate->areatraveltimes = aasworld.areatraveltimes[areanum][0]; - curupdate->tmptraveltime = 0; - //put the area to start with in the current read list - curupdate->next = NULL; - curupdate->prev = NULL; - updateliststart = curupdate; - updatelistend = curupdate; - //while there are updates in the list - while (updateliststart) - { - curupdate = updateliststart; - // - if (curupdate->next) curupdate->next->prev = NULL; - else updatelistend = NULL; - updateliststart = curupdate->next; - // - curupdate->inlist = qfalse; - //check all reversed reachability links - numreach = aasworld.areasettings[curupdate->areanum].numreachableareas; - reach = &aasworld.reachability[aasworld.areasettings[curupdate->areanum].firstreachablearea]; - // - for (i = 0; i < numreach; i++, reach++) - { - //if an undesired travel type is used - if (AAS_TravelFlagForType_inline(reach->traveltype) & badtravelflags) continue; - // - if (AAS_AreaContentsTravelFlags_inline(reach->areanum) & badtravelflags) continue; - //number of the area the reachability leads to - nextareanum = reach->areanum; - // if this moves us into the enemies area, skip it - if (nextareanum == enemyareanum) continue; - //time already travelled plus the traveltime through - //the current area plus the travel time from the reachability - t = curupdate->tmptraveltime + - AAS_AreaTravelTime(curupdate->areanum, curupdate->start, reach->start) + - reach->traveltime; - - //avoid going near the enemy - AAS_ProjectPointOntoVector(enemyorigin, curupdate->start, reach->end, p); - for (j = 0; j < 3; j++) - if ((p[j] > curupdate->start[j] && p[j] > reach->end[j]) || - (p[j] < curupdate->start[j] && p[j] < reach->end[j])) - break; - if (j < 3) - { - VectorSubtract(enemyorigin, reach->end, v2); - } //end if - else - { - VectorSubtract(enemyorigin, p, v2); - } //end else - dist2 = VectorLength(v2); - //never go through the enemy - if (dist2 < 40) continue; - // - VectorSubtract(enemyorigin, curupdate->start, v1); - dist1 = VectorLength(v1); - // - if (dist2 < dist1) - { - t += (dist1 - dist2) * 10; - } - // if we weren't visible when starting, make sure we don't move into their view - if (!startVisible && AAS_AreaVisible(enemyareanum, nextareanum)) { - continue; - } - // - if (besttraveltime && t >= besttraveltime) continue; - // - if (!hidetraveltimes[nextareanum] || - hidetraveltimes[nextareanum] > t) - { - //if the nextarea is not visible from the enemy area - if (!AAS_AreaVisible(enemyareanum, nextareanum)) - { - besttraveltime = t; - bestarea = nextareanum; - } //end if - hidetraveltimes[nextareanum] = t; - nextupdate = &aasworld.areaupdate[nextareanum]; - nextupdate->areanum = nextareanum; - nextupdate->tmptraveltime = t; - //remember where we entered this area - VectorCopy(reach->end, nextupdate->start); - //if this update is not in the list yet - if (!nextupdate->inlist) - { - //add the new update to the end of the list - nextupdate->next = NULL; - nextupdate->prev = updatelistend; - if (updatelistend) updatelistend->next = nextupdate; - else updateliststart = nextupdate; - updatelistend = nextupdate; - nextupdate->inlist = qtrue; - } //end if - } //end if - } //end for - } //end while - return bestarea; -} //end of the function AAS_NearestHideArea |