summaryrefslogtreecommitdiff
path: root/src/botlib/be_aas_cluster.c
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2006-05-16 20:41:57 +0000
committerTim Angus <tim@ngus.net>2006-05-16 20:41:57 +0000
commit5c0efda0ef811b2bafedb2b4f53b083a9b90e1b4 (patch)
tree972db3bf7fabe5293b383bb51fcb1aa74cc0e309 /src/botlib/be_aas_cluster.c
parentf68a49a146f20c7b6fc8e19dd1c4e6d58cf473e9 (diff)
* Removal of bot code
* Refactored botlib parsing code into qcommon
Diffstat (limited to 'src/botlib/be_aas_cluster.c')
-rw-r--r--src/botlib/be_aas_cluster.c1546
1 files changed, 0 insertions, 1546 deletions
diff --git a/src/botlib/be_aas_cluster.c b/src/botlib/be_aas_cluster.c
deleted file mode 100644
index 2805dc99..00000000
--- a/src/botlib/be_aas_cluster.c
+++ /dev/null
@@ -1,1546 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-Copyright (C) 2000-2006 Tim Angus
-
-This file is part of Tremulous.
-
-Tremulous 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.
-
-Tremulous 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 Tremulous; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-/*****************************************************************************
- * name: be_aas_cluster.c
- *
- * desc: area clustering
- *
- * $Archive: /MissionPack/code/botlib/be_aas_cluster.c $
- *
- *****************************************************************************/
-
-#include "../qcommon/q_shared.h"
-#include "l_memory.h"
-#include "l_script.h"
-#include "l_precomp.h"
-#include "l_struct.h"
-#include "l_log.h"
-#include "l_memory.h"
-#include "l_libvar.h"
-#include "aasfile.h"
-#include "botlib.h"
-#include "be_aas.h"
-#include "be_aas_funcs.h"
-#include "be_aas_def.h"
-
-extern botlib_import_t botimport;
-
-#define AAS_MAX_PORTALS 65536
-#define AAS_MAX_PORTALINDEXSIZE 65536
-#define AAS_MAX_CLUSTERS 65536
-//
-#define MAX_PORTALAREAS 1024
-
-// do not flood through area faces, only use reachabilities
-int nofaceflood = qtrue;
-
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_RemoveClusterAreas(void)
-{
- int i;
-
- for (i = 1; i < aasworld.numareas; i++)
- {
- aasworld.areasettings[i].cluster = 0;
- } //end for
-} //end of the function AAS_RemoveClusterAreas
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_ClearCluster(int clusternum)
-{
- int i;
-
- for (i = 1; i < aasworld.numareas; i++)
- {
- if (aasworld.areasettings[i].cluster == clusternum)
- {
- aasworld.areasettings[i].cluster = 0;
- } //end if
- } //end for
-} //end of the function AAS_ClearCluster
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_RemovePortalsClusterReference(int clusternum)
-{
- int portalnum;
-
- for (portalnum = 1; portalnum < aasworld.numportals; portalnum++)
- {
- if (aasworld.portals[portalnum].frontcluster == clusternum)
- {
- aasworld.portals[portalnum].frontcluster = 0;
- } //end if
- if (aasworld.portals[portalnum].backcluster == clusternum)
- {
- aasworld.portals[portalnum].backcluster = 0;
- } //end if
- } //end for
-} //end of the function AAS_RemovePortalsClusterReference
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int AAS_UpdatePortal(int areanum, int clusternum)
-{
- int portalnum;
- aas_portal_t *portal;
- aas_cluster_t *cluster;
-
- //find the portal of the area
- for (portalnum = 1; portalnum < aasworld.numportals; portalnum++)
- {
- if (aasworld.portals[portalnum].areanum == areanum) break;
- } //end for
- //
- if (portalnum == aasworld.numportals)
- {
- AAS_Error("no portal of area %d", areanum);
- return qtrue;
- } //end if
- //
- portal = &aasworld.portals[portalnum];
- //if the portal is already fully updated
- if (portal->frontcluster == clusternum) return qtrue;
- if (portal->backcluster == clusternum) return qtrue;
- //if the portal has no front cluster yet
- if (!portal->frontcluster)
- {
- portal->frontcluster = clusternum;
- } //end if
- //if the portal has no back cluster yet
- else if (!portal->backcluster)
- {
- portal->backcluster = clusternum;
- } //end else if
- else
- {
- //remove the cluster portal flag contents
- aasworld.areasettings[areanum].contents &= ~AREACONTENTS_CLUSTERPORTAL;
- Log_Write("portal area %d is seperating more than two clusters\r\n", areanum);
- return qfalse;
- } //end else
- if (aasworld.portalindexsize >= AAS_MAX_PORTALINDEXSIZE)
- {
- AAS_Error("AAS_MAX_PORTALINDEXSIZE");
- return qtrue;
- } //end if
- //set the area cluster number to the negative portal number
- aasworld.areasettings[areanum].cluster = -portalnum;
- //add the portal to the cluster using the portal index
- cluster = &aasworld.clusters[clusternum];
- aasworld.portalindex[cluster->firstportal + cluster->numportals] = portalnum;
- aasworld.portalindexsize++;
- cluster->numportals++;
- return qtrue;
-} //end of the function AAS_UpdatePortal
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int AAS_FloodClusterAreas_r(int areanum, int clusternum)
-{
- aas_area_t *area;
- aas_face_t *face;
- int facenum, i;
-
- //
- if (areanum <= 0 || areanum >= aasworld.numareas)
- {
- AAS_Error("AAS_FloodClusterAreas_r: areanum out of range");
- return qfalse;
- } //end if
- //if the area is already part of a cluster
- if (aasworld.areasettings[areanum].cluster > 0)
- {
- if (aasworld.areasettings[areanum].cluster == clusternum) return qtrue;
- //
- //there's a reachability going from one cluster to another only in one direction
- //
- AAS_Error("cluster %d touched cluster %d at area %d\r\n",
- clusternum, aasworld.areasettings[areanum].cluster, areanum);
- return qfalse;
- } //end if
- //don't add the cluster portal areas to the clusters
- if (aasworld.areasettings[areanum].contents & AREACONTENTS_CLUSTERPORTAL)
- {
- return AAS_UpdatePortal(areanum, clusternum);
- } //end if
- //set the area cluster number
- aasworld.areasettings[areanum].cluster = clusternum;
- aasworld.areasettings[areanum].clusterareanum =
- aasworld.clusters[clusternum].numareas;
- //the cluster has an extra area
- aasworld.clusters[clusternum].numareas++;
-
- area = &aasworld.areas[areanum];
- //use area faces to flood into adjacent areas
- if (!nofaceflood)
- {
- for (i = 0; i < area->numfaces; i++)
- {
- facenum = abs(aasworld.faceindex[area->firstface + i]);
- face = &aasworld.faces[facenum];
- if (face->frontarea == areanum)
- {
- if (face->backarea) if (!AAS_FloodClusterAreas_r(face->backarea, clusternum)) return qfalse;
- } //end if
- else
- {
- if (face->frontarea) if (!AAS_FloodClusterAreas_r(face->frontarea, clusternum)) return qfalse;
- } //end else
- } //end for
- } //end if
- //use the reachabilities to flood into other areas
- for (i = 0; i < aasworld.areasettings[areanum].numreachableareas; i++)
- {
- if (!aasworld.reachability[
- aasworld.areasettings[areanum].firstreachablearea + i].areanum)
- {
- continue;
- } //end if
- if (!AAS_FloodClusterAreas_r(aasworld.reachability[
- aasworld.areasettings[areanum].firstreachablearea + i].areanum, clusternum)) return qfalse;
- } //end for
- return qtrue;
-} //end of the function AAS_FloodClusterAreas_r
-//===========================================================================
-// try to flood from all areas without cluster into areas with a cluster set
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int AAS_FloodClusterAreasUsingReachabilities(int clusternum)
-{
- int i, j, areanum;
-
- for (i = 1; i < aasworld.numareas; i++)
- {
- //if this area already has a cluster set
- if (aasworld.areasettings[i].cluster)
- continue;
- //if this area is a cluster portal
- if (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)
- continue;
- //loop over the reachable areas from this area
- for (j = 0; j < aasworld.areasettings[i].numreachableareas; j++)
- {
- //the reachable area
- areanum = aasworld.reachability[aasworld.areasettings[i].firstreachablearea + j].areanum;
- //if this area is a cluster portal
- if (aasworld.areasettings[areanum].contents & AREACONTENTS_CLUSTERPORTAL)
- continue;
- //if this area has a cluster set
- if (aasworld.areasettings[areanum].cluster)
- {
- if (!AAS_FloodClusterAreas_r(i, clusternum))
- return qfalse;
- i = 0;
- break;
- } //end if
- } //end for
- } //end for
- return qtrue;
-} //end of the function AAS_FloodClusterAreasUsingReachabilities
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_NumberClusterPortals(int clusternum)
-{
- int i, portalnum;
- aas_cluster_t *cluster;
- aas_portal_t *portal;
-
- cluster = &aasworld.clusters[clusternum];
- for (i = 0; i < cluster->numportals; i++)
- {
- portalnum = aasworld.portalindex[cluster->firstportal + i];
- portal = &aasworld.portals[portalnum];
- if (portal->frontcluster == clusternum)
- {
- portal->clusterareanum[0] = cluster->numareas++;
- } //end if
- else
- {
- portal->clusterareanum[1] = cluster->numareas++;
- } //end else
- } //end for
-} //end of the function AAS_NumberClusterPortals
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_NumberClusterAreas(int clusternum)
-{
- int i, portalnum;
- aas_cluster_t *cluster;
- aas_portal_t *portal;
-
- aasworld.clusters[clusternum].numareas = 0;
- aasworld.clusters[clusternum].numreachabilityareas = 0;
- //number all areas in this cluster WITH reachabilities
- for (i = 1; i < aasworld.numareas; i++)
- {
- //
- if (aasworld.areasettings[i].cluster != clusternum) continue;
- //
- if (!AAS_AreaReachability(i)) continue;
- //
- aasworld.areasettings[i].clusterareanum = aasworld.clusters[clusternum].numareas;
- //the cluster has an extra area
- aasworld.clusters[clusternum].numareas++;
- aasworld.clusters[clusternum].numreachabilityareas++;
- } //end for
- //number all portals in this cluster WITH reachabilities
- cluster = &aasworld.clusters[clusternum];
- for (i = 0; i < cluster->numportals; i++)
- {
- portalnum = aasworld.portalindex[cluster->firstportal + i];
- portal = &aasworld.portals[portalnum];
- if (!AAS_AreaReachability(portal->areanum)) continue;
- if (portal->frontcluster == clusternum)
- {
- portal->clusterareanum[0] = cluster->numareas++;
- aasworld.clusters[clusternum].numreachabilityareas++;
- } //end if
- else
- {
- portal->clusterareanum[1] = cluster->numareas++;
- aasworld.clusters[clusternum].numreachabilityareas++;
- } //end else
- } //end for
- //number all areas in this cluster WITHOUT reachabilities
- for (i = 1; i < aasworld.numareas; i++)
- {
- //
- if (aasworld.areasettings[i].cluster != clusternum) continue;
- //
- if (AAS_AreaReachability(i)) continue;
- //
- aasworld.areasettings[i].clusterareanum = aasworld.clusters[clusternum].numareas;
- //the cluster has an extra area
- aasworld.clusters[clusternum].numareas++;
- } //end for
- //number all portals in this cluster WITHOUT reachabilities
- cluster = &aasworld.clusters[clusternum];
- for (i = 0; i < cluster->numportals; i++)
- {
- portalnum = aasworld.portalindex[cluster->firstportal + i];
- portal = &aasworld.portals[portalnum];
- if (AAS_AreaReachability(portal->areanum)) continue;
- if (portal->frontcluster == clusternum)
- {
- portal->clusterareanum[0] = cluster->numareas++;
- } //end if
- else
- {
- portal->clusterareanum[1] = cluster->numareas++;
- } //end else
- } //end for
-} //end of the function AAS_NumberClusterAreas
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int AAS_FindClusters(void)
-{
- int i;
- aas_cluster_t *cluster;
-
- AAS_RemoveClusterAreas();
- //
- for (i = 1; i < aasworld.numareas; i++)
- {
- //if the area is already part of a cluster
- if (aasworld.areasettings[i].cluster)
- continue;
- // if not flooding through faces only use areas that have reachabilities
- if (nofaceflood)
- {
- if (!aasworld.areasettings[i].numreachableareas)
- continue;
- } //end if
- //if the area is a cluster portal
- if (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)
- continue;
- if (aasworld.numclusters >= AAS_MAX_CLUSTERS)
- {
- AAS_Error("AAS_MAX_CLUSTERS");
- return qfalse;
- } //end if
- cluster = &aasworld.clusters[aasworld.numclusters];
- cluster->numareas = 0;
- cluster->numreachabilityareas = 0;
- cluster->firstportal = aasworld.portalindexsize;
- cluster->numportals = 0;
- //flood the areas in this cluster
- if (!AAS_FloodClusterAreas_r(i, aasworld.numclusters))
- return qfalse;
- if (!AAS_FloodClusterAreasUsingReachabilities(aasworld.numclusters))
- return qfalse;
- //number the cluster areas
- //AAS_NumberClusterPortals(aasworld.numclusters);
- AAS_NumberClusterAreas(aasworld.numclusters);
- //Log_Write("cluster %d has %d areas\r\n", aasworld.numclusters, cluster->numareas);
- aasworld.numclusters++;
- } //end for
- return qtrue;
-} //end of the function AAS_FindClusters
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_CreatePortals(void)
-{
- int i;
- aas_portal_t *portal;
-
- for (i = 1; i < aasworld.numareas; i++)
- {
- //if the area is a cluster portal
- if (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)
- {
- if (aasworld.numportals >= AAS_MAX_PORTALS)
- {
- AAS_Error("AAS_MAX_PORTALS");
- return;
- } //end if
- portal = &aasworld.portals[aasworld.numportals];
- portal->areanum = i;
- portal->frontcluster = 0;
- portal->backcluster = 0;
- aasworld.numportals++;
- } //end if
- } //end for
-} //end of the function AAS_CreatePortals
-/*
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int AAS_MapContainsTeleporters(void)
-{
- bsp_entity_t *entities, *ent;
- char *classname;
-
- entities = AAS_ParseBSPEntities();
-
- for (ent = entities; ent; ent = ent->next)
- {
- classname = AAS_ValueForBSPEpairKey(ent, "classname");
- if (classname && !strcmp(classname, "misc_teleporter"))
- {
- AAS_FreeBSPEntities(entities);
- return qtrue;
- } //end if
- } //end for
- return qfalse;
-} //end of the function AAS_MapContainsTeleporters
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int AAS_NonConvexFaces(aas_face_t *face1, aas_face_t *face2, int side1, int side2)
-{
- int i, j, edgenum;
- aas_plane_t *plane1, *plane2;
- aas_edge_t *edge;
-
-
- plane1 = &aasworld.planes[face1->planenum ^ side1];
- plane2 = &aasworld.planes[face2->planenum ^ side2];
-
- //check if one of the points of face1 is at the back of the plane of face2
- for (i = 0; i < face1->numedges; i++)
- {
- edgenum = abs(aasworld.edgeindex[face1->firstedge + i]);
- edge = &aasworld.edges[edgenum];
- for (j = 0; j < 2; j++)
- {
- if (DotProduct(plane2->normal, aasworld.vertexes[edge->v[j]]) -
- plane2->dist < -0.01) return qtrue;
- } //end for
- } //end for
- for (i = 0; i < face2->numedges; i++)
- {
- edgenum = abs(aasworld.edgeindex[face2->firstedge + i]);
- edge = &aasworld.edges[edgenum];
- for (j = 0; j < 2; j++)
- {
- if (DotProduct(plane1->normal, aasworld.vertexes[edge->v[j]]) -
- plane1->dist < -0.01) return qtrue;
- } //end for
- } //end for
-
- return qfalse;
-} //end of the function AAS_NonConvexFaces
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-qboolean AAS_CanMergeAreas(int *areanums, int numareas)
-{
- int i, j, s, face1num, face2num, side1, side2, fn1, fn2;
- aas_face_t *face1, *face2;
- aas_area_t *area1, *area2;
-
- for (i = 0; i < numareas; i++)
- {
- area1 = &aasworld.areas[areanums[i]];
- for (fn1 = 0; fn1 < area1->numfaces; fn1++)
- {
- face1num = abs(aasworld.faceindex[area1->firstface + fn1]);
- face1 = &aasworld.faces[face1num];
- side1 = face1->frontarea != areanums[i];
- //check if the face isn't a shared one with one of the other areas
- for (s = 0; s < numareas; s++)
- {
- if (s == i) continue;
- if (face1->frontarea == s || face1->backarea == s) break;
- } //end for
- //if the face was a shared one
- if (s != numareas) continue;
- //
- for (j = 0; j < numareas; j++)
- {
- if (j == i) continue;
- area2 = &aasworld.areas[areanums[j]];
- for (fn2 = 0; fn2 < area2->numfaces; fn2++)
- {
- face2num = abs(aasworld.faceindex[area2->firstface + fn2]);
- face2 = &aasworld.faces[face2num];
- side2 = face2->frontarea != areanums[j];
- //check if the face isn't a shared one with one of the other areas
- for (s = 0; s < numareas; s++)
- {
- if (s == j) continue;
- if (face2->frontarea == s || face2->backarea == s) break;
- } //end for
- //if the face was a shared one
- if (s != numareas) continue;
- //
- if (AAS_NonConvexFaces(face1, face2, side1, side2)) return qfalse;
- } //end for
- } //end for
- } //end for
- } //end for
- return qtrue;
-} //end of the function AAS_CanMergeAreas
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-qboolean AAS_NonConvexEdges(aas_edge_t *edge1, aas_edge_t *edge2, int side1, int side2, int planenum)
-{
- int i;
- vec3_t edgevec1, edgevec2, normal1, normal2;
- float dist1, dist2;
- aas_plane_t *plane;
-
- plane = &aasworld.planes[planenum];
- VectorSubtract(aasworld.vertexes[edge1->v[1]], aasworld.vertexes[edge1->v[0]], edgevec1);
- VectorSubtract(aasworld.vertexes[edge2->v[1]], aasworld.vertexes[edge2->v[0]], edgevec2);
- if (side1) VectorInverse(edgevec1);
- if (side2) VectorInverse(edgevec2);
- //
- CrossProduct(edgevec1, plane->normal, normal1);
- dist1 = DotProduct(normal1, aasworld.vertexes[edge1->v[0]]);
- CrossProduct(edgevec2, plane->normal, normal2);
- dist2 = DotProduct(normal2, aasworld.vertexes[edge2->v[0]]);
-
- for (i = 0; i < 2; i++)
- {
- if (DotProduct(aasworld.vertexes[edge1->v[i]], normal2) - dist2 < -0.01) return qfalse;
- } //end for
- for (i = 0; i < 2; i++)
- {
- if (DotProduct(aasworld.vertexes[edge2->v[i]], normal1) - dist1 < -0.01) return qfalse;
- } //end for
- return qtrue;
-} //end of the function AAS_NonConvexEdges
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-qboolean AAS_CanMergeFaces(int *facenums, int numfaces, int planenum)
-{
- int i, j, s, edgenum1, edgenum2, side1, side2, en1, en2, ens;
- aas_face_t *face1, *face2, *otherface;
- aas_edge_t *edge1, *edge2;
-
- for (i = 0; i < numfaces; i++)
- {
- face1 = &aasworld.faces[facenums[i]];
- for (en1 = 0; en1 < face1->numedges; en1++)
- {
- edgenum1 = aasworld.edgeindex[face1->firstedge + en1];
- side1 = (edgenum1 < 0) ^ (face1->planenum != planenum);
- edgenum1 = abs(edgenum1);
- edge1 = &aasworld.edges[edgenum1];
- //check if the edge is shared with another face
- for (s = 0; s < numfaces; s++)
- {
- if (s == i) continue;
- otherface = &aasworld.faces[facenums[s]];
- for (ens = 0; ens < otherface->numedges; ens++)
- {
- if (edgenum1 == abs(aasworld.edgeindex[otherface->firstedge + ens])) break;
- } //end for
- if (ens != otherface->numedges) break;
- } //end for
- //if the edge was shared
- if (s != numfaces) continue;
- //
- for (j = 0; j < numfaces; j++)
- {
- if (j == i) continue;
- face2 = &aasworld.faces[facenums[j]];
- for (en2 = 0; en2 < face2->numedges; en2++)
- {
- edgenum2 = aasworld.edgeindex[face2->firstedge + en2];
- side2 = (edgenum2 < 0) ^ (face2->planenum != planenum);
- edgenum2 = abs(edgenum2);
- edge2 = &aasworld.edges[edgenum2];
- //check if the edge is shared with another face
- for (s = 0; s < numfaces; s++)
- {
- if (s == i) continue;
- otherface = &aasworld.faces[facenums[s]];
- for (ens = 0; ens < otherface->numedges; ens++)
- {
- if (edgenum2 == abs(aasworld.edgeindex[otherface->firstedge + ens])) break;
- } //end for
- if (ens != otherface->numedges) break;
- } //end for
- //if the edge was shared
- if (s != numfaces) continue;
- //
- if (AAS_NonConvexEdges(edge1, edge2, side1, side2, planenum)) return qfalse;
- } //end for
- } //end for
- } //end for
- } //end for
- return qtrue;
-} //end of the function AAS_CanMergeFaces*/
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_ConnectedAreas_r(int *areanums, int numareas, int *connectedareas, int curarea)
-{
- int i, j, otherareanum, facenum;
- aas_area_t *area;
- aas_face_t *face;
-
- connectedareas[curarea] = qtrue;
- area = &aasworld.areas[areanums[curarea]];
- for (i = 0; i < area->numfaces; i++)
- {
- facenum = abs(aasworld.faceindex[area->firstface + i]);
- face = &aasworld.faces[facenum];
- //if the face is solid
- if (face->faceflags & FACE_SOLID) continue;
- //get the area at the other side of the face
- if (face->frontarea != areanums[curarea]) otherareanum = face->frontarea;
- else otherareanum = face->backarea;
- //check if the face is leading to one of the other areas
- for (j = 0; j < numareas; j++)
- {
- if (areanums[j] == otherareanum) break;
- } //end for
- //if the face isn't leading to one of the other areas
- if (j == numareas) continue;
- //if the other area is already connected
- if (connectedareas[j]) continue;
- //recursively proceed with the other area
- AAS_ConnectedAreas_r(areanums, numareas, connectedareas, j);
- } //end for
-} //end of the function AAS_ConnectedAreas_r
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-qboolean AAS_ConnectedAreas(int *areanums, int numareas)
-{
- int connectedareas[MAX_PORTALAREAS], i;
-
- Com_Memset(connectedareas, 0, sizeof(connectedareas));
- if (numareas < 1) return qfalse;
- if (numareas == 1) return qtrue;
- AAS_ConnectedAreas_r(areanums, numareas, connectedareas, 0);
- for (i = 0; i < numareas; i++)
- {
- if (!connectedareas[i]) return qfalse;
- } //end for
- return qtrue;
-} //end of the function AAS_ConnectedAreas
-//===========================================================================
-// gets adjacent areas with less presence types recursively
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int AAS_GetAdjacentAreasWithLessPresenceTypes_r(int *areanums, int numareas, int curareanum)
-{
- int i, j, presencetype, otherpresencetype, otherareanum, facenum;
- aas_area_t *area;
- aas_face_t *face;
-
- areanums[numareas++] = curareanum;
- area = &aasworld.areas[curareanum];
- presencetype = aasworld.areasettings[curareanum].presencetype;
- for (i = 0; i < area->numfaces; i++)
- {
- facenum = abs(aasworld.faceindex[area->firstface + i]);
- face = &aasworld.faces[facenum];
- //if the face is solid
- if (face->faceflags & FACE_SOLID) continue;
- //the area at the other side of the face
- if (face->frontarea != curareanum) otherareanum = face->frontarea;
- else otherareanum = face->backarea;
- //
- otherpresencetype = aasworld.areasettings[otherareanum].presencetype;
- //if the other area has less presence types
- if ((presencetype & ~otherpresencetype) &&
- !(otherpresencetype & ~presencetype))
- {
- //check if the other area isn't already in the list
- for (j = 0; j < numareas; j++)
- {
- if (otherareanum == areanums[j]) break;
- } //end for
- //if the other area isn't already in the list
- if (j == numareas)
- {
- if (numareas >= MAX_PORTALAREAS)
- {
- AAS_Error("MAX_PORTALAREAS");
- return numareas;
- } //end if
- numareas = AAS_GetAdjacentAreasWithLessPresenceTypes_r(areanums, numareas, otherareanum);
- } //end if
- } //end if
- } //end for
- return numareas;
-} //end of the function AAS_GetAdjacentAreasWithLessPresenceTypes_r
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int AAS_CheckAreaForPossiblePortals(int areanum)
-{
- int i, j, k, fen, ben, frontedgenum, backedgenum, facenum;
- int areanums[MAX_PORTALAREAS], numareas, otherareanum;
- int numareafrontfaces[MAX_PORTALAREAS], numareabackfaces[MAX_PORTALAREAS];
- int frontfacenums[MAX_PORTALAREAS], backfacenums[MAX_PORTALAREAS];
- int numfrontfaces, numbackfaces;
- int frontareanums[MAX_PORTALAREAS], backareanums[MAX_PORTALAREAS];
- int numfrontareas, numbackareas;
- int frontplanenum, backplanenum, faceplanenum;
- aas_area_t *area;
- aas_face_t *frontface, *backface, *face;
-
- //if it isn't already a portal
- if (aasworld.areasettings[areanum].contents & AREACONTENTS_CLUSTERPORTAL) return 0;
- //it must be a grounded area
- if (!(aasworld.areasettings[areanum].areaflags & AREA_GROUNDED)) return 0;
- //
- Com_Memset(numareafrontfaces, 0, sizeof(numareafrontfaces));
- Com_Memset(numareabackfaces, 0, sizeof(numareabackfaces));
- numareas = numfrontfaces = numbackfaces = 0;
- numfrontareas = numbackareas = 0;
- frontplanenum = backplanenum = -1;
- //add any adjacent areas with less presence types
- numareas = AAS_GetAdjacentAreasWithLessPresenceTypes_r(areanums, 0, areanum);
- //
- for (i = 0; i < numareas; i++)
- {
- area = &aasworld.areas[areanums[i]];
- for (j = 0; j < area->numfaces; j++)
- {
- facenum = abs(aasworld.faceindex[area->firstface + j]);
- face = &aasworld.faces[facenum];
- //if the face is solid
- if (face->faceflags & FACE_SOLID) continue;
- //check if the face is shared with one of the other areas
- for (k = 0; k < numareas; k++)
- {
- if (k == i) continue;
- if (face->frontarea == areanums[k] || face->backarea == areanums[k]) break;
- } //end for
- //if the face is shared
- if (k != numareas) continue;
- //the number of the area at the other side of the face
- if (face->frontarea == areanums[i]) otherareanum = face->backarea;
- else otherareanum = face->frontarea;
- //if the other area already is a cluter portal
- if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL) return 0;
- //number of the plane of the area
- faceplanenum = face->planenum & ~1;
- //
- if (frontplanenum < 0 || faceplanenum == frontplanenum)
- {
- frontplanenum = faceplanenum;
- frontfacenums[numfrontfaces++] = facenum;
- for (k = 0; k < numfrontareas; k++)
- {
- if (frontareanums[k] == otherareanum) break;
- } //end for
- if (k == numfrontareas) frontareanums[numfrontareas++] = otherareanum;
- numareafrontfaces[i]++;
- } //end if
- else if (backplanenum < 0 || faceplanenum == backplanenum)
- {
- backplanenum = faceplanenum;
- backfacenums[numbackfaces++] = facenum;
- for (k = 0; k < numbackareas; k++)
- {
- if (backareanums[k] == otherareanum) break;
- } //end for
- if (k == numbackareas) backareanums[numbackareas++] = otherareanum;
- numareabackfaces[i]++;
- } //end else
- else
- {
- return 0;
- } //end else
- } //end for
- } //end for
- //every area should have at least one front face and one back face
- for (i = 0; i < numareas; i++)
- {
- if (!numareafrontfaces[i] || !numareabackfaces[i]) return 0;
- } //end for
- //the front areas should all be connected
- if (!AAS_ConnectedAreas(frontareanums, numfrontareas)) return 0;
- //the back areas should all be connected
- if (!AAS_ConnectedAreas(backareanums, numbackareas)) return 0;
- //none of the front faces should have a shared edge with a back face
- for (i = 0; i < numfrontfaces; i++)
- {
- frontface = &aasworld.faces[frontfacenums[i]];
- for (fen = 0; fen < frontface->numedges; fen++)
- {
- frontedgenum = abs(aasworld.edgeindex[frontface->firstedge + fen]);
- for (j = 0; j < numbackfaces; j++)
- {
- backface = &aasworld.faces[backfacenums[j]];
- for (ben = 0; ben < backface->numedges; ben++)
- {
- backedgenum = abs(aasworld.edgeindex[backface->firstedge + ben]);
- if (frontedgenum == backedgenum) break;
- } //end for
- if (ben != backface->numedges) break;
- } //end for
- if (j != numbackfaces) break;
- } //end for
- if (fen != frontface->numedges) break;
- } //end for
- if (i != numfrontfaces) return 0;
- //set the cluster portal contents
- for (i = 0; i < numareas; i++)
- {
- aasworld.areasettings[areanums[i]].contents |= AREACONTENTS_CLUSTERPORTAL;
- //this area can be used as a route portal
- aasworld.areasettings[areanums[i]].contents |= AREACONTENTS_ROUTEPORTAL;
- Log_Write("possible portal: %d\r\n", areanums[i]);
- } //end for
- //
- return numareas;
-} //end of the function AAS_CheckAreaForPossiblePortals
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_FindPossiblePortals(void)
-{
- int i, numpossibleportals;
-
- numpossibleportals = 0;
- for (i = 1; i < aasworld.numareas; i++)
- {
- numpossibleportals += AAS_CheckAreaForPossiblePortals(i);
- } //end for
- botimport.Print(PRT_MESSAGE, "\r%6d possible portal areas\n", numpossibleportals);
-} //end of the function AAS_FindPossiblePortals
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_RemoveAllPortals(void)
-{
- int i;
-
- for (i = 1; i < aasworld.numareas; i++)
- {
- aasworld.areasettings[i].contents &= ~AREACONTENTS_CLUSTERPORTAL;
- } //end for
-} //end of the function AAS_RemoveAllPortals
-
-#if 0
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_FloodCluster_r(int areanum, int clusternum)
-{
- int i, otherareanum;
- aas_face_t *face;
- aas_area_t *area;
-
- //set cluster mark
- aasworld.areasettings[areanum].cluster = clusternum;
- //if the area is a portal
- //if (aasworld.areasettings[areanum].contents & AREACONTENTS_CLUSTERPORTAL) return;
- //
- area = &aasworld.areas[areanum];
- //use area faces to flood into adjacent areas
- for (i = 0; i < area->numfaces; i++)
- {
- face = &aasworld.faces[abs(aasworld.faceindex[area->firstface + i])];
- //
- if (face->frontarea != areanum) otherareanum = face->frontarea;
- else otherareanum = face->backarea;
- //if there's no area at the other side
- if (!otherareanum) continue;
- //if the area is a portal
- if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL) continue;
- //if the area is already marked
- if (aasworld.areasettings[otherareanum].cluster) continue;
- //
- AAS_FloodCluster_r(otherareanum, clusternum);
- } //end for
- //use the reachabilities to flood into other areas
- for (i = 0; i < aasworld.areasettings[areanum].numreachableareas; i++)
- {
- otherareanum = aasworld.reachability[
- aasworld.areasettings[areanum].firstreachablearea + i].areanum;
- if (!otherareanum)
- {
- continue;
- AAS_Error("reachability %d has zero area\n", aasworld.areasettings[areanum].firstreachablearea + i);
- } //end if
- //if the area is a portal
- if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL) continue;
- //if the area is already marked
- if (aasworld.areasettings[otherareanum].cluster) continue;
- //
- AAS_FloodCluster_r(otherareanum, clusternum);
- } //end for
-} //end of the function AAS_FloodCluster_r
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_RemoveTeleporterPortals(void)
-{
- int i, j, areanum;
-
- for (i = 1; i < aasworld.numareas; i++)
- {
- for (j = 0; j < aasworld.areasettings[i].numreachableareas; j++)
- {
- areanum = aasworld.reachability[aasworld.areasettings[i].firstreachablearea + j].areanum;
- if (aasworld.reachability[aasworld.areasettings[i].firstreachablearea + j].traveltype == TRAVEL_TELEPORT)
- {
- aasworld.areasettings[i].contents &= ~AREACONTENTS_CLUSTERPORTAL;
- aasworld.areasettings[areanum].contents &= ~AREACONTENTS_CLUSTERPORTAL;
- break;
- } //end if
- } //end for
- } //end for
-} //end of the function AAS_RemoveTeleporterPortals
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_FloodClusterReachabilities(int clusternum)
-{
- int i, j, areanum;
-
- for (i = 1; i < aasworld.numareas; i++)
- {
- //if this area already has a cluster set
- if (aasworld.areasettings[i].cluster) continue;
- //if this area is a cluster portal
- if (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL) continue;
- //loop over the reachable areas from this area
- for (j = 0; j < aasworld.areasettings[i].numreachableareas; j++)
- {
- //the reachable area
- areanum = aasworld.reachability[aasworld.areasettings[i].firstreachablearea + j].areanum;
- //if this area is a cluster portal
- if (aasworld.areasettings[areanum].contents & AREACONTENTS_CLUSTERPORTAL) continue;
- //if this area has a cluster set
- if (aasworld.areasettings[areanum].cluster == clusternum)
- {
- AAS_FloodCluster_r(i, clusternum);
- i = 0;
- break;
- } //end if
- } //end for
- } //end for
-} //end of the function AAS_FloodClusterReachabilities
-
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_RemoveNotClusterClosingPortals(void)
-{
- int i, j, k, facenum, otherareanum, nonclosingportals;
- aas_area_t *area;
- aas_face_t *face;
-
- AAS_RemoveTeleporterPortals();
- //
- nonclosingportals = 0;
- for (i = 1; i < aasworld.numareas; i++)
- {
- if (!(aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)) continue;
- //find a non-portal area adjacent to the portal area and flood
- //the cluster from there
- area = &aasworld.areas[i];
- for (j = 0; j < area->numfaces; j++)
- {
- facenum = abs(aasworld.faceindex[area->firstface + j]);
- face = &aasworld.faces[facenum];
- //
- if (face->frontarea != i) otherareanum = face->frontarea;
- else otherareanum = face->backarea;
- //
- if (!otherareanum) continue;
- //
- if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL)
- {
- continue;
- } //end if
- //reset all cluster fields
- AAS_RemoveClusterAreas();
- //
- AAS_FloodCluster_r(otherareanum, 1);
- AAS_FloodClusterReachabilities(1);
- //check if all adjacent non-portal areas have a cluster set
- for (k = 0; k < area->numfaces; k++)
- {
- facenum = abs(aasworld.faceindex[area->firstface + k]);
- face = &aasworld.faces[facenum];
- //
- if (face->frontarea != i) otherareanum = face->frontarea;
- else otherareanum = face->backarea;
- //
- if (!otherareanum) continue;
- //
- if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL)
- {
- continue;
- } //end if
- //
- if (!aasworld.areasettings[otherareanum].cluster) break;
- } //end for
- //if all adjacent non-portal areas have a cluster set then the portal
- //didn't seal a cluster
- if (k >= area->numfaces)
- {
- aasworld.areasettings[i].contents &= ~AREACONTENTS_CLUSTERPORTAL;
- nonclosingportals++;
- //recheck all the other portals again
- i = 0;
- break;
- } //end if
- } //end for
- } //end for
- botimport.Print(PRT_MESSAGE, "\r%6d non closing portals removed\n", nonclosingportals);
-} //end of the function AAS_RemoveNotClusterClosingPortals
-
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-
-void AAS_RemoveNotClusterClosingPortals(void)
-{
- int i, j, facenum, otherareanum, nonclosingportals, numseperatedclusters;
- aas_area_t *area;
- aas_face_t *face;
-
- AAS_RemoveTeleporterPortals();
- //
- nonclosingportals = 0;
- for (i = 1; i < aasworld.numareas; i++)
- {
- if (!(aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)) continue;
- //
- numseperatedclusters = 0;
- //reset all cluster fields
- AAS_RemoveClusterAreas();
- //find a non-portal area adjacent to the portal area and flood
- //the cluster from there
- area = &aasworld.areas[i];
- for (j = 0; j < area->numfaces; j++)
- {
- facenum = abs(aasworld.faceindex[area->firstface + j]);
- face = &aasworld.faces[facenum];
- //
- if (face->frontarea != i) otherareanum = face->frontarea;
- else otherareanum = face->backarea;
- //if not solid at the other side of the face
- if (!otherareanum) continue;
- //don't flood into other portals
- if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL) continue;
- //if the area already has a cluster set
- if (aasworld.areasettings[otherareanum].cluster) continue;
- //another cluster is seperated by this portal
- numseperatedclusters++;
- //flood the cluster
- AAS_FloodCluster_r(otherareanum, numseperatedclusters);
- AAS_FloodClusterReachabilities(numseperatedclusters);
- } //end for
- //use the reachabilities to flood into other areas
- for (j = 0; j < aasworld.areasettings[i].numreachableareas; j++)
- {
- otherareanum = aasworld.reachability[
- aasworld.areasettings[i].firstreachablearea + j].areanum;
- //this should never be qtrue but we check anyway
- if (!otherareanum) continue;
- //don't flood into other portals
- if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL) continue;
- //if the area already has a cluster set
- if (aasworld.areasettings[otherareanum].cluster) continue;
- //another cluster is seperated by this portal
- numseperatedclusters++;
- //flood the cluster
- AAS_FloodCluster_r(otherareanum, numseperatedclusters);
- AAS_FloodClusterReachabilities(numseperatedclusters);
- } //end for
- //a portal must seperate no more and no less than 2 clusters
- if (numseperatedclusters != 2)
- {
- aasworld.areasettings[i].contents &= ~AREACONTENTS_CLUSTERPORTAL;
- nonclosingportals++;
- //recheck all the other portals again
- i = 0;
- } //end if
- } //end for
- botimport.Print(PRT_MESSAGE, "\r%6d non closing portals removed\n", nonclosingportals);
-} //end of the function AAS_RemoveNotClusterClosingPortals
-
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-
-void AAS_AddTeleporterPortals(void)
-{
- int j, area2num, facenum, otherareanum;
- char *target, *targetname, *classname;
- bsp_entity_t *entities, *ent, *dest;
- vec3_t origin, destorigin, mins, maxs, end;
- vec3_t bbmins, bbmaxs;
- aas_area_t *area;
- aas_face_t *face;
- aas_trace_t trace;
- aas_link_t *areas, *link;
-
- entities = AAS_ParseBSPEntities();
-
- for (ent = entities; ent; ent = ent->next)
- {
- classname = AAS_ValueForBSPEpairKey(ent, "classname");
- if (classname && !strcmp(classname, "misc_teleporter"))
- {
- if (!AAS_VectorForBSPEpairKey(ent, "origin", origin))
- {
- botimport.Print(PRT_ERROR, "teleporter (%s) without origin\n", target);
- continue;
- } //end if
- //
- target = AAS_ValueForBSPEpairKey(ent, "target");
- if (!target)
- {
- botimport.Print(PRT_ERROR, "teleporter (%s) without target\n", target);
- continue;
- } //end if
- for (dest = entities; dest; dest = dest->next)
- {
- classname = AAS_ValueForBSPEpairKey(dest, "classname");
- if (classname && !strcmp(classname, "misc_teleporter_dest"))
- {
- targetname = AAS_ValueForBSPEpairKey(dest, "targetname");
- if (targetname && !strcmp(targetname, target))
- {
- break;
- } //end if
- } //end if
- } //end for
- if (!dest)
- {
- botimport.Print(PRT_ERROR, "teleporter without destination (%s)\n", target);
- continue;
- } //end if
- if (!AAS_VectorForBSPEpairKey(dest, "origin", destorigin))
- {
- botimport.Print(PRT_ERROR, "teleporter destination (%s) without origin\n", target);
- continue;
- } //end if
- destorigin[2] += 24; //just for q2e1m2, the dork has put the telepads in the ground
- VectorCopy(destorigin, end);
- end[2] -= 100;
- trace = AAS_TraceClientBBox(destorigin, end, PRESENCE_CROUCH, -1);
- if (trace.startsolid)
- {
- botimport.Print(PRT_ERROR, "teleporter destination (%s) in solid\n", target);
- continue;
- } //end if
- VectorCopy(trace.endpos, destorigin);
- area2num = AAS_PointAreaNum(destorigin);
- //reset all cluster fields
- for (j = 0; j < aasworld.numareas; j++)
- {
- aasworld.areasettings[j].cluster = 0;
- } //end for
- //
- VectorSet(mins, -8, -8, 8);
- VectorSet(maxs, 8, 8, 24);
- //
- AAS_PresenceTypeBoundingBox(PRESENCE_CROUCH, bbmins, bbmaxs);
- //
- VectorAdd(origin, mins, mins);
- VectorAdd(origin, maxs, maxs);
- //add bounding box size
- VectorSubtract(mins, bbmaxs, mins);
- VectorSubtract(maxs, bbmins, maxs);
- //link an invalid (-1) entity
- areas = AAS_AASLinkEntity(mins, maxs, -1);
- //
- for (link = areas; link; link = link->next_area)
- {
- if (!AAS_AreaGrounded(link->areanum)) continue;
- //add the teleporter portal mark
- aasworld.areasettings[link->areanum].contents |= AREACONTENTS_CLUSTERPORTAL |
- AREACONTENTS_TELEPORTAL;
- } //end for
- //
- for (link = areas; link; link = link->next_area)
- {
- if (!AAS_AreaGrounded(link->areanum)) continue;
- //find a non-portal area adjacent to the portal area and flood
- //the cluster from there
- area = &aasworld.areas[link->areanum];
- for (j = 0; j < area->numfaces; j++)
- {
- facenum = abs(aasworld.faceindex[area->firstface + j]);
- face = &aasworld.faces[facenum];
- //
- if (face->frontarea != link->areanum) otherareanum = face->frontarea;
- else otherareanum = face->backarea;
- //
- if (!otherareanum) continue;
- //
- if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL)
- {
- continue;
- } //end if
- //
- AAS_FloodCluster_r(otherareanum, 1);
- } //end for
- } //end for
- //if the teleport destination IS in the same cluster
- if (aasworld.areasettings[area2num].cluster)
- {
- for (link = areas; link; link = link->next_area)
- {
- if (!AAS_AreaGrounded(link->areanum)) continue;
- //add the teleporter portal mark
- aasworld.areasettings[link->areanum].contents &= ~(AREACONTENTS_CLUSTERPORTAL |
- AREACONTENTS_TELEPORTAL);
- } //end for
- } //end if
- } //end if
- } //end for
- AAS_FreeBSPEntities(entities);
-} //end of the function AAS_AddTeleporterPortals
-
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_AddTeleporterPortals(void)
-{
- int i, j, areanum;
-
- for (i = 1; i < aasworld.numareas; i++)
- {
- for (j = 0; j < aasworld.areasettings[i].numreachableareas; j++)
- {
- if (aasworld.reachability[aasworld.areasettings[i].firstreachablearea + j].traveltype != TRAVEL_TELEPORT) continue;
- areanum = aasworld.reachability[aasworld.areasettings[i].firstreachablearea + j].areanum;
- aasworld.areasettings[areanum].contents |= AREACONTENTS_CLUSTERPORTAL;
- } //end for
- } //end for
-} //end of the function AAS_AddTeleporterPortals
-
-#endif
-
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-int AAS_TestPortals(void)
-{
- int i;
- aas_portal_t *portal;
-
- for (i = 1; i < aasworld.numportals; i++)
- {
- portal = &aasworld.portals[i];
- if (!portal->frontcluster)
- {
- aasworld.areasettings[portal->areanum].contents &= ~AREACONTENTS_CLUSTERPORTAL;
- Log_Write("portal area %d has no front cluster\r\n", portal->areanum);
- return qfalse;
- } //end if
- if (!portal->backcluster)
- {
- aasworld.areasettings[portal->areanum].contents &= ~AREACONTENTS_CLUSTERPORTAL;
- Log_Write("portal area %d has no back cluster\r\n", portal->areanum);
- return qfalse;
- } //end if
- } //end for
- return qtrue;
-} //end of the function
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_CountForcedClusterPortals(void)
-{
- int num, i;
-
- num = 0;
- for (i = 1; i < aasworld.numareas; i++)
- {
- if (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)
- {
- Log_Write("area %d is a forced portal area\r\n", i);
- num++;
- } //end if
- } //end for
- botimport.Print(PRT_MESSAGE, "%6d forced portal areas\n", num);
-} //end of the function AAS_CountForcedClusterPortals
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_CreateViewPortals(void)
-{
- int i;
-
- for (i = 1; i < aasworld.numareas; i++)
- {
- if (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)
- {
- aasworld.areasettings[i].contents |= AREACONTENTS_VIEWPORTAL;
- } //end if
- } //end for
-} //end of the function AAS_CreateViewPortals
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_SetViewPortalsAsClusterPortals(void)
-{
- int i;
-
- for (i = 1; i < aasworld.numareas; i++)
- {
- if (aasworld.areasettings[i].contents & AREACONTENTS_VIEWPORTAL)
- {
- aasworld.areasettings[i].contents |= AREACONTENTS_CLUSTERPORTAL;
- } //end if
- } //end for
-} //end of the function AAS_SetViewPortalsAsClusterPortals
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void AAS_InitClustering(void)
-{
- int i, removedPortalAreas;
- int n, total, numreachabilityareas;
-
- if (!aasworld.loaded) return;
- //if there are clusters
- if (aasworld.numclusters >= 1)
- {
-#ifndef BSPC
- //if clustering isn't forced
- if (!((int)LibVarGetValue("forceclustering")) &&
- !((int)LibVarGetValue("forcereachability"))) return;
-#endif
- } //end if
- //set all view portals as cluster portals in case we re-calculate the reachabilities and clusters (with -reach)
- AAS_SetViewPortalsAsClusterPortals();
- //count the number of forced cluster portals
- AAS_CountForcedClusterPortals();
- //remove all area cluster marks
- AAS_RemoveClusterAreas();
- //find possible cluster portals
- AAS_FindPossiblePortals();
- //craete portals to for the bot view
- AAS_CreateViewPortals();
- //remove all portals that are not closing a cluster
- //AAS_RemoveNotClusterClosingPortals();
- //initialize portal memory
- if (aasworld.portals) FreeMemory(aasworld.portals);
- aasworld.portals = (aas_portal_t *) GetClearedMemory(AAS_MAX_PORTALS * sizeof(aas_portal_t));
- //initialize portal index memory
- if (aasworld.portalindex) FreeMemory(aasworld.portalindex);
- aasworld.portalindex = (aas_portalindex_t *) GetClearedMemory(AAS_MAX_PORTALINDEXSIZE * sizeof(aas_portalindex_t));
- //initialize cluster memory
- if (aasworld.clusters) FreeMemory(aasworld.clusters);
- aasworld.clusters = (aas_cluster_t *) GetClearedMemory(AAS_MAX_CLUSTERS * sizeof(aas_cluster_t));
- //
- removedPortalAreas = 0;
- botimport.Print(PRT_MESSAGE, "\r%6d removed portal areas", removedPortalAreas);
- while(1)
- {
- botimport.Print(PRT_MESSAGE, "\r%6d", removedPortalAreas);
- //initialize the number of portals and clusters
- aasworld.numportals = 1; //portal 0 is a dummy
- aasworld.portalindexsize = 0;
- aasworld.numclusters = 1; //cluster 0 is a dummy
- //create the portals from the portal areas
- AAS_CreatePortals();
- //
- removedPortalAreas++;
- //find the clusters
- if (!AAS_FindClusters())
- continue;
- //test the portals
- if (!AAS_TestPortals())
- continue;
- //
- break;
- } //end while
- botimport.Print(PRT_MESSAGE, "\n");
- //the AAS file should be saved
- aasworld.savefile = qtrue;
- //write the portal areas to the log file
- for (i = 1; i < aasworld.numportals; i++)
- {
- Log_Write("portal %d: area %d\r\n", i, aasworld.portals[i].areanum);
- } //end for
- // report cluster info
- botimport.Print(PRT_MESSAGE, "%6d portals created\n", aasworld.numportals);
- botimport.Print(PRT_MESSAGE, "%6d clusters created\n", aasworld.numclusters);
- for (i = 1; i < aasworld.numclusters; i++)
- {
- botimport.Print(PRT_MESSAGE, "cluster %d has %d reachability areas\n", i,
- aasworld.clusters[i].numreachabilityareas);
- } //end for
- // report AAS file efficiency
- numreachabilityareas = 0;
- total = 0;
- for (i = 0; i < aasworld.numclusters; i++) {
- n = aasworld.clusters[i].numreachabilityareas;
- numreachabilityareas += n;
- total += n * n;
- }
- total += numreachabilityareas * aasworld.numportals;
- //
- botimport.Print(PRT_MESSAGE, "%6i total reachability areas\n", numreachabilityareas);
- botimport.Print(PRT_MESSAGE, "%6i AAS memory/CPU usage (the lower the better)\n", total * 3);
-} //end of the function AAS_InitClustering