1 /*
2 ===========================================================================
3 
4 Return to Castle Wolfenstein single player GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
8 
9 RTCW SP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 RTCW SP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with RTCW SP Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 
30 /*****************************************************************************
31  * name:		be_aas_debug.c
32  *
33  * desc:		AAS debug code
34  *
35  *
36  *****************************************************************************/
37 
38 #include "../qcommon/q_shared.h"
39 #include "l_memory.h"
40 #include "l_script.h"
41 #include "l_precomp.h"
42 #include "l_struct.h"
43 #include "l_libvar.h"
44 #include "aasfile.h"
45 #include "botlib.h"
46 #include "be_aas.h"
47 #include "be_interface.h"
48 #include "be_aas_funcs.h"
49 #include "be_aas_def.h"
50 
51 #define MAX_DEBUGLINES              1024
52 #define MAX_DEBUGPOLYGONS           128
53 
54 int debuglines[MAX_DEBUGLINES];
55 int debuglinevisible[MAX_DEBUGLINES];
56 int numdebuglines;
57 
58 static int debugpolygons[MAX_DEBUGPOLYGONS];
59 
60 //===========================================================================
61 //
62 // Parameter:				-
63 // Returns:					-
64 // Changes Globals:		-
65 //===========================================================================
AAS_ClearShownPolygons(void)66 void AAS_ClearShownPolygons( void ) {
67 	int i;
68 //*
69 	for ( i = 0; i < MAX_DEBUGPOLYGONS; i++ )
70 	{
71 		if ( debugpolygons[i] ) {
72 			botimport.DebugPolygonDelete( debugpolygons[i] );
73 		}
74 		debugpolygons[i] = 0;
75 	} //end for
76 //*/
77 /*
78 	for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
79 	{
80 		botimport.DebugPolygonDelete(i);
81 		debugpolygons[i] = 0;
82 	} //end for
83 */
84 } //end of the function AAS_ClearShownPolygons
85 //===========================================================================
86 //
87 // Parameter:				-
88 // Returns:					-
89 // Changes Globals:		-
90 //===========================================================================
AAS_ShowPolygon(int color,int numpoints,vec3_t * points)91 void AAS_ShowPolygon( int color, int numpoints, vec3_t *points ) {
92 	int i;
93 
94 	for ( i = 0; i < MAX_DEBUGPOLYGONS; i++ )
95 	{
96 		if ( !debugpolygons[i] ) {
97 			debugpolygons[i] = botimport.DebugPolygonCreate( color, numpoints, points );
98 			break;
99 		} //end if
100 	} //end for
101 } //end of the function AAS_ShowPolygon
102 //===========================================================================
103 //
104 // Parameter:				-
105 // Returns:					-
106 // Changes Globals:		-
107 //===========================================================================
AAS_ClearShownDebugLines(void)108 void AAS_ClearShownDebugLines( void ) {
109 	int i;
110 
111 	//make all lines invisible
112 	for ( i = 0; i < MAX_DEBUGLINES; i++ )
113 	{
114 		if ( debuglines[i] ) {
115 			//botimport.DebugLineShow(debuglines[i], NULL, NULL, LINECOLOR_NONE);
116 			botimport.DebugLineDelete( debuglines[i] );
117 			debuglines[i] = 0;
118 			debuglinevisible[i] = qfalse;
119 		} //end if
120 	} //end for
121 } //end of the function AAS_ClearShownDebugLines
122 //===========================================================================
123 //
124 // Parameter:				-
125 // Returns:					-
126 // Changes Globals:		-
127 //===========================================================================
AAS_DebugLine(vec3_t start,vec3_t end,int color)128 void AAS_DebugLine( vec3_t start, vec3_t end, int color ) {
129 	int line;
130 
131 	for ( line = 0; line < MAX_DEBUGLINES; line++ )
132 	{
133 		if ( !debuglines[line] ) {
134 			debuglines[line] = botimport.DebugLineCreate();
135 			debuglinevisible[line] = qfalse;
136 			numdebuglines++;
137 		} //end if
138 		if ( !debuglinevisible[line] ) {
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 	int line;
153 
154 	line = botimport.DebugLineCreate();
155 	botimport.DebugLineShow( line, start, end, color );
156 } //end of the function AAS_PermenentLine
157 //===========================================================================
158 //
159 // Parameter:			-
160 // Returns:				-
161 // Changes Globals:		-
162 //===========================================================================
AAS_DrawPermanentCross(vec3_t origin,float size,int color)163 void AAS_DrawPermanentCross( vec3_t origin, float size, int color ) {
164 	int i, debugline;
165 	vec3_t start, end;
166 
167 	for ( i = 0; i < 3; i++ )
168 	{
169 		VectorCopy( origin, start );
170 		start[i] += size;
171 		VectorCopy( origin, end );
172 		end[i] -= size;
173 		AAS_DebugLine( start, end, color );
174 		debugline = botimport.DebugLineCreate();
175 		botimport.DebugLineShow( debugline, start, end, color );
176 	} //end for
177 } //end of the function AAS_DrawPermanentCross
178 //===========================================================================
179 //
180 // Parameter:				-
181 // Returns:					-
182 // Changes Globals:		-
183 //===========================================================================
AAS_DrawPlaneCross(vec3_t point,vec3_t normal,float dist,int type,int color)184 void AAS_DrawPlaneCross( vec3_t point, vec3_t normal, float dist, int type, int color ) {
185 	int n0, n1, n2, j, line, lines[2];
186 	vec3_t start1, end1, start2, end2;
187 
188 	//make a cross in the hit plane at the hit point
189 	VectorCopy( point, start1 );
190 	VectorCopy( point, end1 );
191 	VectorCopy( point, start2 );
192 	VectorCopy( point, end2 );
193 
194 	n0 = type % 3;
195 	n1 = ( type + 1 ) % 3;
196 	n2 = ( type + 2 ) % 3;
197 	start1[n1] -= 6;
198 	start1[n2] -= 6;
199 	end1[n1] += 6;
200 	end1[n2] += 6;
201 	start2[n1] += 6;
202 	start2[n2] -= 6;
203 	end2[n1] -= 6;
204 	end2[n2] += 6;
205 
206 	start1[n0] = ( dist - ( start1[n1] * normal[n1] +
207 							start1[n2] * normal[n2] ) ) / normal[n0];
208 	end1[n0] = ( dist - ( end1[n1] * normal[n1] +
209 						  end1[n2] * normal[n2] ) ) / normal[n0];
210 	start2[n0] = ( dist - ( start2[n1] * normal[n1] +
211 							start2[n2] * normal[n2] ) ) / normal[n0];
212 	end2[n0] = ( dist - ( end2[n1] * normal[n1] +
213 						  end2[n2] * normal[n2] ) ) / normal[n0];
214 
215 	for ( j = 0, line = 0; j < 2 && line < MAX_DEBUGLINES; line++ )
216 	{
217 		if ( !debuglines[line] ) {
218 			debuglines[line] = botimport.DebugLineCreate();
219 			lines[j++] = debuglines[line];
220 			debuglinevisible[line] = qtrue;
221 			numdebuglines++;
222 		} //end if
223 		else if ( !debuglinevisible[line] ) {
224 			lines[j++] = debuglines[line];
225 			debuglinevisible[line] = qtrue;
226 		} //end else
227 	} //end for
228 	botimport.DebugLineShow( lines[0], start1, end1, color );
229 	botimport.DebugLineShow( lines[1], start2, end2, color );
230 } //end of the function AAS_DrawPlaneCross
231 //===========================================================================
232 //
233 // Parameter:				-
234 // Returns:					-
235 // Changes Globals:		-
236 //===========================================================================
AAS_ShowBoundingBox(vec3_t origin,vec3_t mins,vec3_t maxs)237 void AAS_ShowBoundingBox( vec3_t origin, vec3_t mins, vec3_t maxs ) {
238 	vec3_t bboxcorners[8];
239 	int lines[3];
240 	int i, j, line;
241 
242 	//upper corners
243 	bboxcorners[0][0] = origin[0] + maxs[0];
244 	bboxcorners[0][1] = origin[1] + maxs[1];
245 	bboxcorners[0][2] = origin[2] + maxs[2];
246 	//
247 	bboxcorners[1][0] = origin[0] + mins[0];
248 	bboxcorners[1][1] = origin[1] + maxs[1];
249 	bboxcorners[1][2] = origin[2] + maxs[2];
250 	//
251 	bboxcorners[2][0] = origin[0] + mins[0];
252 	bboxcorners[2][1] = origin[1] + mins[1];
253 	bboxcorners[2][2] = origin[2] + maxs[2];
254 	//
255 	bboxcorners[3][0] = origin[0] + maxs[0];
256 	bboxcorners[3][1] = origin[1] + mins[1];
257 	bboxcorners[3][2] = origin[2] + maxs[2];
258 	//lower corners
259 	memcpy( bboxcorners[4], bboxcorners[0], sizeof( vec3_t ) * 4 );
260 	for ( i = 0; i < 4; i++ ) bboxcorners[4 + i][2] = origin[2] + mins[2];
261 	//draw bounding box
262 	for ( i = 0; i < 4; i++ )
263 	{
264 		for ( j = 0, line = 0; j < 3 && line < MAX_DEBUGLINES; line++ )
265 		{
266 			if ( !debuglines[line] ) {
267 				debuglines[line] = botimport.DebugLineCreate();
268 				lines[j++] = debuglines[line];
269 				debuglinevisible[line] = qtrue;
270 				numdebuglines++;
271 			} //end if
272 			else if ( !debuglinevisible[line] ) {
273 				lines[j++] = debuglines[line];
274 				debuglinevisible[line] = qtrue;
275 			} //end else
276 		} //end for
277 		  //top plane
278 		botimport.DebugLineShow( lines[0], bboxcorners[i],
279 								 bboxcorners[( i + 1 ) & 3], LINECOLOR_RED );
280 		//bottom plane
281 		botimport.DebugLineShow( lines[1], bboxcorners[4 + i],
282 								 bboxcorners[4 + ( ( i + 1 ) & 3 )], LINECOLOR_RED );
283 		//vertical lines
284 		botimport.DebugLineShow( lines[2], bboxcorners[i],
285 								 bboxcorners[4 + i], LINECOLOR_RED );
286 	} //end for
287 } //end of the function AAS_ShowBoundingBox
288 //===========================================================================
289 //
290 // Parameter:				-
291 // Returns:					-
292 // Changes Globals:		-
293 //===========================================================================
AAS_ShowFace(int facenum)294 void AAS_ShowFace( int facenum ) {
295 	int i, color, edgenum;
296 	aas_edge_t *edge;
297 	aas_face_t *face;
298 	aas_plane_t *plane;
299 	vec3_t start, end;
300 
301 	color = LINECOLOR_YELLOW;
302 	//check if face number is in range
303 	if ( facenum >= ( *aasworld ).numfaces ) {
304 		botimport.Print( PRT_ERROR, "facenum %d out of range\n", facenum );
305 	} //end if
306 	face = &( *aasworld ).faces[facenum];
307 	//walk through the edges of the face
308 	for ( i = 0; i < face->numedges; i++ )
309 	{
310 		//edge number
311 		edgenum = abs( ( *aasworld ).edgeindex[face->firstedge + i] );
312 		//check if edge number is in range
313 		if ( edgenum >= ( *aasworld ).numedges ) {
314 			botimport.Print( PRT_ERROR, "edgenum %d out of range\n", edgenum );
315 		} //end if
316 		edge = &( *aasworld ).edges[edgenum];
317 		if ( color == LINECOLOR_RED ) {
318 			color = LINECOLOR_GREEN;
319 		} else if ( color == LINECOLOR_GREEN ) {
320 			color = LINECOLOR_BLUE;
321 		} else if ( color == LINECOLOR_BLUE )                                                            {
322 			color = LINECOLOR_YELLOW;
323 		} else { color = LINECOLOR_RED;}
324 		AAS_DebugLine( ( *aasworld ).vertexes[edge->v[0]],
325 					   ( *aasworld ).vertexes[edge->v[1]],
326 					   color );
327 	} //end for
328 	plane = &( *aasworld ).planes[face->planenum];
329 	edgenum = abs( ( *aasworld ).edgeindex[face->firstedge] );
330 	edge = &( *aasworld ).edges[edgenum];
331 	VectorCopy( ( *aasworld ).vertexes[edge->v[0]], start );
332 	VectorMA( start, 20, plane->normal, end );
333 	AAS_DebugLine( start, end, LINECOLOR_RED );
334 } //end of the function AAS_ShowFace
335 //===========================================================================
336 //
337 // Parameter:				-
338 // Returns:					-
339 // Changes Globals:		-
340 //===========================================================================
AAS_ShowFacePolygon(int facenum,int color,int flip)341 void AAS_ShowFacePolygon( int facenum, int color, int flip ) {
342 	int i, edgenum, numpoints;
343 	vec3_t points[128];
344 	aas_edge_t *edge;
345 	aas_face_t *face;
346 
347 	//check if face number is in range
348 	if ( facenum >= ( *aasworld ).numfaces ) {
349 		botimport.Print( PRT_ERROR, "facenum %d out of range\n", facenum );
350 	} //end if
351 	face = &( *aasworld ).faces[facenum];
352 	//walk through the edges of the face
353 	numpoints = 0;
354 	if ( flip ) {
355 		for ( i = face->numedges - 1; i >= 0; i-- )
356 		{
357 			//edge number
358 			edgenum = ( *aasworld ).edgeindex[face->firstedge + i];
359 			edge = &( *aasworld ).edges[abs( edgenum )];
360 			VectorCopy( ( *aasworld ).vertexes[edge->v[edgenum < 0]], points[numpoints] );
361 			numpoints++;
362 		} //end for
363 	} //end if
364 	else
365 	{
366 		for ( i = 0; i < face->numedges; 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 else
375 	AAS_ShowPolygon( color, numpoints, points );
376 } //end of the function AAS_ShowFacePolygon
377 //===========================================================================
378 //
379 // Parameter:				-
380 // Returns:					-
381 // Changes Globals:		-
382 //===========================================================================
AAS_ShowArea(int areanum,int groundfacesonly)383 void AAS_ShowArea( int areanum, int groundfacesonly ) {
384 	int areaedges[MAX_DEBUGLINES];
385 	int numareaedges, i, j, n, color = 0, line;
386 	int facenum, edgenum;
387 	aas_area_t *area;
388 	aas_face_t *face;
389 	aas_edge_t *edge;
390 
391 	//
392 	numareaedges = 0;
393 	//
394 	if ( areanum < 0 || areanum >= ( *aasworld ).numareas ) {
395 		botimport.Print( PRT_ERROR, "area %d out of range [0, %d]\n",
396 						 areanum, ( *aasworld ).numareas );
397 		return;
398 	} //end if
399 	  //pointer to the convex area
400 	area = &( *aasworld ).areas[areanum];
401 	//walk through the faces of the area
402 	for ( i = 0; i < area->numfaces; i++ )
403 	{
404 		facenum = abs( ( *aasworld ).faceindex[area->firstface + i] );
405 		//check if face number is in range
406 		if ( facenum >= ( *aasworld ).numfaces ) {
407 			botimport.Print( PRT_ERROR, "facenum %d out of range\n", facenum );
408 		} //end if
409 		face = &( *aasworld ).faces[facenum];
410 		//ground faces only
411 		if ( groundfacesonly ) {
412 			if ( !( face->faceflags & ( FACE_GROUND | FACE_LADDER ) ) ) {
413 				continue;
414 			}
415 		} //end if
416 		  //walk through the edges of the face
417 		for ( j = 0; j < face->numedges; j++ )
418 		{
419 			//edge number
420 			edgenum = abs( ( *aasworld ).edgeindex[face->firstedge + j] );
421 			//check if edge number is in range
422 			if ( edgenum >= ( *aasworld ).numedges ) {
423 				botimport.Print( PRT_ERROR, "edgenum %d out of range\n", edgenum );
424 			} //end if
425 			  //check if the edge is stored already
426 			for ( n = 0; n < numareaedges; n++ )
427 			{
428 				if ( areaedges[n] == edgenum ) {
429 					break;
430 				}
431 			} //end for
432 			if ( n == numareaedges && numareaedges < MAX_DEBUGLINES ) {
433 				areaedges[numareaedges++] = edgenum;
434 			} //end if
435 		} //end for
436 		  //AAS_ShowFace(facenum);
437 	} //end for
438 	  //draw all the edges
439 	for ( n = 0; n < numareaedges; n++ )
440 	{
441 		for ( line = 0; line < MAX_DEBUGLINES; line++ )
442 		{
443 			if ( !debuglines[line] ) {
444 				debuglines[line] = botimport.DebugLineCreate();
445 				debuglinevisible[line] = qfalse;
446 				numdebuglines++;
447 			} //end if
448 			if ( !debuglinevisible[line] ) {
449 				break;
450 			} //end else
451 		} //end for
452 		if ( line >= MAX_DEBUGLINES ) {
453 			return;
454 		}
455 		edge = &( *aasworld ).edges[areaedges[n]];
456 		if ( color == LINECOLOR_RED ) {
457 			color = LINECOLOR_BLUE;
458 		} else if ( color == LINECOLOR_BLUE ) {
459 			color = LINECOLOR_GREEN;
460 		} else if ( color == LINECOLOR_GREEN )                                                            {
461 			color = LINECOLOR_YELLOW;
462 		} else { color = LINECOLOR_RED;}
463 		botimport.DebugLineShow( debuglines[line],
464 								 ( *aasworld ).vertexes[edge->v[0]],
465 								 ( *aasworld ).vertexes[edge->v[1]],
466 								 color );
467 		debuglinevisible[line] = qtrue;
468 	} //end for*/
469 } //end of the function AAS_ShowArea
470 //===========================================================================
471 //
472 // Parameter:				-
473 // Returns:					-
474 // Changes Globals:		-
475 //===========================================================================
AAS_ShowAreaPolygons(int areanum,int color,int groundfacesonly)476 void AAS_ShowAreaPolygons( int areanum, int color, int groundfacesonly ) {
477 	int i, facenum;
478 	aas_area_t *area;
479 	aas_face_t *face;
480 
481 	//
482 	if ( areanum < 0 || areanum >= ( *aasworld ).numareas ) {
483 		botimport.Print( PRT_ERROR, "area %d out of range [0, %d]\n",
484 						 areanum, ( *aasworld ).numareas );
485 		return;
486 	} //end if
487 	  //pointer to the convex area
488 	area = &( *aasworld ).areas[areanum];
489 	//walk through the faces of the area
490 	for ( i = 0; i < area->numfaces; i++ )
491 	{
492 		facenum = abs( ( *aasworld ).faceindex[area->firstface + i] );
493 		//check if face number is in range
494 		if ( facenum >= ( *aasworld ).numfaces ) {
495 			botimport.Print( PRT_ERROR, "facenum %d out of range\n", facenum );
496 		} //end if
497 		face = &( *aasworld ).faces[facenum];
498 		//ground faces only
499 		if ( groundfacesonly ) {
500 			if ( !( face->faceflags & ( FACE_GROUND | FACE_LADDER ) ) ) {
501 				continue;
502 			}
503 		} //end if
504 		AAS_ShowFacePolygon( facenum, color, face->frontarea != areanum );
505 	} //end for
506 } //end of the function AAS_ShowAreaPolygons
507 //===========================================================================
508 //
509 // Parameter:				-
510 // Returns:					-
511 // Changes Globals:		-
512 //===========================================================================
AAS_DrawCross(vec3_t origin,float size,int color)513 void AAS_DrawCross( vec3_t origin, float size, int color ) {
514 	int i;
515 	vec3_t start, end;
516 
517 	for ( i = 0; i < 3; i++ )
518 	{
519 		VectorCopy( origin, start );
520 		start[i] += size;
521 		VectorCopy( origin, end );
522 		end[i] -= size;
523 		AAS_DebugLine( start, end, color );
524 	} //end for
525 } //end of the function AAS_DrawCross
526 //===========================================================================
527 //
528 // Parameter:				-
529 // Returns:					-
530 // Changes Globals:		-
531 //===========================================================================
AAS_PrintTravelType(int traveltype)532 void AAS_PrintTravelType( int traveltype ) {
533 #ifdef DEBUG
534 	char *str;
535 	//
536 	switch ( traveltype )
537 	{
538 	case TRAVEL_INVALID: str = "TRAVEL_INVALID"; break;
539 	case TRAVEL_WALK: str = "TRAVEL_WALK"; break;
540 	case TRAVEL_CROUCH: str = "TRAVEL_CROUCH"; break;
541 	case TRAVEL_BARRIERJUMP: str = "TRAVEL_BARRIERJUMP"; break;
542 	case TRAVEL_JUMP: str = "TRAVEL_JUMP"; break;
543 	case TRAVEL_LADDER: str = "TRAVEL_LADDER"; break;
544 	case TRAVEL_WALKOFFLEDGE: str = "TRAVEL_WALKOFFLEDGE"; break;
545 	case TRAVEL_SWIM: str = "TRAVEL_SWIM"; break;
546 	case TRAVEL_WATERJUMP: str = "TRAVEL_WATERJUMP"; break;
547 	case TRAVEL_TELEPORT: str = "TRAVEL_TELEPORT"; break;
548 	case TRAVEL_ELEVATOR: str = "TRAVEL_ELEVATOR"; break;
549 	case TRAVEL_ROCKETJUMP: str = "TRAVEL_ROCKETJUMP"; break;
550 	case TRAVEL_BFGJUMP: str = "TRAVEL_BFGJUMP"; break;
551 	case TRAVEL_GRAPPLEHOOK: str = "TRAVEL_GRAPPLEHOOK"; break;
552 	case TRAVEL_JUMPPAD: str = "TRAVEL_JUMPPAD"; break;
553 	case TRAVEL_FUNCBOB: str = "TRAVEL_FUNCBOB"; break;
554 	default: str = "UNKNOWN TRAVEL TYPE"; break;
555 	} //end switch
556 	botimport.Print( PRT_MESSAGE, "%s", str );
557 #endif //DEBUG
558 } //end of the function AAS_PrintTravelType
559 //===========================================================================
560 //
561 // Parameter:				-
562 // Returns:					-
563 // Changes Globals:		-
564 //===========================================================================
AAS_DrawArrow(vec3_t start,vec3_t end,int linecolor,int arrowcolor)565 void AAS_DrawArrow( vec3_t start, vec3_t end, int linecolor, int arrowcolor ) {
566 	vec3_t dir, cross, p1, p2, up = {0, 0, 1};
567 	float dot;
568 
569 	VectorSubtract( end, start, dir );
570 	VectorNormalize( dir );
571 	dot = DotProduct( dir, up );
572 	if ( dot > 0.99 || dot < -0.99 ) {
573 		VectorSet( cross, 1, 0, 0 );
574 	} else { CrossProduct( dir, up, cross );}
575 
576 	VectorMA( end, -6, dir, p1 );
577 	VectorCopy( p1, p2 );
578 	VectorMA( p1, 6, cross, p1 );
579 	VectorMA( p2, -6, cross, p2 );
580 
581 	AAS_DebugLine( start, end, linecolor );
582 	AAS_DebugLine( p1, end, arrowcolor );
583 	AAS_DebugLine( p2, end, arrowcolor );
584 } //end of the function AAS_DrawArrow
585 //===========================================================================
586 //
587 // Parameter:				-
588 // Returns:					-
589 // Changes Globals:		-
590 //===========================================================================
AAS_ShowReachability(aas_reachability_t * reach)591 void AAS_ShowReachability( aas_reachability_t *reach ) {
592 	vec3_t dir, cmdmove, velocity;
593 	float speed, zvel;
594 	aas_clientmove_t move;
595 
596 	AAS_ShowAreaPolygons( reach->areanum, 5, qtrue );
597 	//AAS_ShowArea(reach->areanum, qtrue);
598 	AAS_DrawArrow( reach->start, reach->end, LINECOLOR_BLUE, LINECOLOR_YELLOW );
599 	//
600 	if ( reach->traveltype == TRAVEL_JUMP || reach->traveltype == TRAVEL_WALKOFFLEDGE ) {
601 		AAS_HorizontalVelocityForJump( aassettings.sv_jumpvel, reach->start, reach->end, &speed );
602 		//
603 		VectorSubtract( reach->end, reach->start, dir );
604 		dir[2] = 0;
605 		VectorNormalize( dir );
606 		//set the velocity
607 		VectorScale( dir, speed, velocity );
608 		//set the command movement
609 		VectorClear( cmdmove );
610 		cmdmove[2] = aassettings.sv_jumpvel;
611 		//
612 		AAS_PredictClientMovement( &move, -1, reach->start, PRESENCE_NORMAL, qtrue,
613 								   velocity, cmdmove, 3, 30, 0.1,
614 								   SE_HITGROUND | SE_ENTERWATER | SE_ENTERSLIME |
615 								   SE_ENTERLAVA | SE_HITGROUNDDAMAGE, 0, qtrue );
616 		//
617 		if ( reach->traveltype == TRAVEL_JUMP ) {
618 			AAS_JumpReachRunStart( reach, dir );
619 			AAS_DrawCross( dir, 4, LINECOLOR_BLUE );
620 		} //end if
621 	} //end if
622 	else if ( reach->traveltype == TRAVEL_ROCKETJUMP ) {
623 		zvel = AAS_RocketJumpZVelocity( reach->start );
624 		AAS_HorizontalVelocityForJump( zvel, reach->start, reach->end, &speed );
625 		//
626 		VectorSubtract( reach->end, reach->start, dir );
627 		dir[2] = 0;
628 		VectorNormalize( dir );
629 		//get command movement
630 		VectorScale( dir, speed, cmdmove );
631 		VectorSet( velocity, 0, 0, zvel );
632 		//
633 		AAS_PredictClientMovement( &move, -1, reach->start, PRESENCE_NORMAL, qtrue,
634 								   velocity, cmdmove, 30, 30, 0.1,
635 								   SE_ENTERWATER | SE_ENTERSLIME |
636 								   SE_ENTERLAVA | SE_HITGROUNDDAMAGE |
637 								   SE_TOUCHJUMPPAD | SE_HITGROUNDAREA, reach->areanum, qtrue );
638 	} //end else if
639 	else if ( reach->traveltype == TRAVEL_JUMPPAD ) {
640 		VectorSet( cmdmove, 0, 0, 0 );
641 		//
642 		VectorSubtract( reach->end, reach->start, dir );
643 		dir[2] = 0;
644 		VectorNormalize( dir );
645 		//set the velocity
646 		//NOTE: the edgenum is the horizontal velocity
647 		VectorScale( dir, reach->edgenum, velocity );
648 		//NOTE: the facenum is the Z velocity
649 		velocity[2] = reach->facenum;
650 		//
651 		AAS_PredictClientMovement( &move, -1, reach->start, PRESENCE_NORMAL, qtrue,
652 								   velocity, cmdmove, 30, 30, 0.1,
653 								   SE_ENTERWATER | SE_ENTERSLIME |
654 								   SE_ENTERLAVA | SE_HITGROUNDDAMAGE |
655 								   SE_TOUCHJUMPPAD | SE_HITGROUNDAREA, reach->areanum, qtrue );
656 	} //end else if
657 } //end of the function AAS_ShowReachability
658 //===========================================================================
659 //
660 // Parameter:				-
661 // Returns:					-
662 // Changes Globals:		-
663 //===========================================================================
AAS_ShowReachableAreas(int areanum)664 void AAS_ShowReachableAreas( int areanum ) {
665 	aas_areasettings_t *settings;
666 	static aas_reachability_t reach;
667 	static int index, lastareanum;
668 	static float lasttime;
669 
670 	if ( areanum != lastareanum ) {
671 		index = 0;
672 		lastareanum = areanum;
673 	} //end if
674 	settings = &( *aasworld ).areasettings[areanum];
675 	//
676 	if ( !settings->numreachableareas ) {
677 		return;
678 	}
679 	//
680 	if ( index >= settings->numreachableareas ) {
681 		index = 0;
682 	}
683 	//
684 	if ( AAS_Time() - lasttime > 1.5 ) {
685 		memcpy( &reach, &( *aasworld ).reachability[settings->firstreachablearea + index], sizeof( aas_reachability_t ) );
686 		index++;
687 		lasttime = AAS_Time();
688 		AAS_PrintTravelType( reach.traveltype );
689 		botimport.Print( PRT_MESSAGE, "(traveltime: %i)\n", reach.traveltime );
690 	} //end if
691 	AAS_ShowReachability( &reach );
692 } //end of the function ShowReachableAreas
693