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_script.h"
00037 #include "l_precomp.h"
00038 #include "l_struct.h"
00039 #include "aasfile.h"
00040 #include "../game/botlib.h"
00041 #include "../game/be_aas.h"
00042 #include "be_aas_funcs.h"
00043 #include "be_interface.h"
00044 #include "be_aas_def.h"
00045
00046 #define ENABLE_ALTROUTING
00047
00048
00049 typedef struct midrangearea_s
00050 {
00051 int valid;
00052 unsigned short starttime;
00053 unsigned short goaltime;
00054 } midrangearea_t;
00055
00056 midrangearea_t *midrangeareas;
00057 int *clusterareas;
00058 int numclusterareas;
00059
00060
00061
00062
00063
00064
00065
00066 void AAS_AltRoutingFloodCluster_r(int areanum)
00067 {
00068 int i, otherareanum;
00069 aas_area_t *area;
00070 aas_face_t *face;
00071
00072
00073 clusterareas[numclusterareas] = areanum;
00074 numclusterareas++;
00075
00076 midrangeareas[areanum].valid = qfalse;
00077
00078 area = &aasworld.areas[areanum];
00079 for (i = 0; i < area->numfaces; i++)
00080 {
00081 face = &aasworld.faces[abs(aasworld.faceindex[area->firstface + i])];
00082
00083 if (face->frontarea == areanum) otherareanum = face->backarea;
00084 else otherareanum = face->frontarea;
00085
00086 if (!otherareanum) continue;
00087
00088 if (!midrangeareas[otherareanum].valid) continue;
00089
00090 AAS_AltRoutingFloodCluster_r(otherareanum);
00091 }
00092 }
00093
00094
00095
00096
00097
00098
00099 int AAS_AlternativeRouteGoals(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags,
00100 aas_altroutegoal_t *altroutegoals, int maxaltroutegoals,
00101 int type)
00102 {
00103 #ifndef ENABLE_ALTROUTING
00104 return 0;
00105 #else
00106 int i, j, bestareanum;
00107 int numaltroutegoals, nummidrangeareas;
00108 int starttime, goaltime, goaltraveltime;
00109 float dist, bestdist;
00110 vec3_t mid, dir;
00111 #ifdef ALTROUTE_DEBUG
00112 int startmillisecs;
00113
00114 startmillisecs = Sys_MilliSeconds();
00115 #endif
00116
00117 if (!startareanum || !goalareanum)
00118 return 0;
00119
00120 goaltraveltime = AAS_AreaTravelTimeToGoalArea(startareanum, start, goalareanum, travelflags);
00121
00122 Com_Memset(midrangeareas, 0, aasworld.numareas * sizeof(midrangearea_t));
00123 numaltroutegoals = 0;
00124
00125 nummidrangeareas = 0;
00126
00127 for (i = 1; i < aasworld.numareas; i++)
00128 {
00129
00130 if (!(type & ALTROUTEGOAL_ALL))
00131 {
00132 if (!(type & ALTROUTEGOAL_CLUSTERPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)))
00133 {
00134 if (!(type & ALTROUTEGOAL_VIEWPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_VIEWPORTAL)))
00135 {
00136 continue;
00137 }
00138 }
00139 }
00140
00141 if (!AAS_AreaReachability(i)) continue;
00142
00143 starttime = AAS_AreaTravelTimeToGoalArea(startareanum, start, i, travelflags);
00144 if (!starttime) continue;
00145
00146 if (starttime > (float) 1.1 * goaltraveltime) continue;
00147
00148 goaltime = AAS_AreaTravelTimeToGoalArea(i, NULL, goalareanum, travelflags);
00149 if (!goaltime) continue;
00150
00151 if (goaltime > (float) 0.8 * goaltraveltime) continue;
00152
00153 midrangeareas[i].valid = qtrue;
00154 midrangeareas[i].starttime = starttime;
00155 midrangeareas[i].goaltime = goaltime;
00156 Log_Write("%d midrange area %d", nummidrangeareas, i);
00157 nummidrangeareas++;
00158 }
00159
00160 for (i = 1; i < aasworld.numareas; i++)
00161 {
00162 if (!midrangeareas[i].valid) continue;
00163
00164 numclusterareas = 0;
00165 AAS_AltRoutingFloodCluster_r(i);
00166
00167
00168 VectorClear(mid);
00169 for (j = 0; j < numclusterareas; j++)
00170 {
00171 VectorAdd(mid, aasworld.areas[clusterareas[j]].center, mid);
00172 }
00173 VectorScale(mid, 1.0 / numclusterareas, mid);
00174
00175 bestdist = 999999;
00176 bestareanum = 0;
00177 for (j = 0; j < numclusterareas; j++)
00178 {
00179 VectorSubtract(mid, aasworld.areas[clusterareas[j]].center, dir);
00180 dist = VectorLength(dir);
00181 if (dist < bestdist)
00182 {
00183 bestdist = dist;
00184 bestareanum = clusterareas[j];
00185 }
00186 }
00187
00188
00189 VectorCopy(aasworld.areas[bestareanum].center, altroutegoals[numaltroutegoals].origin);
00190 altroutegoals[numaltroutegoals].areanum = bestareanum;
00191 altroutegoals[numaltroutegoals].starttraveltime = midrangeareas[bestareanum].starttime;
00192 altroutegoals[numaltroutegoals].goaltraveltime = midrangeareas[bestareanum].goaltime;
00193 altroutegoals[numaltroutegoals].extratraveltime =
00194 (midrangeareas[bestareanum].starttime + midrangeareas[bestareanum].goaltime) -
00195 goaltraveltime;
00196 numaltroutegoals++;
00197
00198 #ifdef ALTROUTE_DEBUG
00199 AAS_ShowAreaPolygons(bestareanum, 1, qtrue);
00200 #endif
00201
00202 if (numaltroutegoals >= maxaltroutegoals) break;
00203 }
00204 #ifdef ALTROUTE_DEBUG
00205 botimport.Print(PRT_MESSAGE, "alternative route goals in %d msec\n", Sys_MilliSeconds() - startmillisecs);
00206 #endif
00207 return numaltroutegoals;
00208 #endif
00209 }
00210
00211
00212
00213
00214
00215
00216 void AAS_InitAlternativeRouting(void)
00217 {
00218 #ifdef ENABLE_ALTROUTING
00219 if (midrangeareas) FreeMemory(midrangeareas);
00220 midrangeareas = (midrangearea_t *) GetMemory(aasworld.numareas * sizeof(midrangearea_t));
00221 if (clusterareas) FreeMemory(clusterareas);
00222 clusterareas = (int *) GetMemory(aasworld.numareas * sizeof(int));
00223 #endif
00224 }
00225
00226
00227
00228
00229
00230
00231 void AAS_ShutdownAlternativeRouting(void)
00232 {
00233 #ifdef ENABLE_ALTROUTING
00234 if (midrangeareas) FreeMemory(midrangeareas);
00235 midrangeareas = NULL;
00236 if (clusterareas) FreeMemory(clusterareas);
00237 clusterareas = NULL;
00238 numclusterareas = 0;
00239 #endif
00240 }