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_memory.h"
00034 #include "l_script.h"
00035 #include "l_precomp.h"
00036 #include "l_struct.h"
00037 #include "l_log.h"
00038 #include "l_memory.h"
00039 #include "l_libvar.h"
00040 #include "aasfile.h"
00041 #include "../game/botlib.h"
00042 #include "../game/be_aas.h"
00043 #include "be_aas_funcs.h"
00044 #include "be_aas_def.h"
00045
00046 extern botlib_import_t botimport;
00047
00048 #define AAS_MAX_PORTALS 65536
00049 #define AAS_MAX_PORTALINDEXSIZE 65536
00050 #define AAS_MAX_CLUSTERS 65536
00051
00052 #define MAX_PORTALAREAS 1024
00053
00054
00055 int nofaceflood = qtrue;
00056
00057
00058
00059
00060
00061
00062
00063 void AAS_RemoveClusterAreas(void)
00064 {
00065 int i;
00066
00067 for (i = 1; i < aasworld.numareas; i++)
00068 {
00069 aasworld.areasettings[i].cluster = 0;
00070 }
00071 }
00072
00073
00074
00075
00076
00077
00078 void AAS_ClearCluster(int clusternum)
00079 {
00080 int i;
00081
00082 for (i = 1; i < aasworld.numareas; i++)
00083 {
00084 if (aasworld.areasettings[i].cluster == clusternum)
00085 {
00086 aasworld.areasettings[i].cluster = 0;
00087 }
00088 }
00089 }
00090
00091
00092
00093
00094
00095
00096 void AAS_RemovePortalsClusterReference(int clusternum)
00097 {
00098 int portalnum;
00099
00100 for (portalnum = 1; portalnum < aasworld.numportals; portalnum++)
00101 {
00102 if (aasworld.portals[portalnum].frontcluster == clusternum)
00103 {
00104 aasworld.portals[portalnum].frontcluster = 0;
00105 }
00106 if (aasworld.portals[portalnum].backcluster == clusternum)
00107 {
00108 aasworld.portals[portalnum].backcluster = 0;
00109 }
00110 }
00111 }
00112
00113
00114
00115
00116
00117
00118 int AAS_UpdatePortal(int areanum, int clusternum)
00119 {
00120 int portalnum;
00121 aas_portal_t *portal;
00122 aas_cluster_t *cluster;
00123
00124
00125 for (portalnum = 1; portalnum < aasworld.numportals; portalnum++)
00126 {
00127 if (aasworld.portals[portalnum].areanum == areanum) break;
00128 }
00129
00130 if (portalnum == aasworld.numportals)
00131 {
00132 AAS_Error("no portal of area %d", areanum);
00133 return qtrue;
00134 }
00135
00136 portal = &aasworld.portals[portalnum];
00137
00138 if (portal->frontcluster == clusternum) return qtrue;
00139 if (portal->backcluster == clusternum) return qtrue;
00140
00141 if (!portal->frontcluster)
00142 {
00143 portal->frontcluster = clusternum;
00144 }
00145
00146 else if (!portal->backcluster)
00147 {
00148 portal->backcluster = clusternum;
00149 }
00150 else
00151 {
00152
00153 aasworld.areasettings[areanum].contents &= ~AREACONTENTS_CLUSTERPORTAL;
00154 Log_Write("portal area %d is seperating more than two clusters\r\n", areanum);
00155 return qfalse;
00156 }
00157 if (aasworld.portalindexsize >= AAS_MAX_PORTALINDEXSIZE)
00158 {
00159 AAS_Error("AAS_MAX_PORTALINDEXSIZE");
00160 return qtrue;
00161 }
00162
00163 aasworld.areasettings[areanum].cluster = -portalnum;
00164
00165 cluster = &aasworld.clusters[clusternum];
00166 aasworld.portalindex[cluster->firstportal + cluster->numportals] = portalnum;
00167 aasworld.portalindexsize++;
00168 cluster->numportals++;
00169 return qtrue;
00170 }
00171
00172
00173
00174
00175
00176
00177 int AAS_FloodClusterAreas_r(int areanum, int clusternum)
00178 {
00179 aas_area_t *area;
00180 aas_face_t *face;
00181 int facenum, i;
00182
00183
00184 if (areanum <= 0 || areanum >= aasworld.numareas)
00185 {
00186 AAS_Error("AAS_FloodClusterAreas_r: areanum out of range");
00187 return qfalse;
00188 }
00189
00190 if (aasworld.areasettings[areanum].cluster > 0)
00191 {
00192 if (aasworld.areasettings[areanum].cluster == clusternum) return qtrue;
00193
00194
00195
00196 AAS_Error("cluster %d touched cluster %d at area %d\r\n",
00197 clusternum, aasworld.areasettings[areanum].cluster, areanum);
00198 return qfalse;
00199 }
00200
00201 if (aasworld.areasettings[areanum].contents & AREACONTENTS_CLUSTERPORTAL)
00202 {
00203 return AAS_UpdatePortal(areanum, clusternum);
00204 }
00205
00206 aasworld.areasettings[areanum].cluster = clusternum;
00207 aasworld.areasettings[areanum].clusterareanum =
00208 aasworld.clusters[clusternum].numareas;
00209
00210 aasworld.clusters[clusternum].numareas++;
00211
00212 area = &aasworld.areas[areanum];
00213
00214 if (!nofaceflood)
00215 {
00216 for (i = 0; i < area->numfaces; i++)
00217 {
00218 facenum = abs(aasworld.faceindex[area->firstface + i]);
00219 face = &aasworld.faces[facenum];
00220 if (face->frontarea == areanum)
00221 {
00222 if (face->backarea) if (!AAS_FloodClusterAreas_r(face->backarea, clusternum)) return qfalse;
00223 }
00224 else
00225 {
00226 if (face->frontarea) if (!AAS_FloodClusterAreas_r(face->frontarea, clusternum)) return qfalse;
00227 }
00228 }
00229 }
00230
00231 for (i = 0; i < aasworld.areasettings[areanum].numreachableareas; i++)
00232 {
00233 if (!aasworld.reachability[
00234 aasworld.areasettings[areanum].firstreachablearea + i].areanum)
00235 {
00236 continue;
00237 }
00238 if (!AAS_FloodClusterAreas_r(aasworld.reachability[
00239 aasworld.areasettings[areanum].firstreachablearea + i].areanum, clusternum)) return qfalse;
00240 }
00241 return qtrue;
00242 }
00243
00244
00245
00246
00247
00248
00249
00250 int AAS_FloodClusterAreasUsingReachabilities(int clusternum)
00251 {
00252 int i, j, areanum;
00253
00254 for (i = 1; i < aasworld.numareas; i++)
00255 {
00256
00257 if (aasworld.areasettings[i].cluster)
00258 continue;
00259
00260 if (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)
00261 continue;
00262
00263 for (j = 0; j < aasworld.areasettings[i].numreachableareas; j++)
00264 {
00265
00266 areanum = aasworld.reachability[aasworld.areasettings[i].firstreachablearea + j].areanum;
00267
00268 if (aasworld.areasettings[areanum].contents & AREACONTENTS_CLUSTERPORTAL)
00269 continue;
00270
00271 if (aasworld.areasettings[areanum].cluster)
00272 {
00273 if (!AAS_FloodClusterAreas_r(i, clusternum))
00274 return qfalse;
00275 i = 0;
00276 break;
00277 }
00278 }
00279 }
00280 return qtrue;
00281 }
00282
00283
00284
00285
00286
00287
00288 void AAS_NumberClusterPortals(int clusternum)
00289 {
00290 int i, portalnum;
00291 aas_cluster_t *cluster;
00292 aas_portal_t *portal;
00293
00294 cluster = &aasworld.clusters[clusternum];
00295 for (i = 0; i < cluster->numportals; i++)
00296 {
00297 portalnum = aasworld.portalindex[cluster->firstportal + i];
00298 portal = &aasworld.portals[portalnum];
00299 if (portal->frontcluster == clusternum)
00300 {
00301 portal->clusterareanum[0] = cluster->numareas++;
00302 }
00303 else
00304 {
00305 portal->clusterareanum[1] = cluster->numareas++;
00306 }
00307 }
00308 }
00309
00310
00311
00312
00313
00314
00315 void AAS_NumberClusterAreas(int clusternum)
00316 {
00317 int i, portalnum;
00318 aas_cluster_t *cluster;
00319 aas_portal_t *portal;
00320
00321 aasworld.clusters[clusternum].numareas = 0;
00322 aasworld.clusters[clusternum].numreachabilityareas = 0;
00323
00324 for (i = 1; i < aasworld.numareas; i++)
00325 {
00326
00327 if (aasworld.areasettings[i].cluster != clusternum) continue;
00328
00329 if (!AAS_AreaReachability(i)) continue;
00330
00331 aasworld.areasettings[i].clusterareanum = aasworld.clusters[clusternum].numareas;
00332
00333 aasworld.clusters[clusternum].numareas++;
00334 aasworld.clusters[clusternum].numreachabilityareas++;
00335 }
00336
00337 cluster = &aasworld.clusters[clusternum];
00338 for (i = 0; i < cluster->numportals; i++)
00339 {
00340 portalnum = aasworld.portalindex[cluster->firstportal + i];
00341 portal = &aasworld.portals[portalnum];
00342 if (!AAS_AreaReachability(portal->areanum)) continue;
00343 if (portal->frontcluster == clusternum)
00344 {
00345 portal->clusterareanum[0] = cluster->numareas++;
00346 aasworld.clusters[clusternum].numreachabilityareas++;
00347 }
00348 else
00349 {
00350 portal->clusterareanum[1] = cluster->numareas++;
00351 aasworld.clusters[clusternum].numreachabilityareas++;
00352 }
00353 }
00354
00355 for (i = 1; i < aasworld.numareas; i++)
00356 {
00357
00358 if (aasworld.areasettings[i].cluster != clusternum) continue;
00359
00360 if (AAS_AreaReachability(i)) continue;
00361
00362 aasworld.areasettings[i].clusterareanum = aasworld.clusters[clusternum].numareas;
00363
00364 aasworld.clusters[clusternum].numareas++;
00365 }
00366
00367 cluster = &aasworld.clusters[clusternum];
00368 for (i = 0; i < cluster->numportals; i++)
00369 {
00370 portalnum = aasworld.portalindex[cluster->firstportal + i];
00371 portal = &aasworld.portals[portalnum];
00372 if (AAS_AreaReachability(portal->areanum)) continue;
00373 if (portal->frontcluster == clusternum)
00374 {
00375 portal->clusterareanum[0] = cluster->numareas++;
00376 }
00377 else
00378 {
00379 portal->clusterareanum[1] = cluster->numareas++;
00380 }
00381 }
00382 }
00383
00384
00385
00386
00387
00388
00389 int AAS_FindClusters(void)
00390 {
00391 int i;
00392 aas_cluster_t *cluster;
00393
00394 AAS_RemoveClusterAreas();
00395
00396 for (i = 1; i < aasworld.numareas; i++)
00397 {
00398
00399 if (aasworld.areasettings[i].cluster)
00400 continue;
00401
00402 if (nofaceflood)
00403 {
00404 if (!aasworld.areasettings[i].numreachableareas)
00405 continue;
00406 }
00407
00408 if (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)
00409 continue;
00410 if (aasworld.numclusters >= AAS_MAX_CLUSTERS)
00411 {
00412 AAS_Error("AAS_MAX_CLUSTERS");
00413 return qfalse;
00414 }
00415 cluster = &aasworld.clusters[aasworld.numclusters];
00416 cluster->numareas = 0;
00417 cluster->numreachabilityareas = 0;
00418 cluster->firstportal = aasworld.portalindexsize;
00419 cluster->numportals = 0;
00420
00421 if (!AAS_FloodClusterAreas_r(i, aasworld.numclusters))
00422 return qfalse;
00423 if (!AAS_FloodClusterAreasUsingReachabilities(aasworld.numclusters))
00424 return qfalse;
00425
00426
00427 AAS_NumberClusterAreas(aasworld.numclusters);
00428
00429 aasworld.numclusters++;
00430 }
00431 return qtrue;
00432 }
00433
00434
00435
00436
00437
00438
00439 void AAS_CreatePortals(void)
00440 {
00441 int i;
00442 aas_portal_t *portal;
00443
00444 for (i = 1; i < aasworld.numareas; i++)
00445 {
00446
00447 if (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)
00448 {
00449 if (aasworld.numportals >= AAS_MAX_PORTALS)
00450 {
00451 AAS_Error("AAS_MAX_PORTALS");
00452 return;
00453 }
00454 portal = &aasworld.portals[aasworld.numportals];
00455 portal->areanum = i;
00456 portal->frontcluster = 0;
00457 portal->backcluster = 0;
00458 aasworld.numportals++;
00459 }
00460 }
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
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 void AAS_ConnectedAreas_r(int *areanums, int numareas, int *connectedareas, int curarea)
00688 {
00689 int i, j, otherareanum, facenum;
00690 aas_area_t *area;
00691 aas_face_t *face;
00692
00693 connectedareas[curarea] = qtrue;
00694 area = &aasworld.areas[areanums[curarea]];
00695 for (i = 0; i < area->numfaces; i++)
00696 {
00697 facenum = abs(aasworld.faceindex[area->firstface + i]);
00698 face = &aasworld.faces[facenum];
00699
00700 if (face->faceflags & FACE_SOLID) continue;
00701
00702 if (face->frontarea != areanums[curarea]) otherareanum = face->frontarea;
00703 else otherareanum = face->backarea;
00704
00705 for (j = 0; j < numareas; j++)
00706 {
00707 if (areanums[j] == otherareanum) break;
00708 }
00709
00710 if (j == numareas) continue;
00711
00712 if (connectedareas[j]) continue;
00713
00714 AAS_ConnectedAreas_r(areanums, numareas, connectedareas, j);
00715 }
00716 }
00717
00718
00719
00720
00721
00722
00723 qboolean AAS_ConnectedAreas(int *areanums, int numareas)
00724 {
00725 int connectedareas[MAX_PORTALAREAS], i;
00726
00727 Com_Memset(connectedareas, 0, sizeof(connectedareas));
00728 if (numareas < 1) return qfalse;
00729 if (numareas == 1) return qtrue;
00730 AAS_ConnectedAreas_r(areanums, numareas, connectedareas, 0);
00731 for (i = 0; i < numareas; i++)
00732 {
00733 if (!connectedareas[i]) return qfalse;
00734 }
00735 return qtrue;
00736 }
00737
00738
00739
00740
00741
00742
00743
00744 int AAS_GetAdjacentAreasWithLessPresenceTypes_r(int *areanums, int numareas, int curareanum)
00745 {
00746 int i, j, presencetype, otherpresencetype, otherareanum, facenum;
00747 aas_area_t *area;
00748 aas_face_t *face;
00749
00750 areanums[numareas++] = curareanum;
00751 area = &aasworld.areas[curareanum];
00752 presencetype = aasworld.areasettings[curareanum].presencetype;
00753 for (i = 0; i < area->numfaces; i++)
00754 {
00755 facenum = abs(aasworld.faceindex[area->firstface + i]);
00756 face = &aasworld.faces[facenum];
00757
00758 if (face->faceflags & FACE_SOLID) continue;
00759
00760 if (face->frontarea != curareanum) otherareanum = face->frontarea;
00761 else otherareanum = face->backarea;
00762
00763 otherpresencetype = aasworld.areasettings[otherareanum].presencetype;
00764
00765 if ((presencetype & ~otherpresencetype) &&
00766 !(otherpresencetype & ~presencetype))
00767 {
00768
00769 for (j = 0; j < numareas; j++)
00770 {
00771 if (otherareanum == areanums[j]) break;
00772 }
00773
00774 if (j == numareas)
00775 {
00776 if (numareas >= MAX_PORTALAREAS)
00777 {
00778 AAS_Error("MAX_PORTALAREAS");
00779 return numareas;
00780 }
00781 numareas = AAS_GetAdjacentAreasWithLessPresenceTypes_r(areanums, numareas, otherareanum);
00782 }
00783 }
00784 }
00785 return numareas;
00786 }
00787
00788
00789
00790
00791
00792
00793 int AAS_CheckAreaForPossiblePortals(int areanum)
00794 {
00795 int i, j, k, fen, ben, frontedgenum, backedgenum, facenum;
00796 int areanums[MAX_PORTALAREAS], numareas, otherareanum;
00797 int numareafrontfaces[MAX_PORTALAREAS], numareabackfaces[MAX_PORTALAREAS];
00798 int frontfacenums[MAX_PORTALAREAS], backfacenums[MAX_PORTALAREAS];
00799 int numfrontfaces, numbackfaces;
00800 int frontareanums[MAX_PORTALAREAS], backareanums[MAX_PORTALAREAS];
00801 int numfrontareas, numbackareas;
00802 int frontplanenum, backplanenum, faceplanenum;
00803 aas_area_t *area;
00804 aas_face_t *frontface, *backface, *face;
00805
00806
00807 if (aasworld.areasettings[areanum].contents & AREACONTENTS_CLUSTERPORTAL) return 0;
00808
00809 if (!(aasworld.areasettings[areanum].areaflags & AREA_GROUNDED)) return 0;
00810
00811 Com_Memset(numareafrontfaces, 0, sizeof(numareafrontfaces));
00812 Com_Memset(numareabackfaces, 0, sizeof(numareabackfaces));
00813 numareas = numfrontfaces = numbackfaces = 0;
00814 numfrontareas = numbackareas = 0;
00815 frontplanenum = backplanenum = -1;
00816
00817 numareas = AAS_GetAdjacentAreasWithLessPresenceTypes_r(areanums, 0, areanum);
00818
00819 for (i = 0; i < numareas; i++)
00820 {
00821 area = &aasworld.areas[areanums[i]];
00822 for (j = 0; j < area->numfaces; j++)
00823 {
00824 facenum = abs(aasworld.faceindex[area->firstface + j]);
00825 face = &aasworld.faces[facenum];
00826
00827 if (face->faceflags & FACE_SOLID) continue;
00828
00829 for (k = 0; k < numareas; k++)
00830 {
00831 if (k == i) continue;
00832 if (face->frontarea == areanums[k] || face->backarea == areanums[k]) break;
00833 }
00834
00835 if (k != numareas) continue;
00836
00837 if (face->frontarea == areanums[i]) otherareanum = face->backarea;
00838 else otherareanum = face->frontarea;
00839
00840 if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL) return 0;
00841
00842 faceplanenum = face->planenum & ~1;
00843
00844 if (frontplanenum < 0 || faceplanenum == frontplanenum)
00845 {
00846 frontplanenum = faceplanenum;
00847 frontfacenums[numfrontfaces++] = facenum;
00848 for (k = 0; k < numfrontareas; k++)
00849 {
00850 if (frontareanums[k] == otherareanum) break;
00851 }
00852 if (k == numfrontareas) frontareanums[numfrontareas++] = otherareanum;
00853 numareafrontfaces[i]++;
00854 }
00855 else if (backplanenum < 0 || faceplanenum == backplanenum)
00856 {
00857 backplanenum = faceplanenum;
00858 backfacenums[numbackfaces++] = facenum;
00859 for (k = 0; k < numbackareas; k++)
00860 {
00861 if (backareanums[k] == otherareanum) break;
00862 }
00863 if (k == numbackareas) backareanums[numbackareas++] = otherareanum;
00864 numareabackfaces[i]++;
00865 }
00866 else
00867 {
00868 return 0;
00869 }
00870 }
00871 }
00872
00873 for (i = 0; i < numareas; i++)
00874 {
00875 if (!numareafrontfaces[i] || !numareabackfaces[i]) return 0;
00876 }
00877
00878 if (!AAS_ConnectedAreas(frontareanums, numfrontareas)) return 0;
00879
00880 if (!AAS_ConnectedAreas(backareanums, numbackareas)) return 0;
00881
00882 for (i = 0; i < numfrontfaces; i++)
00883 {
00884 frontface = &aasworld.faces[frontfacenums[i]];
00885 for (fen = 0; fen < frontface->numedges; fen++)
00886 {
00887 frontedgenum = abs(aasworld.edgeindex[frontface->firstedge + fen]);
00888 for (j = 0; j < numbackfaces; j++)
00889 {
00890 backface = &aasworld.faces[backfacenums[j]];
00891 for (ben = 0; ben < backface->numedges; ben++)
00892 {
00893 backedgenum = abs(aasworld.edgeindex[backface->firstedge + ben]);
00894 if (frontedgenum == backedgenum) break;
00895 }
00896 if (ben != backface->numedges) break;
00897 }
00898 if (j != numbackfaces) break;
00899 }
00900 if (fen != frontface->numedges) break;
00901 }
00902 if (i != numfrontfaces) return 0;
00903
00904 for (i = 0; i < numareas; i++)
00905 {
00906 aasworld.areasettings[areanums[i]].contents |= AREACONTENTS_CLUSTERPORTAL;
00907
00908 aasworld.areasettings[areanums[i]].contents |= AREACONTENTS_ROUTEPORTAL;
00909 Log_Write("possible portal: %d\r\n", areanums[i]);
00910 }
00911
00912 return numareas;
00913 }
00914
00915
00916
00917
00918
00919
00920 void AAS_FindPossiblePortals(void)
00921 {
00922 int i, numpossibleportals;
00923
00924 numpossibleportals = 0;
00925 for (i = 1; i < aasworld.numareas; i++)
00926 {
00927 numpossibleportals += AAS_CheckAreaForPossiblePortals(i);
00928 }
00929 botimport.Print(PRT_MESSAGE, "\r%6d possible portal areas\n", numpossibleportals);
00930 }
00931
00932
00933
00934
00935
00936
00937 void AAS_RemoveAllPortals(void)
00938 {
00939 int i;
00940
00941 for (i = 1; i < aasworld.numareas; i++)
00942 {
00943 aasworld.areasettings[i].contents &= ~AREACONTENTS_CLUSTERPORTAL;
00944 }
00945 }
00946
00947 #if 0
00948
00949
00950
00951
00952
00953
00954 void AAS_FloodCluster_r(int areanum, int clusternum)
00955 {
00956 int i, otherareanum;
00957 aas_face_t *face;
00958 aas_area_t *area;
00959
00960
00961 aasworld.areasettings[areanum].cluster = clusternum;
00962
00963
00964
00965 area = &aasworld.areas[areanum];
00966
00967 for (i = 0; i < area->numfaces; i++)
00968 {
00969 face = &aasworld.faces[abs(aasworld.faceindex[area->firstface + i])];
00970
00971 if (face->frontarea != areanum) otherareanum = face->frontarea;
00972 else otherareanum = face->backarea;
00973
00974 if (!otherareanum) continue;
00975
00976 if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL) continue;
00977
00978 if (aasworld.areasettings[otherareanum].cluster) continue;
00979
00980 AAS_FloodCluster_r(otherareanum, clusternum);
00981 }
00982
00983 for (i = 0; i < aasworld.areasettings[areanum].numreachableareas; i++)
00984 {
00985 otherareanum = aasworld.reachability[
00986 aasworld.areasettings[areanum].firstreachablearea + i].areanum;
00987 if (!otherareanum)
00988 {
00989 continue;
00990 AAS_Error("reachability %d has zero area\n", aasworld.areasettings[areanum].firstreachablearea + i);
00991 }
00992
00993 if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL) continue;
00994
00995 if (aasworld.areasettings[otherareanum].cluster) continue;
00996
00997 AAS_FloodCluster_r(otherareanum, clusternum);
00998 }
00999 }
01000
01001
01002
01003
01004
01005
01006 void AAS_RemoveTeleporterPortals(void)
01007 {
01008 int i, j, areanum;
01009
01010 for (i = 1; i < aasworld.numareas; i++)
01011 {
01012 for (j = 0; j < aasworld.areasettings[i].numreachableareas; j++)
01013 {
01014 areanum = aasworld.reachability[aasworld.areasettings[i].firstreachablearea + j].areanum;
01015 if (aasworld.reachability[aasworld.areasettings[i].firstreachablearea + j].traveltype == TRAVEL_TELEPORT)
01016 {
01017 aasworld.areasettings[i].contents &= ~AREACONTENTS_CLUSTERPORTAL;
01018 aasworld.areasettings[areanum].contents &= ~AREACONTENTS_CLUSTERPORTAL;
01019 break;
01020 }
01021 }
01022 }
01023 }
01024
01025
01026
01027
01028
01029
01030 void AAS_FloodClusterReachabilities(int clusternum)
01031 {
01032 int i, j, areanum;
01033
01034 for (i = 1; i < aasworld.numareas; i++)
01035 {
01036
01037 if (aasworld.areasettings[i].cluster) continue;
01038
01039 if (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL) continue;
01040
01041 for (j = 0; j < aasworld.areasettings[i].numreachableareas; j++)
01042 {
01043
01044 areanum = aasworld.reachability[aasworld.areasettings[i].firstreachablearea + j].areanum;
01045
01046 if (aasworld.areasettings[areanum].contents & AREACONTENTS_CLUSTERPORTAL) continue;
01047
01048 if (aasworld.areasettings[areanum].cluster == clusternum)
01049 {
01050 AAS_FloodCluster_r(i, clusternum);
01051 i = 0;
01052 break;
01053 }
01054 }
01055 }
01056 }
01057
01058
01059
01060
01061
01062
01063
01064 void AAS_RemoveNotClusterClosingPortals(void)
01065 {
01066 int i, j, k, facenum, otherareanum, nonclosingportals;
01067 aas_area_t *area;
01068 aas_face_t *face;
01069
01070 AAS_RemoveTeleporterPortals();
01071
01072 nonclosingportals = 0;
01073 for (i = 1; i < aasworld.numareas; i++)
01074 {
01075 if (!(aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)) continue;
01076
01077
01078 area = &aasworld.areas[i];
01079 for (j = 0; j < area->numfaces; j++)
01080 {
01081 facenum = abs(aasworld.faceindex[area->firstface + j]);
01082 face = &aasworld.faces[facenum];
01083
01084 if (face->frontarea != i) otherareanum = face->frontarea;
01085 else otherareanum = face->backarea;
01086
01087 if (!otherareanum) continue;
01088
01089 if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL)
01090 {
01091 continue;
01092 }
01093
01094 AAS_RemoveClusterAreas();
01095
01096 AAS_FloodCluster_r(otherareanum, 1);
01097 AAS_FloodClusterReachabilities(1);
01098
01099 for (k = 0; k < area->numfaces; k++)
01100 {
01101 facenum = abs(aasworld.faceindex[area->firstface + k]);
01102 face = &aasworld.faces[facenum];
01103
01104 if (face->frontarea != i) otherareanum = face->frontarea;
01105 else otherareanum = face->backarea;
01106
01107 if (!otherareanum) continue;
01108
01109 if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL)
01110 {
01111 continue;
01112 }
01113
01114 if (!aasworld.areasettings[otherareanum].cluster) break;
01115 }
01116
01117
01118 if (k >= area->numfaces)
01119 {
01120 aasworld.areasettings[i].contents &= ~AREACONTENTS_CLUSTERPORTAL;
01121 nonclosingportals++;
01122
01123 i = 0;
01124 break;
01125 }
01126 }
01127 }
01128 botimport.Print(PRT_MESSAGE, "\r%6d non closing portals removed\n", nonclosingportals);
01129 }
01130
01131
01132
01133
01134
01135
01136
01137
01138 void AAS_RemoveNotClusterClosingPortals(void)
01139 {
01140 int i, j, facenum, otherareanum, nonclosingportals, numseperatedclusters;
01141 aas_area_t *area;
01142 aas_face_t *face;
01143
01144 AAS_RemoveTeleporterPortals();
01145
01146 nonclosingportals = 0;
01147 for (i = 1; i < aasworld.numareas; i++)
01148 {
01149 if (!(aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)) continue;
01150
01151 numseperatedclusters = 0;
01152
01153 AAS_RemoveClusterAreas();
01154
01155
01156 area = &aasworld.areas[i];
01157 for (j = 0; j < area->numfaces; j++)
01158 {
01159 facenum = abs(aasworld.faceindex[area->firstface + j]);
01160 face = &aasworld.faces[facenum];
01161
01162 if (face->frontarea != i) otherareanum = face->frontarea;
01163 else otherareanum = face->backarea;
01164
01165 if (!otherareanum) continue;
01166
01167 if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL) continue;
01168
01169 if (aasworld.areasettings[otherareanum].cluster) continue;
01170
01171 numseperatedclusters++;
01172
01173 AAS_FloodCluster_r(otherareanum, numseperatedclusters);
01174 AAS_FloodClusterReachabilities(numseperatedclusters);
01175 }
01176
01177 for (j = 0; j < aasworld.areasettings[i].numreachableareas; j++)
01178 {
01179 otherareanum = aasworld.reachability[
01180 aasworld.areasettings[i].firstreachablearea + j].areanum;
01181
01182 if (!otherareanum) continue;
01183
01184 if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL) continue;
01185
01186 if (aasworld.areasettings[otherareanum].cluster) continue;
01187
01188 numseperatedclusters++;
01189
01190 AAS_FloodCluster_r(otherareanum, numseperatedclusters);
01191 AAS_FloodClusterReachabilities(numseperatedclusters);
01192 }
01193
01194 if (numseperatedclusters != 2)
01195 {
01196 aasworld.areasettings[i].contents &= ~AREACONTENTS_CLUSTERPORTAL;
01197 nonclosingportals++;
01198
01199 i = 0;
01200 }