00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "../game/q_shared.h"
00033 #include "l_utils.h"
00034 #include "l_memory.h"
00035 #include "l_log.h"
00036 #include "l_crc.h"
00037 #include "l_libvar.h"
00038 #include "l_script.h"
00039 #include "l_precomp.h"
00040 #include "l_struct.h"
00041 #include "aasfile.h"
00042 #include "../game/botlib.h"
00043 #include "../game/be_aas.h"
00044 #include "be_aas_funcs.h"
00045 #include "be_interface.h"
00046 #include "be_aas_def.h"
00047
00048 #define ROUTING_DEBUG
00049
00050
00051 #define DISTANCEFACTOR_CROUCH 1.3f //crouch speed = 100
00052 #define DISTANCEFACTOR_SWIM 1 //should be 0.66, swim speed = 150
00053 #define DISTANCEFACTOR_WALK 0.33f //walk speed = 300
00054
00055
00056 #define CACHE_REFRESHTIME 15.0f //15 seconds refresh time
00057
00058
00059 #define MAX_FRAMEROUTINGUPDATES 10
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 #ifdef ROUTING_DEBUG
00080 int numareacacheupdates;
00081 int numportalcacheupdates;
00082 #endif //ROUTING_DEBUG
00083
00084 int routingcachesize;
00085 int max_routingcachesize;
00086
00087
00088
00089
00090
00091
00092
00093 #ifdef ROUTING_DEBUG
00094 void AAS_RoutingInfo(void)
00095 {
00096 botimport.Print(PRT_MESSAGE, "%d area cache updates\n", numareacacheupdates);
00097 botimport.Print(PRT_MESSAGE, "%d portal cache updates\n", numportalcacheupdates);
00098 botimport.Print(PRT_MESSAGE, "%d bytes routing cache\n", routingcachesize);
00099 }
00100 #endif //ROUTING_DEBUG
00101
00102
00103
00104
00105
00106
00107
00108
00109 __inline int AAS_ClusterAreaNum(int cluster, int areanum)
00110 {
00111 int side, areacluster;
00112
00113 areacluster = aasworld.areasettings[areanum].cluster;
00114 if (areacluster > 0) return aasworld.areasettings[areanum].clusterareanum;
00115 else
00116 {
00117
00118
00119
00120
00121
00122
00123
00124
00125 side = aasworld.portals[-areacluster].frontcluster != cluster;
00126 return aasworld.portals[-areacluster].clusterareanum[side];
00127 }
00128 }
00129
00130
00131
00132
00133
00134
00135 void AAS_InitTravelFlagFromType(void)
00136 {
00137 int i;
00138
00139 for (i = 0; i < MAX_TRAVELTYPES; i++)
00140 {
00141 aasworld.travelflagfortype[i] = TFL_INVALID;
00142 }
00143 aasworld.travelflagfortype[TRAVEL_INVALID] = TFL_INVALID;
00144 aasworld.travelflagfortype[TRAVEL_WALK] = TFL_WALK;
00145 aasworld.travelflagfortype[TRAVEL_CROUCH] = TFL_CROUCH;
00146 aasworld.travelflagfortype[TRAVEL_BARRIERJUMP] = TFL_BARRIERJUMP;
00147 aasworld.travelflagfortype[TRAVEL_JUMP] = TFL_JUMP;
00148 aasworld.travelflagfortype[TRAVEL_LADDER] = TFL_LADDER;
00149 aasworld.travelflagfortype[TRAVEL_WALKOFFLEDGE] = TFL_WALKOFFLEDGE;
00150 aasworld.travelflagfortype[TRAVEL_SWIM] = TFL_SWIM;
00151 aasworld.travelflagfortype[TRAVEL_WATERJUMP] = TFL_WATERJUMP;
00152 aasworld.travelflagfortype[TRAVEL_TELEPORT] = TFL_TELEPORT;
00153 aasworld.travelflagfortype[TRAVEL_ELEVATOR] = TFL_ELEVATOR;
00154 aasworld.travelflagfortype[TRAVEL_ROCKETJUMP] = TFL_ROCKETJUMP;
00155 aasworld.travelflagfortype[TRAVEL_BFGJUMP] = TFL_BFGJUMP;
00156 aasworld.travelflagfortype[TRAVEL_GRAPPLEHOOK] = TFL_GRAPPLEHOOK;
00157 aasworld.travelflagfortype[TRAVEL_DOUBLEJUMP] = TFL_DOUBLEJUMP;
00158 aasworld.travelflagfortype[TRAVEL_RAMPJUMP] = TFL_RAMPJUMP;
00159 aasworld.travelflagfortype[TRAVEL_STRAFEJUMP] = TFL_STRAFEJUMP;
00160 aasworld.travelflagfortype[TRAVEL_JUMPPAD] = TFL_JUMPPAD;
00161 aasworld.travelflagfortype[TRAVEL_FUNCBOB] = TFL_FUNCBOB;
00162 }
00163
00164
00165
00166
00167
00168
00169 __inline int AAS_TravelFlagForType_inline(int traveltype)
00170 {
00171 int tfl;
00172
00173 tfl = 0;
00174 if (tfl & TRAVELFLAG_NOTTEAM1)
00175 tfl |= TFL_NOTTEAM1;
00176 if (tfl & TRAVELFLAG_NOTTEAM2)
00177 tfl |= TFL_NOTTEAM2;
00178 traveltype &= TRAVELTYPE_MASK;
00179 if (traveltype < 0 || traveltype >= MAX_TRAVELTYPES)
00180 return TFL_INVALID;
00181 tfl |= aasworld.travelflagfortype[traveltype];
00182 return tfl;
00183 }
00184
00185
00186
00187
00188
00189
00190 int AAS_TravelFlagForType(int traveltype)
00191 {
00192 return AAS_TravelFlagForType_inline(traveltype);
00193 }
00194
00195
00196
00197
00198
00199
00200 void AAS_UnlinkCache(aas_routingcache_t *cache)
00201 {
00202 if (cache->time_next) cache->time_next->time_prev = cache->time_prev;
00203 else aasworld.newestcache = cache->time_prev;
00204 if (cache->time_prev) cache->time_prev->time_next = cache->time_next;
00205 else aasworld.oldestcache = cache->time_next;
00206 cache->time_next = NULL;
00207 cache->time_prev = NULL;
00208 }
00209
00210
00211
00212
00213
00214
00215 void AAS_LinkCache(aas_routingcache_t *cache)
00216 {
00217 if (aasworld.newestcache)
00218 {
00219 aasworld.newestcache->time_next = cache;
00220 cache->time_prev = aasworld.newestcache;
00221 }
00222 else
00223 {
00224 aasworld.oldestcache = cache;
00225 cache->time_prev = NULL;
00226 }
00227 cache->time_next = NULL;
00228 aasworld.newestcache = cache;
00229 }
00230
00231
00232
00233
00234
00235
00236 void AAS_FreeRoutingCache(aas_routingcache_t *cache)
00237 {
00238 AAS_UnlinkCache(cache);
00239 routingcachesize -= cache->size;
00240 FreeMemory(cache);
00241 }
00242
00243
00244
00245
00246
00247
00248 void AAS_RemoveRoutingCacheInCluster( int clusternum )
00249 {
00250 int i;
00251 aas_routingcache_t *cache, *nextcache;
00252 aas_cluster_t *cluster;
00253
00254 if (!aasworld.clusterareacache)
00255 return;
00256 cluster = &aasworld.clusters[clusternum];
00257 for (i = 0; i < cluster->numareas; i++)
00258 {
00259 for (cache = aasworld.clusterareacache[clusternum][i]; cache; cache = nextcache)
00260 {
00261 nextcache = cache->next;
00262 AAS_FreeRoutingCache(cache);
00263 }
00264 aasworld.clusterareacache[clusternum][i] = NULL;
00265 }
00266 }
00267
00268
00269
00270
00271
00272
00273 void AAS_RemoveRoutingCacheUsingArea( int areanum )
00274 {
00275 int i, clusternum;
00276 aas_routingcache_t *cache, *nextcache;
00277
00278 clusternum = aasworld.areasettings[areanum].cluster;
00279 if (clusternum > 0)
00280 {
00281
00282 AAS_RemoveRoutingCacheInCluster( clusternum );
00283 }
00284 else
00285 {
00286
00287 AAS_RemoveRoutingCacheInCluster( aasworld.portals[-clusternum].frontcluster );
00288 AAS_RemoveRoutingCacheInCluster( aasworld.portals[-clusternum].backcluster );
00289 }
00290
00291 for (i = 0; i < aasworld.numareas; i++)
00292 {
00293
00294 for (cache = aasworld.portalcache[i]; cache; cache = nextcache)
00295 {
00296 nextcache = cache->next;
00297 AAS_FreeRoutingCache(cache);
00298 }
00299 aasworld.portalcache[i] = NULL;
00300 }
00301 }
00302
00303
00304
00305
00306
00307
00308 int AAS_EnableRoutingArea(int areanum, int enable)
00309 {
00310 int flags;
00311
00312 if (areanum <= 0 || areanum >= aasworld.numareas)
00313 {
00314 if (bot_developer)
00315 {
00316 botimport.Print(PRT_ERROR, "AAS_EnableRoutingArea: areanum %d out of range\n", areanum);
00317 }
00318 return 0;
00319 }
00320 flags = aasworld.areasettings[areanum].areaflags & AREA_DISABLED;
00321 if (enable < 0)
00322 return !flags;
00323
00324 if (enable)
00325 aasworld.areasettings[areanum].areaflags &= ~AREA_DISABLED;
00326 else
00327 aasworld.areasettings[areanum].areaflags |= AREA_DISABLED;
00328
00329 if ( (flags & AREA_DISABLED) != (aasworld.areasettings[areanum].areaflags & AREA_DISABLED) )
00330 {
00331
00332 AAS_RemoveRoutingCacheUsingArea( areanum );
00333 }
00334 return !flags;
00335 }
00336
00337
00338
00339
00340
00341
00342 __inline float AAS_RoutingTime(void)
00343 {
00344 return AAS_Time();
00345 }
00346
00347
00348
00349
00350
00351
00352 int AAS_GetAreaContentsTravelFlags(int areanum)
00353 {
00354 int contents, tfl;
00355
00356 contents = aasworld.areasettings[areanum].contents;
00357 tfl = 0;
00358 if (contents & AREACONTENTS_WATER)
00359 tfl |= TFL_WATER;
00360 else if (contents & AREACONTENTS_SLIME)
00361 tfl |= TFL_SLIME;
00362 else if (contents & AREACONTENTS_LAVA)
00363 tfl |= TFL_LAVA;
00364 else
00365 tfl |= TFL_AIR;
00366 if (contents & AREACONTENTS_DONOTENTER)
00367 tfl |= TFL_DONOTENTER;
00368 if (contents & AREACONTENTS_NOTTEAM1)
00369 tfl |= TFL_NOTTEAM1;
00370 if (contents & AREACONTENTS_NOTTEAM2)
00371 tfl |= TFL_NOTTEAM2;
00372 if (aasworld.areasettings[areanum].areaflags & AREA_BRIDGE)
00373 tfl |= TFL_BRIDGE;
00374 return tfl;
00375 }
00376
00377
00378
00379
00380
00381
00382 __inline int AAS_AreaContentsTravelFlags_inline(int areanum)
00383 {
00384 return aasworld.areacontentstravelflags[areanum];
00385 }
00386
00387
00388
00389
00390
00391
00392 int AAS_AreaContentsTravelFlags(int areanum)
00393 {
00394 return aasworld.areacontentstravelflags[areanum];
00395 }
00396
00397
00398
00399
00400
00401
00402 void AAS_InitAreaContentsTravelFlags(void)
00403 {
00404 int i;
00405
00406 if (aasworld.areacontentstravelflags) FreeMemory(aasworld.areacontentstravelflags);
00407 aasworld.areacontentstravelflags = (int *) GetClearedMemory(aasworld.numareas * sizeof(int));
00408
00409 for (i = 0; i < aasworld.numareas; i++) {
00410 aasworld.areacontentstravelflags[i] = AAS_GetAreaContentsTravelFlags(i);
00411 }
00412 }
00413
00414
00415
00416
00417
00418
00419 void AAS_CreateReversedReachability(void)
00420 {
00421 int i, n;
00422 aas_reversedlink_t *revlink;
00423 aas_reachability_t *reach;
00424 aas_areasettings_t *settings;
00425 char *ptr;
00426 #ifdef DEBUG
00427 int starttime;
00428
00429 starttime = Sys_MilliSeconds();
00430 #endif
00431
00432 if (aasworld.reversedreachability) FreeMemory(aasworld.reversedreachability);
00433
00434 ptr = (char *) GetClearedMemory(aasworld.numareas * sizeof(aas_reversedreachability_t) +
00435 aasworld.reachabilitysize * sizeof(aas_reversedlink_t));
00436
00437 aasworld.reversedreachability = (aas_reversedreachability_t *) ptr;
00438
00439 ptr += aasworld.numareas * sizeof(aas_reversedreachability_t);
00440
00441 for (i = 1; i < aasworld.numareas; i++)
00442 {
00443
00444 settings = &aasworld.areasettings[i];
00445
00446 if (settings->numreachableareas >= 128)
00447 botimport.Print(PRT_WARNING, "area %d has more than 128 reachabilities\n", i);
00448
00449 for (n = 0; n < settings->numreachableareas && n < 128; n++)
00450 {
00451
00452 reach = &aasworld.reachability[settings->firstreachablearea + n];
00453
00454 revlink = (aas_reversedlink_t *) ptr;
00455 ptr += sizeof(aas_reversedlink_t);
00456
00457 revlink->areanum = i;
00458 revlink->linknum = settings->firstreachablearea + n;
00459 revlink->next = aasworld.reversedreachability[reach->areanum].first;
00460 aasworld.reversedreachability[reach->areanum].first = revlink;
00461 aasworld.reversedreachability[reach->areanum].numlinks++;
00462 }
00463 }
00464 #ifdef DEBUG
00465 botimport.Print(PRT_MESSAGE, "reversed reachability %d msec\n", Sys_MilliSeconds() - starttime);
00466 #endif
00467 }
00468
00469
00470
00471
00472
00473
00474 unsigned short int AAS_AreaTravelTime(int areanum, vec3_t start, vec3_t end)
00475 {
00476 int intdist;
00477 float dist;
00478 vec3_t dir;
00479
00480 VectorSubtract(start, end, dir);
00481 dist = VectorLength(dir);
00482
00483 if (AAS_AreaCrouch(areanum)) dist *= DISTANCEFACTOR_CROUCH;
00484
00485 else if (AAS_AreaSwim(areanum)) dist *= DISTANCEFACTOR_SWIM;
00486
00487 else dist *= DISTANCEFACTOR_WALK;
00488
00489 intdist = (int) dist;
00490
00491 if (intdist <= 0) intdist = 1;
00492 return intdist;
00493 }
00494
00495
00496
00497
00498
00499
00500 void AAS_CalculateAreaTravelTimes(void)
00501 {
00502 int i, l, n, size;
00503 char *ptr;
00504 vec3_t end;
00505 aas_reversedreachability_t *revreach;
00506 aas_reversedlink_t *revlink;
00507 aas_reachability_t *reach;
00508 aas_areasettings_t *settings;
00509 int starttime;
00510
00511 starttime = Sys_MilliSeconds();
00512
00513 if (aasworld.areatraveltimes) FreeMemory(aasworld.areatraveltimes);
00514
00515 size = aasworld.numareas * sizeof(unsigned short **);
00516 for (i = 0; i < aasworld.numareas; i++)
00517 {
00518 revreach = &aasworld.reversedreachability[i];
00519
00520 settings = &aasworld.areasettings[i];
00521
00522 size += settings->numreachableareas * sizeof(unsigned short *);
00523
00524 size += settings->numreachableareas * revreach->numlinks * sizeof(unsigned short);
00525 }
00526
00527 ptr = (char *) GetClearedMemory(size);
00528 aasworld.areatraveltimes = (unsigned short ***) ptr;
00529 ptr += aasworld.numareas * sizeof(unsigned short **);
00530
00531 for (i = 0; i < aasworld.numareas; i++)
00532 {
00533
00534 revreach = &aasworld.reversedreachability[i];
00535
00536 settings = &aasworld.areasettings[i];
00537
00538 aasworld.areatraveltimes[i] = (unsigned short **) ptr;
00539 ptr += settings->numreachableareas * sizeof(unsigned short *);
00540
00541 for (l = 0; l < settings->numreachableareas; l++)
00542 {
00543 aasworld.areatraveltimes[i][l] = (unsigned short *) ptr;
00544 ptr += revreach->numlinks * sizeof(unsigned short);
00545
00546 reach = &aasworld.reachability[settings->firstreachablearea + l];
00547
00548 for (n = 0, revlink = revreach->first; revlink; revlink = revlink->next, n++)
00549 {
00550 VectorCopy(aasworld.reachability[revlink->linknum].end, end);
00551
00552 aasworld.areatraveltimes[i][l][n] = AAS_AreaTravelTime(i, end, reach->start);
00553 }
00554 }
00555 }
00556 #ifdef DEBUG
00557 botimport.Print(PRT_MESSAGE, "area travel times %d msec\n", Sys_MilliSeconds() - starttime);
00558 #endif
00559 }
00560
00561
00562
00563
00564
00565
00566 int AAS_PortalMaxTravelTime(int portalnum)
00567 {
00568 int l, n, t, maxt;
00569 aas_portal_t *portal;
00570 aas_reversedreachability_t *revreach;
00571 aas_reversedlink_t *revlink;
00572 aas_areasettings_t *settings;
00573
00574 portal = &aasworld.portals[portalnum];
00575
00576 revreach = &aasworld.reversedreachability[portal->areanum];
00577
00578 settings = &aasworld.areasettings[portal->areanum];
00579
00580 maxt = 0;
00581 for (l = 0; l < settings->numreachableareas; l++)
00582 {
00583 for (n = 0, revlink = revreach->first; revlink; revlink = revlink->next, n++)
00584 {
00585 t = aasworld.areatraveltimes[portal->areanum][l][n];
00586 if (t > maxt)
00587 {
00588 maxt = t;
00589 }
00590 }
00591 }
00592 return maxt;
00593 }
00594
00595
00596
00597
00598
00599
00600 void AAS_InitPortalMaxTravelTimes(void)
00601 {
00602 int i;
00603
00604 if (aasworld.portalmaxtraveltimes) FreeMemory(aasworld.portalmaxtraveltimes);
00605
00606 aasworld.portalmaxtraveltimes = (int *) GetClearedMemory(aasworld.numportals * sizeof(int));
00607
00608 for (i = 0; i < aasworld.numportals; i++)
00609 {
00610 aasworld.portalmaxtraveltimes[i] = AAS_PortalMaxTravelTime(i);
00611
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 int AAS_FreeOldestCache(void)
00696 {
00697 int clusterareanum;
00698 aas_routingcache_t *cache;
00699
00700 for (cache = aasworld.oldestcache; cache; cache = cache->time_next) {
00701
00702 if (cache->type == CACHETYPE_AREA && aasworld.areasettings[cache->areanum].cluster < 0) {
00703 continue;
00704 }
00705 break;
00706 }
00707 if (cache) {
00708
00709 if (cache->type == CACHETYPE_AREA) {
00710
00711 clusterareanum = AAS_ClusterAreaNum(cache->cluster, cache->areanum);
00712
00713 if (cache->prev) cache->prev->next = cache->next;
00714 else aasworld.clusterareacache[cache->cluster][clusterareanum] = cache->next;
00715 if (cache->next) cache->next->prev = cache->prev;
00716 }
00717 else {
00718
00719 if (cache->prev) cache->prev->next = cache->next;
00720 else aasworld.portalcache[cache->areanum] = cache->next;
00721 if (cache->next) cache->next->prev = cache->prev;
00722 }
00723 AAS_FreeRoutingCache(cache);
00724 return qtrue;
00725 }
00726 return qfalse;
00727 }
00728
00729
00730
00731
00732
00733
00734 aas_routingcache_t *AAS_AllocRoutingCache(int numtraveltimes)
00735 {
00736 aas_routingcache_t *cache;
00737 int size;
00738
00739
00740 size = sizeof(aas_routingcache_t)
00741 + numtraveltimes * sizeof(unsigned short int)
00742 + numtraveltimes * sizeof(unsigned char);
00743
00744 routingcachesize += size;
00745
00746 cache = (aas_routingcache_t *) GetClearedMemory(size);
00747 cache->reachabilities = (unsigned char *) cache + sizeof(aas_routingcache_t)
00748 + numtraveltimes * sizeof(unsigned short int);
00749 cache->size = size;
00750 return cache;
00751 }
00752
00753
00754
00755
00756
00757
00758 void AAS_FreeAllClusterAreaCache(void)
00759 {
00760 int i, j;
00761 aas_routingcache_t *cache, *nextcache;
00762 aas_cluster_t *cluster;
00763
00764
00765 if (!aasworld.clusterareacache) return;
00766
00767 for (i = 0; i < aasworld.numclusters; i++)
00768 {
00769 cluster = &aasworld.clusters[i];
00770 for (j = 0; j < cluster->numareas; j++)
00771 {
00772 for (cache = aasworld.clusterareacache[i][j]; cache; cache = nextcache)
00773 {
00774 nextcache = cache->next;
00775 AAS_FreeRoutingCache(cache);
00776 }
00777 aasworld.clusterareacache[i][j] = NULL;
00778 }
00779 }
00780
00781 FreeMemory(aasworld.clusterareacache);
00782 aasworld.clusterareacache = NULL;
00783 }
00784
00785
00786
00787
00788
00789
00790 void AAS_InitClusterAreaCache(void)
00791 {
00792 int i, size;
00793 char *ptr;
00794
00795
00796 for (size = 0, i = 0; i < aasworld.numclusters; i++)
00797 {
00798 size += aasworld.clusters[i].numareas;
00799 }
00800
00801
00802 ptr = (char *) GetClearedMemory(
00803 aasworld.numclusters * sizeof(aas_routingcache_t **) +
00804 size * sizeof(aas_routingcache_t *));
00805 aasworld.clusterareacache = (aas_routingcache_t ***) ptr;
00806 ptr += aasworld.numclusters * sizeof(aas_routingcache_t **);
00807 for (i = 0; i < aasworld.numclusters; i++)
00808 {
00809 aasworld.clusterareacache[i] = (aas_routingcache_t **) ptr;
00810 ptr += aasworld.clusters[i].numareas * sizeof(aas_routingcache_t *);
00811 }
00812 }
00813
00814
00815
00816
00817
00818
00819 void AAS_FreeAllPortalCache(void)
00820 {
00821 int i;
00822 aas_routingcache_t *cache, *nextcache;
00823
00824
00825 if (!aasworld.portalcache) return;
00826
00827 for (i = 0; i < aasworld.numareas; i++)
00828 {
00829 for (cache = aasworld.portalcache[i]; cache; cache = nextcache)
00830 {
00831 nextcache = cache->next;
00832 AAS_FreeRoutingCache(cache);
00833 }
00834 aasworld.portalcache[i] = NULL;
00835 }
00836 FreeMemory(aasworld.portalcache);
00837 aasworld.portalcache = NULL;
00838 }
00839
00840
00841
00842
00843
00844
00845 void AAS_InitPortalCache(void)
00846 {
00847
00848 aasworld.portalcache = (aas_routingcache_t **) GetClearedMemory(
00849 aasworld.numareas * sizeof(aas_routingcache_t *));
00850 }
00851
00852
00853
00854
00855
00856
00857 void AAS_InitRoutingUpdate(void)
00858 {
00859 int i, maxreachabilityareas;
00860
00861
00862 if (aasworld.areaupdate) FreeMemory(aasworld.areaupdate);
00863
00864 maxreachabilityareas = 0;
00865 for (i = 0; i < aasworld.numclusters; i++)
00866 {
00867 if (aasworld.clusters[i].numreachabilityareas > maxreachabilityareas)
00868 {
00869 maxreachabilityareas = aasworld.clusters[i].numreachabilityareas;
00870 }
00871 }
00872
00873 aasworld.areaupdate = (aas_routingupdate_t *) GetClearedMemory(
00874 maxreachabilityareas * sizeof(aas_routingupdate_t));
00875
00876 if (aasworld.portalupdate) FreeMemory(aasworld.portalupdate);
00877
00878 aasworld.portalupdate = (aas_routingupdate_t *) GetClearedMemory(
00879 (aasworld.numportals+1) * sizeof(aas_routingupdate_t));
00880 }
00881
00882
00883
00884
00885
00886
00887 void AAS_CreateAllRoutingCache(void)
00888 {
00889 int i, j, t;
00890
00891 aasworld.initialized = qtrue;
00892 botimport.Print(PRT_MESSAGE, "AAS_CreateAllRoutingCache\n");
00893 for (i = 1; i < aasworld.numareas; i++)
00894 {
00895 if (!AAS_AreaReachability(i)) continue;
00896 for (j = 1; j < aasworld.numareas; j++)
00897 {
00898 if (i == j) continue;
00899 if (!AAS_AreaReachability(j)) continue;
00900 t = AAS_AreaTravelTimeToGoalArea(i, aasworld.areas[i].center, j, TFL_DEFAULT);
00901
00902 }
00903 }
00904 aasworld.initialized = qfalse;
00905 }
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916 typedef struct routecacheheader_s
00917 {
00918 int ident;
00919 int version;
00920 int numareas;
00921 int numclusters;
00922 int areacrc;
00923 int clustercrc;
00924 int numportalcache;
00925 int numareacache;
00926 } routecacheheader_t;
00927
00928 #define RCID (('C'<<24)+('R'<<16)+('E'<<8)+'M')
00929 #define RCVERSION 2
00930
00931
00932
00933
00934 void AAS_WriteRouteCache(void)
00935 {
00936 int i, j, numportalcache, numareacache, totalsize;
00937 aas_routingcache_t *cache;
00938 aas_cluster_t *cluster;
00939 fileHandle_t fp;
00940 char filename[MAX_QPATH];
00941 routecacheheader_t routecacheheader;
00942
00943 numportalcache = 0;
00944 for (i = 0; i < aasworld.numareas; i++)
00945 {
00946 for (cache = aasworld.portalcache[i]; cache; cache = cache->next)
00947 {
00948 numportalcache++;
00949 }
00950 }
00951 numareacache = 0;
00952 for (i = 0; i < aasworld.numclusters; i++)
00953 {
00954 cluster = &aasworld.clusters[i];
00955 for (j = 0; j < cluster->numareas; j++)
00956 {
00957 for (cache = aasworld.clusterareacache[i][j]; cache; cache = cache->next)
00958 {
00959 numareacache++;
00960 }
00961 }
00962 }
00963
00964 Com_sprintf(filename, MAX_QPATH, "maps/%s.rcd", aasworld.mapname);
00965 botimport.FS_FOpenFile( filename, &fp, FS_WRITE );
00966 if (!fp)
00967 {
00968 AAS_Error("Unable to open file: %s\n", filename);
00969 return;
00970 }
00971
00972 routecacheheader.ident = RCID;
00973 routecacheheader.version = RCVERSION;
00974 routecacheheader.numareas = aasworld.numareas;
00975 routecacheheader.numclusters = aasworld.numclusters;
00976 routecacheheader.areacrc = CRC_ProcessString( (unsigned char *)aasworld.areas, sizeof(aas_area_t) * aasworld.numareas );
00977 routecacheheader.clustercrc = CRC_ProcessString( (unsigned char *)aasworld.clusters, sizeof(aas_cluster_t) * aasworld.numclusters );
00978 routecacheheader.numportalcache = numportalcache;
00979 routecacheheader.numareacache = numareacache;
00980
00981 botimport.FS_Write(&routecacheheader, sizeof(routecacheheader_t), fp);
00982
00983 totalsize = 0;
00984
00985 for (i = 0; i < aasworld.numareas; i++)
00986 {
00987 for (cache = aasworld.portalcache[i]; cache; cache = cache->next)
00988 {
00989 botimport.FS_Write(cache, cache->size, fp);
00990 totalsize += cache->size;
00991 }
00992 }
00993 for (i = 0; i < aasworld.numclusters; i++)
00994 {
00995 cluster = &aasworld.clusters[i];
00996 for (j = 0; j < cluster->numareas; j++)
00997 {
00998 for (cache = aasworld.clusterareacache[i][j]; cache; cache = cache->next)
00999 {
01000 botimport.FS_Write(cache, cache->size, fp);
01001 totalsize += cache->size;
01002 }
01003 }
01004 }
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021 botimport.FS_FCloseFile(fp);
01022 botimport.Print(PRT_MESSAGE, "\nroute cache written to %s\n", filename);
01023 botimport.Print(PRT_MESSAGE, "written %d bytes of routing cache\n", totalsize);
01024 }
01025
01026
01027
01028
01029
01030
01031 aas_routingcache_t *AAS_ReadCache(fileHandle_t fp)
01032 {
01033 int size;
01034 aas_routingcache_t *cache;
01035
01036 botimport.FS_Read(&size, sizeof(size), fp);
01037 cache = (aas_routingcache_t *) GetMemory(size);
01038 cache->size = size;
01039 botimport.FS_Read((unsigned char *)cache + sizeof(size), size - sizeof(size), fp);
01040 cache->reachabilities = (unsigned char *) cache + sizeof(aas_routingcache_t) - sizeof(unsigned short) +
01041 (size - sizeof(aas_routingcache_t) + sizeof(unsigned short)) / 3 * 2;
01042 return cache;
01043 }
01044
01045
01046
01047
01048
01049
01050 int AAS_ReadRouteCache(void)
01051 {
01052 int i, clusterareanum;
01053 fileHandle_t fp;
01054 char filename[MAX_QPATH];
01055 routecacheheader_t routecacheheader;
01056 aas_routingcache_t *cache;
01057
01058 Com_sprintf(filename, MAX_QPATH, "maps/%s.rcd", aasworld.mapname);
01059 botimport.FS_FOpenFile( filename, &fp, FS_READ );
01060 if (!fp)
01061 {
01062 return qfalse;
01063 }
01064 botimport.FS_Read(&routecacheheader, sizeof(routecacheheader_t), fp );
01065 if (routecacheheader.ident != RCID)
01066 {
01067 AAS_Error("%s is not a route cache dump\n");
01068 return qfalse;
01069 }
01070 if (routecacheheader.version != RCVERSION)
01071 {
01072 AAS_Error("route cache dump has wrong version %d, should be %d", routecacheheader.version, RCVERSION);
01073 return qfalse;
01074 }
01075 if (routecacheheader.numareas != aasworld.numareas)
01076 {
01077
01078 return qfalse;
01079 }
01080 if (routecacheheader.numclusters != aasworld.numclusters)
01081 {
01082
01083 return qfalse;
01084 }
01085 if (routecacheheader.areacrc !=
01086 CRC_ProcessString( (unsigned char *)aasworld.areas, sizeof(aas_area_t) * aasworld.numareas ))
01087 {
01088
01089 return qfalse;
01090 }
01091 if (routecacheheader.clustercrc !=
01092 CRC_ProcessString( (unsigned char *)aasworld.clusters, sizeof(aas_cluster_t) * aasworld.numclusters ))
01093 {
01094
01095 return qfalse;
01096 }
01097
01098 for (i = 0; i < routecacheheader.numportalcache; i++)
01099 {
01100 cache = AAS_ReadCache(fp);
01101 cache->next = aasworld.portalcache[cache->areanum];
01102 cache->prev = NULL;
01103 if (aasworld.portalcache[cache->areanum])
01104 aasworld.portalcache[cache->areanum]->prev = cache;
01105 aasworld.portalcache[cache->areanum] = cache;
01106 }
01107
01108 for (i = 0; i < routecacheheader.numareacache; i++)
01109 {
01110 cache = AAS_ReadCache(fp);
01111 clusterareanum = AAS_ClusterAreaNum(cache->cluster, cache->areanum);
01112 cache->next = aasworld.clusterareacache[cache->cluster][clusterareanum];
01113 cache->prev = NULL;
01114 if (aasworld.clusterareacache[cache->cluster][clusterareanum])
01115 aasworld.clusterareacache[cache->cluster][clusterareanum]->prev = cache;
01116 aasworld.clusterareacache[cache->cluster][clusterareanum] = cache;
01117 }
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 botimport.FS_FCloseFile(fp);
01133 return qtrue;
01134 }
01135
01136
01137
01138
01139
01140
01141 #define MAX_REACHABILITYPASSAREAS 32
01142
01143 void AAS_InitReachabilityAreas(void)
01144 {
01145 int i, j, numareas, areas[MAX_REACHABILITYPASSAREAS];
01146 int numreachareas;
01147 aas_reachability_t *reach;
01148 vec3_t start, end;
01149
01150 if (aasworld.