2
===========================================================================
3
Copyright (C) 1999-2005 Id Software, Inc.
5
This file is part of Quake III Arena source code.
7
Quake III Arena source code is free software; you can redistribute it
8
and/or modify it under the terms of the GNU General Public License as
9
published by the Free Software Foundation; either version 2 of the License,
10
or (at your option) any later version.
12
Quake III Arena source code is distributed in the hope that it will be
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with Quake III Arena source code; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
===========================================================================
23
/*****************************************************************************
24
* name: be_aas_routealt.c
28
* $Archive: /MissionPack/code/botlib/be_aas_routealt.c $
30
*****************************************************************************/
32
#include "../qcommon/q_shared.h"
37
#include "l_precomp.h"
42
#include "be_aas_funcs.h"
43
#include "be_interface.h"
44
#include "be_aas_def.h"
46
#define ENABLE_ALTROUTING
47
//#define ALTROUTE_DEBUG
49
typedef struct midrangearea_s
52
unsigned short starttime;
53
unsigned short goaltime;
56
midrangearea_t *midrangeareas;
60
//===========================================================================
65
//===========================================================================
66
void AAS_AltRoutingFloodCluster_r(int areanum)
72
//add the current area to the areas of the current cluster
73
clusterareas[numclusterareas] = areanum;
75
//remove the area from the mid range areas
76
midrangeareas[areanum].valid = qfalse;
77
//flood to other areas through the faces of this area
78
area = &aasworld.areas[areanum];
79
for (i = 0; i < area->numfaces; i++)
81
face = &aasworld.faces[abs(aasworld.faceindex[area->firstface + i])];
82
//get the area at the other side of the face
83
if (face->frontarea == areanum) otherareanum = face->backarea;
84
else otherareanum = face->frontarea;
85
//if there is an area at the other side of this face
86
if (!otherareanum) continue;
87
//if the other area is not a midrange area
88
if (!midrangeareas[otherareanum].valid) continue;
90
AAS_AltRoutingFloodCluster_r(otherareanum);
92
} //end of the function AAS_AltRoutingFloodCluster_r
93
//===========================================================================
98
//===========================================================================
99
int AAS_AlternativeRouteGoals(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags,
100
aas_altroutegoal_t *altroutegoals, int maxaltroutegoals,
103
#ifndef ENABLE_ALTROUTING
106
int i, j, bestareanum;
107
int numaltroutegoals, nummidrangeareas;
108
int starttime, goaltime, goaltraveltime;
109
float dist, bestdist;
111
#ifdef ALTROUTE_DEBUG
114
startmillisecs = Sys_MilliSeconds();
117
if (!startareanum || !goalareanum)
119
//travel time towards the goal area
120
goaltraveltime = AAS_AreaTravelTimeToGoalArea(startareanum, start, goalareanum, travelflags);
121
//clear the midrange areas
122
Com_Memset(midrangeareas, 0, aasworld.numareas * sizeof(midrangearea_t));
123
numaltroutegoals = 0;
125
nummidrangeareas = 0;
127
for (i = 1; i < aasworld.numareas; i++)
130
if (!(type & ALTROUTEGOAL_ALL))
132
if (!(type & ALTROUTEGOAL_CLUSTERPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)))
134
if (!(type & ALTROUTEGOAL_VIEWPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_VIEWPORTAL)))
140
//if the area has no reachabilities
141
if (!AAS_AreaReachability(i)) continue;
142
//tavel time from the area to the start area
143
starttime = AAS_AreaTravelTimeToGoalArea(startareanum, start, i, travelflags);
144
if (!starttime) continue;
145
//if the travel time from the start to the area is greater than the shortest goal travel time
146
if (starttime > (float) 1.1 * goaltraveltime) continue;
147
//travel time from the area to the goal area
148
goaltime = AAS_AreaTravelTimeToGoalArea(i, NULL, goalareanum, travelflags);
149
if (!goaltime) continue;
150
//if the travel time from the area to the goal is greater than the shortest goal travel time
151
if (goaltime > (float) 0.8 * goaltraveltime) continue;
152
//this is a mid range area
153
midrangeareas[i].valid = qtrue;
154
midrangeareas[i].starttime = starttime;
155
midrangeareas[i].goaltime = goaltime;
156
Log_Write("%d midrange area %d", nummidrangeareas, i);
160
for (i = 1; i < aasworld.numareas; i++)
162
if (!midrangeareas[i].valid) continue;
163
//get the areas in one cluster
165
AAS_AltRoutingFloodCluster_r(i);
166
//now we've got a cluster with areas through which an alternative route could go
167
//get the 'center' of the cluster
169
for (j = 0; j < numclusterareas; j++)
171
VectorAdd(mid, aasworld.areas[clusterareas[j]].center, mid);
173
VectorScale(mid, 1.0 / numclusterareas, mid);
174
//get the area closest to the center of the cluster
177
for (j = 0; j < numclusterareas; j++)
179
VectorSubtract(mid, aasworld.areas[clusterareas[j]].center, dir);
180
dist = VectorLength(dir);
184
bestareanum = clusterareas[j];
187
//now we've got an area for an alternative route
188
//FIXME: add alternative goal origin
189
VectorCopy(aasworld.areas[bestareanum].center, altroutegoals[numaltroutegoals].origin);
190
altroutegoals[numaltroutegoals].areanum = bestareanum;
191
altroutegoals[numaltroutegoals].starttraveltime = midrangeareas[bestareanum].starttime;
192
altroutegoals[numaltroutegoals].goaltraveltime = midrangeareas[bestareanum].goaltime;
193
altroutegoals[numaltroutegoals].extratraveltime =
194
(midrangeareas[bestareanum].starttime + midrangeareas[bestareanum].goaltime) -
198
#ifdef ALTROUTE_DEBUG
199
AAS_ShowAreaPolygons(bestareanum, 1, qtrue);
201
//don't return more than the maximum alternative route goals
202
if (numaltroutegoals >= maxaltroutegoals) break;
204
#ifdef ALTROUTE_DEBUG
205
botimport.Print(PRT_MESSAGE, "alternative route goals in %d msec\n", Sys_MilliSeconds() - startmillisecs);
207
return numaltroutegoals;
209
} //end of the function AAS_AlternativeRouteGoals
210
//===========================================================================
214
// Changes Globals: -
215
//===========================================================================
216
void AAS_InitAlternativeRouting(void)
218
#ifdef ENABLE_ALTROUTING
219
if (midrangeareas) FreeMemory(midrangeareas);
220
midrangeareas = (midrangearea_t *) GetMemory(aasworld.numareas * sizeof(midrangearea_t));
221
if (clusterareas) FreeMemory(clusterareas);
222
clusterareas = (int *) GetMemory(aasworld.numareas * sizeof(int));
224
} //end of the function AAS_InitAlternativeRouting
225
//===========================================================================
229
// Changes Globals: -
230
//===========================================================================
231
void AAS_ShutdownAlternativeRouting(void)
233
#ifdef ENABLE_ALTROUTING
234
if (midrangeareas) FreeMemory(midrangeareas);
235
midrangeareas = NULL;
236
if (clusterareas) FreeMemory(clusterareas);
240
} //end of the function AAS_ShutdownAlternativeRouting