1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 
5 This file is part of Quake III Arena source code.
6 
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.
11 
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.
16 
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 ===========================================================================
21 */
22 
23 /*****************************************************************************
24  * name:		be_aas_debug.c
25  *
26  * desc:		AAS debug code
27  *
28  * $Archive: /MissionPack/code/botlib/be_aas_debug.c $
29  *
30  *****************************************************************************/
31 
32 #include "../qcommon/q_shared.h"
33 #include "l_memory.h"
34 #include "l_script.h"
35 #include "l_precomp.h"
36 #include "l_struct.h"
37 #include "l_libvar.h"
38 #include "aasfile.h"
39 #include "botlib.h"
40 #include "be_aas.h"
41 #include "be_interface.h"
42 #include "be_aas_funcs.h"
43 #include "be_aas_def.h"
44 
45 #define MAX_DEBUGLINES				1024
46 #define MAX_DEBUGPOLYGONS			8192
47 
48 int debuglines[MAX_DEBUGLINES];
49 int debuglinevisible[MAX_DEBUGLINES];
50 int numdebuglines;
51 
52 static int debugpolygons[MAX_DEBUGPOLYGONS];
53 
54 //===========================================================================
55 //
56 // Parameter:				-
57 // Returns:					-
58 // Changes Globals:		-
59 //===========================================================================
AAS_ClearShownPolygons(void)60 void AAS_ClearShownPolygons(void)
61 {
62 	int i;
63 //*
64 	for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
65 	{
66 		if (debugpolygons[i]) botimport.DebugPolygonDelete(debugpolygons[i]);
67 		debugpolygons[i] = 0;
68 	} //end for
69 //*/
70 /*
71 	for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
72 	{
73 		botimport.DebugPolygonDelete(i);
74 		debugpolygons[i] = 0;
75 	} //end for
76 */
77 } //end of the function AAS_ClearShownPolygons
78 //===========================================================================
79 //
80 // Parameter:				-
81 // Returns:					-
82 // Changes Globals:		-
83 //===========================================================================
AAS_ShowPolygon(int color,int numpoints,vec3_t * points)84 void AAS_ShowPolygon(int color, int numpoints, vec3_t *points)
85 {
86 	int i;
87 
88 	for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
89 	{
90 		if (!debugpolygons[i])
91 		{
92 			debugpolygons[i] = botimport.DebugPolygonCreate(color, numpoints, points);
93 			break;
94 		} //end if
95 	} //end for
96 } //end of the function AAS_ShowPolygon
97 //===========================================================================
98 //
99 // Parameter:				-
100 // Returns:					-
101 // Changes Globals:		-
102 //===========================================================================
AAS_ClearShownDebugLines(void)103 void AAS_ClearShownDebugLines(void)
104 {
105 	int i;
106 
107 	//make all lines invisible
108 	for (i = 0; i < MAX_DEBUGLINES; i++)
109 	{
110 		if (debuglines[i])
111 		{
112 			//botimport.DebugLineShow(debuglines[i], NULL, NULL, LINECOLOR_NONE);
113 			botimport.DebugLineDelete(debuglines[i]);
114 			debuglines[i] = 0;
115 			debuglinevisible[i] = qfalse;
116 		} //end if
117 	} //end for
118 } //end of the function AAS_ClearShownDebugLines
119 //===========================================================================
120 //
121 // Parameter:				-
122 // Returns:					-
123 // Changes Globals:		-
124 //===========================================================================
AAS_DebugLine(vec3_t start,vec3_t end,int color)125 void AAS_DebugLine(vec3_t start, vec3_t end, int color)
126 {
127 	int line;
128 
129 	for (line = 0; line < MAX_DEBUGLINES; line++)
130 	{
131 		if (!debuglines[line])
132 		{
133 			debuglines[line] = botimport.DebugLineCreate();
134 			debuglinevisible[line] = qfalse;
135 			numdebuglines++;
136 		} //end if
137 		if (!debuglinevisible[line])
138 		{
139 			botimport.DebugLineShow(debuglines[line], start, end, color);
140 			debuglinevisible[line] = qtrue;
141 			return;
142 		} //end else
143 	} //end for
144 } //end of the function AAS_DebugLine
145 //===========================================================================
146 //
147 // Parameter:			-
148 // Returns:				-
149 // Changes Globals:		-
150 //===========================================================================
AAS_PermanentLine(vec3_t start,vec3_t end,int color)151 void AAS_PermanentLine(vec3_t start, vec3_t end, int color)
152 {
153 	int line;
154 
155 	line = botimport.DebugLineCreate();
156 	botimport.DebugLineShow(line, start, end, color);
157 } //end of the function AAS_PermenentLine
158 //===========================================================================
159 //
160 // Parameter:			-
161 // Returns:				-
162 // Changes Globals:		-
163 //===========================================================================
AAS_DrawPermanentCross(vec3_t origin,float size,int color)164 void AAS_DrawPermanentCross(vec3_t origin, float size, int color)
165 {
166 	int i, debugline;
167 	vec3_t start, end;
168 
169 	for (i = 0; i < 3; i++)
170 	{
171 		VectorCopy(origin, start);
172 		start[i] += size;
173 		VectorCopy(origin, end);
174 		end[i] -= size;
175 		AAS_DebugLine(start, end, color);
176 		debugline = botimport.DebugLineCreate();
177 		botimport.DebugLineShow(debugline, start, end, color);
178 	} //end for
179 } //end of the function AAS_DrawPermanentCross
180 //===========================================================================
181 //
182 // Parameter:				-
183 // Returns:					-
184 // Changes Globals:		-
185 //===========================================================================
AAS_DrawPlaneCross(vec3_t point,vec3_t normal,float dist,int type,int color)186 void AAS_DrawPlaneCross(vec3_t point, vec3_t normal, float dist, int type, int color)
187 {
188 	int n0, n1, n2, j, line, lines[2];
189 	vec3_t start1, end1, start2, end2;
190 
191 	//make a cross in the hit plane at the hit point
192 	VectorCopy(point, start1);
193 	VectorCopy(point, end1);
194 	VectorCopy(point, start2);
195 	VectorCopy(point, end2);
196 
197 	n0 = type % 3;
198 	n1 = (type + 1) % 3;
199 	n2 = (type + 2) % 3;
200 	start1[n1] -= 6;
201 	start1[n2] -= 6;
202 	end1[n1] += 6;
203 	end1[n2] += 6;
204 	start2[n1] += 6;
205 	start2[n2] -= 6;
206 	end2[n1] -= 6;
207 	end2[n2] += 6;
208 
209 	start1[n0] = (dist - (start1[n1] * normal[n1] +
210 				start1[n2] * normal[n2])) / normal[n0];
211 	end1[n0] = (dist - (end1[n1] * normal[n1] +
212 				end1[n2] * normal[n2])) / normal[n0];
213 	start2[n0] = (dist - (start2[n1] * normal[n1] +
214 				start2[n2] * normal[n2])) / normal[n0];
215 	end2[n0] = (dist - (end2[n1] * normal[n1] +
216 				end2[n2] * normal[n2])) / normal[n0];
217 
218 	for (j = 0, line = 0; j < 2 && line < MAX_DEBUGLINES; line++)
219 	{
220 		if (!debuglines[line])
221 		{
222 			debuglines[line] = botimport.DebugLineCreate();
223 			lines[j++] = debuglines[line];
224 			debuglinevisible[line] = qtrue;
225 			numdebuglines++;
226 		} //end if
227 		else if (!debuglinevisible[line])
228 		{
229 			lines[j++] = debuglines[line];
230 			debuglinevisible[line] = qtrue;
231 		} //end else
232 	} //end for
233 	botimport.DebugLineShow(lines[0], start1, end1, color);
234 	botimport.DebugLineShow(lines[1], start2, end2, color);
235 } //end of the function AAS_DrawPlaneCross
236 //===========================================================================
237 //
238 // Parameter:				-
239 // Returns:					-
240 // Changes Globals:		-
241 //===========================================================================
AAS_ShowBoundingBox(vec3_t origin,vec3_t mins,vec3_t maxs)242 void AAS_ShowBoundingBox(vec3_t origin, vec3_t mins, vec3_t maxs)
243 {
244 	vec3_t bboxcorners[8];
245 	int lines[3];
246 	int i, j, line;
247 
248 	//upper corners
249 	bboxcorners[0][0] = origin[0] + maxs[0];
250 	bboxcorners[0][1] = origin[1] + maxs[1];
251 	bboxcorners[0][2] = origin[2] + maxs[2];
252 	//
253 	bboxcorners[1][0] = origin[0] + mins[0];
254 	bboxcorners[1][1] = origin[1] + maxs[1];
255 	bboxcorners[1][2] = origin[2] + maxs[2];
256 	//
257 	bboxcorners[2][0] = origin[0] + mins[0];
258 	bboxcorners[2][1] = origin[1] + mins[1];
259 	bboxcorners[2][2] = origin[2] + maxs[2];
260 	//
261 	bboxcorners[3][0] = origin[0] + maxs[0];
262 	bboxcorners[3][1] = origin[1] + mins[1];
263 	bboxcorners[3][2] = origin[2] + maxs[2];
264 	//lower corners
265 	Com_Memcpy(bboxcorners[4], bboxcorners[0], sizeof(vec3_t) * 4);
266 	for (i = 0; i < 4; i++) bboxcorners[4 + i][2] = origin[2] + mins[2];
267 	//draw bounding box
268 	for (i = 0; i < 4; i++)
269 	{
270 		for (j = 0, line = 0; j < 3 && line < MAX_DEBUGLINES; line++)
271 		{
272 			if (!debuglines[line])
273 			{
274 				debuglines[line] = botimport.DebugLineCreate();
275 				lines[j++] = debuglines[line];
276 				debuglinevisible[line] = qtrue;
277 				numdebuglines++;
278 			} //end if
279 			else if (!debuglinevisible[line])
280 			{
281 				lines[j++] = debuglines[line];
282 				debuglinevisible[line] = qtrue;
283 			} //end else
284 		} //end for
285 		//top plane
286 		botimport.DebugLineShow(lines[0], bboxcorners[i],
287 									bboxcorners[(i+1)&3], LINECOLOR_RED);
288 		//bottom plane
289 		botimport.DebugLineShow(lines[1], bboxcorners[4+i],
290 									bboxcorners[4+((i+1)&3)], LINECOLOR_RED);
291 		//vertical lines
292 		botimport.DebugLineShow(lines[2], bboxcorners[i],
293 									bboxcorners[4+i], LINECOLOR_RED);
294 	} //end for
295 } //end of the function AAS_ShowBoundingBox
296 //===========================================================================
297 //
298 // Parameter:				-
299 // Returns:					-
300 // Changes Globals:		-
301 //===========================================================================
AAS_ShowFace(int facenum)302 void AAS_ShowFace(int facenum)
303 {
304 	int i, color, edgenum;
305 	aas_edge_t *edge;
306 	aas_face_t *face;
307 	aas_plane_t *plane;
308 	vec3_t start, end;
309 
310 	color = LINECOLOR_YELLOW;
311 	//check if face number is in range
312 	if (facenum >= aasworld.numfaces)
313 	{
314 		botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
315 	} //end if
316 	face = &aasworld.faces[facenum];
317 	//walk through the edges of the face
318 	for (i = 0; i < face->numedges; i++)
319 	{
320 		//edge number
321 		edgenum = abs(aasworld.edgeindex[face->firstedge + i]);
322 		//check if edge number is in range
323 		if (edgenum >= aasworld.numedges)
324 		{
325 			botimport.Print(PRT_ERROR, "edgenum %d out of range\n", edgenum);
326 		} //end if
327 		edge = &aasworld.edges[edgenum];
328 		if (color == LINECOLOR_RED) color = LINECOLOR_GREEN;
329 		else if (color == LINECOLOR_GREEN) color = LINECOLOR_BLUE;
330 		else if (color == LINECOLOR_BLUE) color = LINECOLOR_YELLOW;
331 		else color = LINECOLOR_RED;
332 		AAS_DebugLine(aasworld.vertexes[edge->v[0]],
333 										aasworld.vertexes[edge->v[1]],
334 										color);
335 	} //end for
336 	plane = &aasworld.planes[face->planenum];
337 	edgenum = abs(aasworld.edgeindex[face->firstedge]);
338 	edge = &aasworld.edges[edgenum];
339 	VectorCopy(aasworld.vertexes[edge->v[0]], start);
340 	VectorMA(start, 20, plane->normal, end);
341 	AAS_DebugLine(start, end, LINECOLOR_RED);
342 } //end of the function AAS_ShowFace
343 //===========================================================================
344 //
345 // Parameter:				-
346 // Returns:					-
347 // Changes Globals:		-
348 //===========================================================================
AAS_ShowFacePolygon(int facenum,int color,int flip)349 void AAS_ShowFacePolygon(int facenum, int color, int flip)
350 {
351 	int i, edgenum, numpoints;
352 	vec3_t points[128];
353 	aas_edge_t *edge;
354 	aas_face_t *face;
355 
356 	//check if face number is in range
357 	if (facenum >= aasworld.numfaces)
358 	{
359 		botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
360 	} //end if
361 	face = &aasworld.faces[facenum];
362 	//walk through the edges of the face
363 	numpoints = 0;
364 	if (flip)
365 	{
366 		for (i = face->numedges-1; i >= 0; i--)
367 		{
368 			//edge number
369 			edgenum = aasworld.edgeindex[face->firstedge + i];
370 			edge = &aasworld.edges[abs(edgenum)];
371 			VectorCopy(aasworld.vertexes[edge->v[edgenum < 0]], points[numpoints]);
372 			numpoints++;
373 		} //end for
374 	} //end if
375 	else
376 	{
377 		for (i = 0; i < face->numedges; i++)
378 		{
379 			//edge number
380 			edgenum = aasworld.edgeindex[face->firstedge + i];
381 			edge = &aasworld.edges[abs(edgenum)];
382 			VectorCopy(aasworld.vertexes[edge->v[edgenum < 0]], points[numpoints]);
383 			numpoints++;
384 		} //end for
385 	} //end else
386 	AAS_ShowPolygon(color, numpoints, points);
387 } //end of the function AAS_ShowFacePolygon
388 //===========================================================================
389 //
390 // Parameter:				-
391 // Returns:					-
392 // Changes Globals:		-
393 //===========================================================================
AAS_ShowArea(int areanum,int groundfacesonly)394 void AAS_ShowArea(int areanum, int groundfacesonly)
395 {
396 	int areaedges[MAX_DEBUGLINES];
397 	int numareaedges, i, j, n, color = 0, line;
398 	int facenum, edgenum;
399 	aas_area_t *area;
400 	aas_face_t *face;
401 	aas_edge_t *edge;
402 
403 	//
404 	numareaedges = 0;
405 	//
406 	if (areanum < 0 || areanum >= aasworld.numareas)
407 	{
408 		botimport.Print(PRT_ERROR, "area %d out of range [0, %d]\n",
409 								areanum, aasworld.numareas);
410 		return;
411 	} //end if
412 	//pointer to the convex area
413 	area = &aasworld.areas[areanum];
414 	//walk through the faces of the area
415 	for (i = 0; i < area->numfaces; i++)
416 	{
417 		facenum = abs(aasworld.faceindex[area->firstface + i]);
418 		//check if face number is in range
419 		if (facenum >= aasworld.numfaces)
420 		{
421 			botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
422 		} //end if
423 		face = &aasworld.faces[facenum];
424 		//ground faces only
425 		if (groundfacesonly)
426 		{
427 			if (!(face->faceflags & (FACE_GROUND | FACE_LADDER))) continue;
428 		} //end if
429 		//walk through the edges of the face
430 		for (j = 0; j < face->numedges; j++)
431 		{
432 			//edge number
433 			edgenum = abs(aasworld.edgeindex[face->firstedge + j]);
434 			//check if edge number is in range
435 			if (edgenum >= aasworld.numedges)
436 			{
437 				botimport.Print(PRT_ERROR, "edgenum %d out of range\n", edgenum);
438 			} //end if
439 			//check if the edge is stored already
440 			for (n = 0; n < numareaedges; n++)
441 			{
442 				if (areaedges[n] == edgenum) break;
443 			} //end for
444 			if (n == numareaedges && numareaedges < MAX_DEBUGLINES)
445 			{
446 				areaedges[numareaedges++] = edgenum;
447 			} //end if
448 		} //end for
449 		//AAS_ShowFace(facenum);
450 	} //end for
451 	//draw all the edges
452 	for (n = 0; n < numareaedges; n++)
453 	{
454 		for (line = 0; line < MAX_DEBUGLINES; line++)
455 		{
456 			if (!debuglines[line])
457 			{
458 				debuglines[line] = botimport.DebugLineCreate();
459 				debuglinevisible[line] = qfalse;
460 				numdebuglines++;
461 			} //end if
462 			if (!debuglinevisible[line])
463 			{
464 				break;
465 			} //end else
466 		} //end for
467 		if (line >= MAX_DEBUGLINES) return;
468 		edge = &aasworld.edges[areaedges[n]];
469 		if (color == LINECOLOR_RED) color = LINECOLOR_BLUE;
470 		else if (color == LINECOLOR_BLUE) color = LINECOLOR_GREEN;
471 		else if (color == LINECOLOR_GREEN) color = LINECOLOR_YELLOW;
472 		else color = LINECOLOR_RED;
473 		botimport.DebugLineShow(debuglines[line],
474 									aasworld.vertexes[edge->v[0]],
475 									aasworld.vertexes[edge->v[1]],
476 									color);
477 		debuglinevisible[line] = qtrue;
478 	} //end for*/
479 } //end of the function AAS_ShowArea
480 //===========================================================================
481 //
482 // Parameter:				-
483 // Returns:					-
484 // Changes Globals:		-
485 //===========================================================================
AAS_ShowAreaPolygons(int areanum,int color,int groundfacesonly)486 void AAS_ShowAreaPolygons(int areanum, int color, int groundfacesonly)
487 {
488 	int i, facenum;
489 	aas_area_t *area;
490 	aas_face_t *face;
491 
492 	//
493 	if (areanum < 0 || areanum >= aasworld.numareas)
494 	{
495 		botimport.Print(PRT_ERROR, "area %d out of range [0, %d]\n",
496 								areanum, aasworld.numareas);
497 		return;
498 	} //end if
499 	//pointer to the convex area
500 	area = &aasworld.areas[areanum];
501 	//walk through the faces of the area
502 	for (i = 0; i < area->numfaces; i++)
503 	{
504 		facenum = abs(aasworld.faceindex[area->firstface + i]);
505 		//check if face number is in range
506 		if (facenum >= aasworld.numfaces)
507 		{
508 			botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
509 		} //end if
510 		face = &aasworld.faces[facenum];
511 		//ground faces only
512 		if (groundfacesonly)
513 		{
514 			if (!(face->faceflags & (FACE_GROUND | FACE_LADDER))) continue;
515 		} //end if
516 		AAS_ShowFacePolygon(facenum, color, face->frontarea != areanum);
517 	} //end for
518 } //end of the function AAS_ShowAreaPolygons
519 //===========================================================================
520 //
521 // Parameter:				-
522 // Returns:					-
523 // Changes Globals:		-
524 //===========================================================================
AAS_DrawCross(vec3_t origin,float size,int color)525 void AAS_DrawCross(vec3_t origin, float size, int color)
526 {
527 	int i;
528 	vec3_t start, end;
529 
530 	for (i = 0; i < 3; i++)
531 	{
532 		VectorCopy(origin, start);
533 		start[i] += size;
534 		VectorCopy(origin, end);
535 		end[i] -= size;
536 		AAS_DebugLine(start, end, color);
537 	} //end for
538 } //end of the function AAS_DrawCross
539 //===========================================================================
540 //
541 // Parameter:				-
542 // Returns:					-
543 // Changes Globals:		-
544 //===========================================================================
AAS_PrintTravelType(int traveltype)545 void AAS_PrintTravelType(int traveltype)
546 {
547 #ifdef DEBUG
548 	char *str;
549 	//
550 	switch(traveltype & TRAVELTYPE_MASK)
551 	{
552 		case TRAVEL_INVALID: str = "TRAVEL_INVALID"; break;
553 		case TRAVEL_WALK: str = "TRAVEL_WALK"; break;
554 		case TRAVEL_CROUCH: str = "TRAVEL_CROUCH"; break;
555 		case TRAVEL_BARRIERJUMP: str = "TRAVEL_BARRIERJUMP"; break;
556 		case TRAVEL_JUMP: str = "TRAVEL_JUMP"; break;
557 		case TRAVEL_LADDER: str = "TRAVEL_LADDER"; break;
558 		case TRAVEL_WALKOFFLEDGE: str = "TRAVEL_WALKOFFLEDGE"; break;
559 		case TRAVEL_SWIM: str = "TRAVEL_SWIM"; break;
560 		case TRAVEL_WATERJUMP: str = "TRAVEL_WATERJUMP"; break;
561 		case TRAVEL_TELEPORT: str = "TRAVEL_TELEPORT"; break;
562 		case TRAVEL_ELEVATOR: str = "TRAVEL_ELEVATOR"; break;
563 		case TRAVEL_ROCKETJUMP: str = "TRAVEL_ROCKETJUMP"; break;
564 		case TRAVEL_BFGJUMP: str = "TRAVEL_BFGJUMP"; break;
565 		case TRAVEL_GRAPPLEHOOK: str = "TRAVEL_GRAPPLEHOOK"; break;
566 		case TRAVEL_JUMPPAD: str = "TRAVEL_JUMPPAD"; break;
567 		case TRAVEL_FUNCBOB: str = "TRAVEL_FUNCBOB"; break;
568 		default: str = "UNKNOWN TRAVEL TYPE"; break;
569 	} //end switch
570 	botimport.Print(PRT_MESSAGE, "%s", str);
571 #endif
572 } //end of the function AAS_PrintTravelType
573 //===========================================================================
574 //
575 // Parameter:				-
576 // Returns:					-
577 // Changes Globals:		-
578 //===========================================================================
AAS_DrawArrow(vec3_t start,vec3_t end,int linecolor,int arrowcolor)579 void AAS_DrawArrow(vec3_t start, vec3_t end, int linecolor, int arrowcolor)
580 {
581 	vec3_t dir, cross, p1, p2, up = {0, 0, 1};
582 	float dot;
583 
584 	VectorSubtract(end, start, dir);
585 	VectorNormalize(dir);
586 	dot = DotProduct(dir, up);
587 	if (dot > 0.99 || dot < -0.99) VectorSet(cross, 1, 0, 0);
588 	else CrossProduct(dir, up, cross);
589 
590 	VectorMA(end, -6, dir, p1);
591 	VectorCopy(p1, p2);
592 	VectorMA(p1, 6, cross, p1);
593 	VectorMA(p2, -6, cross, p2);
594 
595 	AAS_DebugLine(start, end, linecolor);
596 	AAS_DebugLine(p1, end, arrowcolor);
597 	AAS_DebugLine(p2, end, arrowcolor);
598 } //end of the function AAS_DrawArrow
599 //===========================================================================
600 //
601 // Parameter:				-
602 // Returns:					-
603 // Changes Globals:		-
604 //===========================================================================
AAS_ShowReachability(aas_reachability_t * reach)605 void AAS_ShowReachability(aas_reachability_t *reach)
606 {
607 	vec3_t dir, cmdmove, velocity;
608 	float speed, zvel;
609 	aas_clientmove_t move;
610 
611 	AAS_ShowAreaPolygons(reach->areanum, 5, qtrue);
612 	//AAS_ShowArea(reach->areanum, qtrue);
613 	AAS_DrawArrow(reach->start, reach->end, LINECOLOR_BLUE, LINECOLOR_YELLOW);
614 	//
615 	if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP ||
616 		(reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE)
617 	{
618 		AAS_HorizontalVelocityForJump(aassettings.phys_jumpvel, reach->start, reach->end, &speed);
619 		//
620 		VectorSubtract(reach->end, reach->start, dir);
621 		dir[2] = 0;
622 		VectorNormalize(dir);
623 		//set the velocity
624 		VectorScale(dir, speed, velocity);
625 		//set the command movement
626 		VectorClear(cmdmove);
627 		cmdmove[2] = aassettings.phys_jumpvel;
628 		//
629 		AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
630 									velocity, cmdmove, 3, 30, 0.1f,
631 									SE_HITGROUND|SE_ENTERWATER|SE_ENTERSLIME|
632 									SE_ENTERLAVA|SE_HITGROUNDDAMAGE, 0, qtrue);
633 		//
634 		if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP)
635 		{
636 			AAS_JumpReachRunStart(reach, dir);
637 			AAS_DrawCross(dir, 4, LINECOLOR_BLUE);
638 		} //end if
639 	} //end if
640 	else if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_ROCKETJUMP)
641 	{
642 		zvel = AAS_RocketJumpZVelocity(reach->start);
643 		AAS_HorizontalVelocityForJump(zvel, reach->start, reach->end, &speed);
644 		//
645 		VectorSubtract(reach->end, reach->start, dir);
646 		dir[2] = 0;
647 		VectorNormalize(dir);
648 		//get command movement
649 		VectorScale(dir, speed, cmdmove);
650 		VectorSet(velocity, 0, 0, zvel);
651 		//
652 		AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
653 									velocity, cmdmove, 30, 30, 0.1f,
654 									SE_ENTERWATER|SE_ENTERSLIME|
655 									SE_ENTERLAVA|SE_HITGROUNDDAMAGE|
656 									SE_TOUCHJUMPPAD|SE_HITGROUNDAREA, reach->areanum, qtrue);
657 	} //end else if
658 	else if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMPPAD)
659 	{
660 		VectorSet(cmdmove, 0, 0, 0);
661 		//
662 		VectorSubtract(reach->end, reach->start, dir);
663 		dir[2] = 0;
664 		VectorNormalize(dir);
665 		//set the velocity
666 		//NOTE: the edgenum is the horizontal velocity
667 		VectorScale(dir, reach->edgenum, velocity);
668 		//NOTE: the facenum is the Z velocity
669 		velocity[2] = reach->facenum;
670 		//
671 		AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
672 									velocity, cmdmove, 30, 30, 0.1f,
673 									SE_ENTERWATER|SE_ENTERSLIME|
674 									SE_ENTERLAVA|SE_HITGROUNDDAMAGE|
675 									SE_TOUCHJUMPPAD|SE_HITGROUNDAREA, reach->areanum, qtrue);
676 	} //end else if
677 } //end of the function AAS_ShowReachability
678 //===========================================================================
679 //
680 // Parameter:				-
681 // Returns:					-
682 // Changes Globals:		-
683 //===========================================================================
AAS_ShowReachableAreas(int areanum)684 void AAS_ShowReachableAreas(int areanum)
685 {
686 	aas_areasettings_t *settings;
687 	static aas_reachability_t reach;
688 	static int index, lastareanum;
689 	static float lasttime;
690 
691 	if (areanum != lastareanum)
692 	{
693 		index = 0;
694 		lastareanum = areanum;
695 	} //end if
696 	settings = &aasworld.areasettings[areanum];
697 	//
698 	if (!settings->numreachableareas) return;
699 	//
700 	if (index >= settings->numreachableareas) index = 0;
701 	//
702 	if (AAS_Time() - lasttime > 1.5)
703 	{
704 		Com_Memcpy(&reach, &aasworld.reachability[settings->firstreachablearea + index], sizeof(aas_reachability_t));
705 		index++;
706 		lasttime = AAS_Time();
707 		AAS_PrintTravelType(reach.traveltype & TRAVELTYPE_MASK);
708 		botimport.Print(PRT_MESSAGE, "\n");
709 	} //end if
710 	AAS_ShowReachability(&reach);
711 } //end of the function ShowReachableAreas
712 
AAS_FloodAreas_r(int areanum,int cluster,int * done)713 void AAS_FloodAreas_r(int areanum, int cluster, int *done)
714 {
715 	int nextareanum, i, facenum;
716 	aas_area_t *area;
717 	aas_face_t *face;
718 	aas_areasettings_t *settings;
719 	aas_reachability_t *reach;
720 
721 	AAS_ShowAreaPolygons(areanum, 1, qtrue);
722 	//pointer to the convex area
723 	area = &aasworld.areas[areanum];
724 	settings = &aasworld.areasettings[areanum];
725 	//walk through the faces of the area
726 	for (i = 0; i < area->numfaces; i++)
727 	{
728 		facenum = abs(aasworld.faceindex[area->firstface + i]);
729 		face = &aasworld.faces[facenum];
730 		if (face->frontarea == areanum)
731 			nextareanum = face->backarea;
732 		else
733 			nextareanum = face->frontarea;
734 		if (!nextareanum)
735 			continue;
736 		if (done[nextareanum])
737 			continue;
738 		done[nextareanum] = qtrue;
739 		if (aasworld.areasettings[nextareanum].contents & AREACONTENTS_VIEWPORTAL)
740 			continue;
741 		if (AAS_AreaCluster(nextareanum) != cluster)
742 			continue;
743 		AAS_FloodAreas_r(nextareanum, cluster, done);
744 	} //end for
745 	//
746 	for (i = 0; i < settings->numreachableareas; i++)
747 	{
748 		reach = &aasworld.reachability[settings->firstreachablearea + i];
749 		nextareanum = reach->areanum;
750 		if (!nextareanum)
751 			continue;
752 		if (done[nextareanum])
753 			continue;
754 		done[nextareanum] = qtrue;
755 		if (aasworld.areasettings[nextareanum].contents & AREACONTENTS_VIEWPORTAL)
756 			continue;
757 		if (AAS_AreaCluster(nextareanum) != cluster)
758 			continue;
759 		/*
760 		if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE)
761 		{
762 			AAS_DebugLine(reach->start, reach->end, 1);
763 		}
764 		*/
765 		AAS_FloodAreas_r(nextareanum, cluster, done);
766 	}
767 }
768 
AAS_FloodAreas(vec3_t origin)769 void AAS_FloodAreas(vec3_t origin)
770 {
771 	int areanum, cluster, *done;
772 
773 	done = (int *) GetClearedMemory(aasworld.numareas * sizeof(int));
774 	areanum = AAS_PointAreaNum(origin);
775 	cluster = AAS_AreaCluster(areanum);
776 	AAS_FloodAreas_r(areanum, cluster, done);
777 }
778