/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2006 Robert Beckebans <trebor_7@users.sourceforge.net>

This file is part of XreaL source code.

XreaL source code 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.

XreaL source code 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 XreaL source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/

/*****************************************************************************
 * name:		be_aas_debug.c
 *
 * desc:		AAS debug code
 *
 * $Archive: /MissionPack/code/botlib/be_aas_debug.c $
 *
 *****************************************************************************/

#include "../common/shared.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "l_libvar.h"
#include "aasfile.h"
#include "../../mod/game/botlib.h"
#include "../../mod/game/be_aas.h"
#include "be_interface.h"
#include "be_aas_funcs.h"
#include "be_aas_def.h"

#define MAX_DEBUGLINES				1024
#define MAX_DEBUGPOLYGONS			8192

int             debuglines[MAX_DEBUGLINES];
int             debuglinevisible[MAX_DEBUGLINES];
int             numdebuglines;

static int      debugpolygons[MAX_DEBUGPOLYGONS];

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_ClearShownPolygons(void)
{
	int             i;

//*
	for(i = 0; i < MAX_DEBUGPOLYGONS; i++)
	{
		if(debugpolygons[i])
			botimport.DebugPolygonDelete(debugpolygons[i]);
		debugpolygons[i] = 0;
	}							//end for
//*/
/*
	for (i = 0; i < MAX_DEBUGPOLYGONS; i++)
	{
		botimport.DebugPolygonDelete(i);
		debugpolygons[i] = 0;
	} //end for
*/
}								//end of the function AAS_ClearShownPolygons

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_ShowPolygon(int color, int numpoints, vec3_t * points)
{
	int             i;

	for(i = 0; i < MAX_DEBUGPOLYGONS; i++)
	{
		if(!debugpolygons[i])
		{
			debugpolygons[i] = botimport.DebugPolygonCreate(color, numpoints, points);
			break;
		}						//end if
	}							//end for
}								//end of the function AAS_ShowPolygon

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_ClearShownDebugLines(void)
{
	int             i;

	//make all lines invisible
	for(i = 0; i < MAX_DEBUGLINES; i++)
	{
		if(debuglines[i])
		{
			//botimport.DebugLineShow(debuglines[i], NULL, NULL, LINECOLOR_NONE);
			botimport.DebugLineDelete(debuglines[i]);
			debuglines[i] = 0;
			debuglinevisible[i] = qfalse;
		}						//end if
	}							//end for
}								//end of the function AAS_ClearShownDebugLines

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_DebugLine(vec3_t start, vec3_t end, int color)
{
	int             line;

	for(line = 0; line < MAX_DEBUGLINES; line++)
	{
		if(!debuglines[line])
		{
			debuglines[line] = botimport.DebugLineCreate();
			debuglinevisible[line] = qfalse;
			numdebuglines++;
		}						//end if
		if(!debuglinevisible[line])
		{
			botimport.DebugLineShow(debuglines[line], start, end, color);
			debuglinevisible[line] = qtrue;
			return;
		}						//end else
	}							//end for
}								//end of the function AAS_DebugLine

//===========================================================================
//
// Parameter:           -
// Returns:             -
// Changes Globals:     -
//===========================================================================
void AAS_PermanentLine(vec3_t start, vec3_t end, int color)
{
	int             line;

	line = botimport.DebugLineCreate();
	botimport.DebugLineShow(line, start, end, color);
}								//end of the function AAS_PermenentLine

//===========================================================================
//
// Parameter:           -
// Returns:             -
// Changes Globals:     -
//===========================================================================
void AAS_DrawPermanentCross(vec3_t origin, float size, int color)
{
	int             i, debugline;
	vec3_t          start, end;

	for(i = 0; i < 3; i++)
	{
		VectorCopy(origin, start);
		start[i] += size;
		VectorCopy(origin, end);
		end[i] -= size;
		AAS_DebugLine(start, end, color);
		debugline = botimport.DebugLineCreate();
		botimport.DebugLineShow(debugline, start, end, color);
	}							//end for
}								//end of the function AAS_DrawPermanentCross

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_DrawPlaneCross(vec3_t point, vec3_t normal, float dist, int type, int color)
{
	int             n0, n1, n2, j, line, lines[2];
	vec3_t          start1, end1, start2, end2;

	//make a cross in the hit plane at the hit point
	VectorCopy(point, start1);
	VectorCopy(point, end1);
	VectorCopy(point, start2);
	VectorCopy(point, end2);

	n0 = type % 3;
	n1 = (type + 1) % 3;
	n2 = (type + 2) % 3;
	start1[n1] -= 6;
	start1[n2] -= 6;
	end1[n1] += 6;
	end1[n2] += 6;
	start2[n1] += 6;
	start2[n2] -= 6;
	end2[n1] -= 6;
	end2[n2] += 6;

	start1[n0] = (dist - (start1[n1] * normal[n1] + start1[n2] * normal[n2])) / normal[n0];
	end1[n0] = (dist - (end1[n1] * normal[n1] + end1[n2] * normal[n2])) / normal[n0];
	start2[n0] = (dist - (start2[n1] * normal[n1] + start2[n2] * normal[n2])) / normal[n0];
	end2[n0] = (dist - (end2[n1] * normal[n1] + end2[n2] * normal[n2])) / normal[n0];

	for(j = 0, line = 0; j < 2 && line < MAX_DEBUGLINES; line++)
	{
		if(!debuglines[line])
		{
			debuglines[line] = botimport.DebugLineCreate();
			lines[j++] = debuglines[line];
			debuglinevisible[line] = qtrue;
			numdebuglines++;
		}						//end if
		else if(!debuglinevisible[line])
		{
			lines[j++] = debuglines[line];
			debuglinevisible[line] = qtrue;
		}						//end else
	}							//end for
	botimport.DebugLineShow(lines[0], start1, end1, color);
	botimport.DebugLineShow(lines[1], start2, end2, color);
}								//end of the function AAS_DrawPlaneCross

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_ShowBoundingBox(vec3_t origin, vec3_t mins, vec3_t maxs)
{
	vec3_t          bboxcorners[8];
	int             lines[3];
	int             i, j, line;

	//upper corners
	bboxcorners[0][0] = origin[0] + maxs[0];
	bboxcorners[0][1] = origin[1] + maxs[1];
	bboxcorners[0][2] = origin[2] + maxs[2];
	//
	bboxcorners[1][0] = origin[0] + mins[0];
	bboxcorners[1][1] = origin[1] + maxs[1];
	bboxcorners[1][2] = origin[2] + maxs[2];
	//
	bboxcorners[2][0] = origin[0] + mins[0];
	bboxcorners[2][1] = origin[1] + mins[1];
	bboxcorners[2][2] = origin[2] + maxs[2];
	//
	bboxcorners[3][0] = origin[0] + maxs[0];
	bboxcorners[3][1] = origin[1] + mins[1];
	bboxcorners[3][2] = origin[2] + maxs[2];
	//lower corners
	Com_Memcpy(bboxcorners[4], bboxcorners[0], sizeof(vec3_t) * 4);
	for(i = 0; i < 4; i++)
		bboxcorners[4 + i][2] = origin[2] + mins[2];
	//draw bounding box
	for(i = 0; i < 4; i++)
	{
		for(j = 0, line = 0; j < 3 && line < MAX_DEBUGLINES; line++)
		{
			if(!debuglines[line])
			{
				debuglines[line] = botimport.DebugLineCreate();
				lines[j++] = debuglines[line];
				debuglinevisible[line] = qtrue;
				numdebuglines++;
			}					//end if
			else if(!debuglinevisible[line])
			{
				lines[j++] = debuglines[line];
				debuglinevisible[line] = qtrue;
			}					//end else
		}						//end for
		//top plane
		botimport.DebugLineShow(lines[0], bboxcorners[i], bboxcorners[(i + 1) & 3], LINECOLOR_RED);
		//bottom plane
		botimport.DebugLineShow(lines[1], bboxcorners[4 + i], bboxcorners[4 + ((i + 1) & 3)], LINECOLOR_RED);
		//vertical lines
		botimport.DebugLineShow(lines[2], bboxcorners[i], bboxcorners[4 + i], LINECOLOR_RED);
	}							//end for
}								//end of the function AAS_ShowBoundingBox

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_ShowFace(int facenum)
{
	int             i, color, edgenum;
	aas_edge_t     *edge;
	aas_face_t     *face;
	aas_plane_t    *plane;
	vec3_t          start, end;

	color = LINECOLOR_YELLOW;
	//check if face number is in range
	if(facenum >= aasworld.numfaces)
	{
		botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
	}							//end if
	face = &aasworld.faces[facenum];
	//walk through the edges of the face
	for(i = 0; i < face->numedges; i++)
	{
		//edge number
		edgenum = abs(aasworld.edgeindex[face->firstedge + i]);
		//check if edge number is in range
		if(edgenum >= aasworld.numedges)
		{
			botimport.Print(PRT_ERROR, "edgenum %d out of range\n", edgenum);
		}						//end if
		edge = &aasworld.edges[edgenum];
		if(color == LINECOLOR_RED)
			color = LINECOLOR_GREEN;
		else if(color == LINECOLOR_GREEN)
			color = LINECOLOR_BLUE;
		else if(color == LINECOLOR_BLUE)
			color = LINECOLOR_YELLOW;
		else
			color = LINECOLOR_RED;
		AAS_DebugLine(aasworld.vertexes[edge->v[0]], aasworld.vertexes[edge->v[1]], color);
	}							//end for
	plane = &aasworld.planes[face->planenum];
	edgenum = abs(aasworld.edgeindex[face->firstedge]);
	edge = &aasworld.edges[edgenum];
	VectorCopy(aasworld.vertexes[edge->v[0]], start);
	VectorMA(start, 20, plane->normal, end);
	AAS_DebugLine(start, end, LINECOLOR_RED);
}								//end of the function AAS_ShowFace

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_ShowFacePolygon(int facenum, int color, int flip)
{
	int             i, edgenum, numpoints;
	vec3_t          points[128];
	aas_edge_t     *edge;
	aas_face_t     *face;

	//check if face number is in range
	if(facenum >= aasworld.numfaces)
	{
		botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
	}							//end if
	face = &aasworld.faces[facenum];
	//walk through the edges of the face
	numpoints = 0;
	if(flip)
	{
		for(i = face->numedges - 1; i >= 0; i--)
		{
			//edge number
			edgenum = aasworld.edgeindex[face->firstedge + i];
			edge = &aasworld.edges[abs(edgenum)];
			VectorCopy(aasworld.vertexes[edge->v[edgenum < 0]], points[numpoints]);
			numpoints++;
		}						//end for
	}							//end if
	else
	{
		for(i = 0; i < face->numedges; i++)
		{
			//edge number
			edgenum = aasworld.edgeindex[face->firstedge + i];
			edge = &aasworld.edges[abs(edgenum)];
			VectorCopy(aasworld.vertexes[edge->v[edgenum < 0]], points[numpoints]);
			numpoints++;
		}						//end for
	}							//end else
	AAS_ShowPolygon(color, numpoints, points);
}								//end of the function AAS_ShowFacePolygon

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_ShowArea(int areanum, int groundfacesonly)
{
	int             areaedges[MAX_DEBUGLINES];
	int             numareaedges, i, j, n, color = 0, line;
	int             facenum, edgenum;
	aas_area_t     *area;
	aas_face_t     *face;
	aas_edge_t     *edge;

	//
	numareaedges = 0;
	//
	if(areanum < 0 || areanum >= aasworld.numareas)
	{
		botimport.Print(PRT_ERROR, "area %d out of range [0, %d]\n", areanum, aasworld.numareas);
		return;
	}							//end if
	//pointer to the convex area
	area = &aasworld.areas[areanum];
	//walk through the faces of the area
	for(i = 0; i < area->numfaces; i++)
	{
		facenum = abs(aasworld.faceindex[area->firstface + i]);
		//check if face number is in range
		if(facenum >= aasworld.numfaces)
		{
			botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
		}						//end if
		face = &aasworld.faces[facenum];
		//ground faces only
		if(groundfacesonly)
		{
			if(!(face->faceflags & (FACE_GROUND | FACE_LADDER)))
				continue;
		}						//end if
		//walk through the edges of the face
		for(j = 0; j < face->numedges; j++)
		{
			//edge number
			edgenum = abs(aasworld.edgeindex[face->firstedge + j]);
			//check if edge number is in range
			if(edgenum >= aasworld.numedges)
			{
				botimport.Print(PRT_ERROR, "edgenum %d out of range\n", edgenum);
			}					//end if
			//check if the edge is stored already
			for(n = 0; n < numareaedges; n++)
			{
				if(areaedges[n] == edgenum)
					break;
			}					//end for
			if(n == numareaedges && numareaedges < MAX_DEBUGLINES)
			{
				areaedges[numareaedges++] = edgenum;
			}					//end if
		}						//end for
		//AAS_ShowFace(facenum);
	}							//end for
	//draw all the edges
	for(n = 0; n < numareaedges; n++)
	{
		for(line = 0; line < MAX_DEBUGLINES; line++)
		{
			if(!debuglines[line])
			{
				debuglines[line] = botimport.DebugLineCreate();
				debuglinevisible[line] = qfalse;
				numdebuglines++;
			}					//end if
			if(!debuglinevisible[line])
			{
				break;
			}					//end else
		}						//end for
		if(line >= MAX_DEBUGLINES)
			return;
		edge = &aasworld.edges[areaedges[n]];
		if(color == LINECOLOR_RED)
			color = LINECOLOR_BLUE;
		else if(color == LINECOLOR_BLUE)
			color = LINECOLOR_GREEN;
		else if(color == LINECOLOR_GREEN)
			color = LINECOLOR_YELLOW;
		else
			color = LINECOLOR_RED;
		botimport.DebugLineShow(debuglines[line], aasworld.vertexes[edge->v[0]], aasworld.vertexes[edge->v[1]], color);
		debuglinevisible[line] = qtrue;
	}							//end for*/
}								//end of the function AAS_ShowArea

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_ShowAreaPolygons(int areanum, int color, int groundfacesonly)
{
	int             i, facenum;
	aas_area_t     *area;
	aas_face_t     *face;

	//
	if(areanum < 0 || areanum >= aasworld.numareas)
	{
		botimport.Print(PRT_ERROR, "area %d out of range [0, %d]\n", areanum, aasworld.numareas);
		return;
	}							//end if
	//pointer to the convex area
	area = &aasworld.areas[areanum];
	//walk through the faces of the area
	for(i = 0; i < area->numfaces; i++)
	{
		facenum = abs(aasworld.faceindex[area->firstface + i]);
		//check if face number is in range
		if(facenum >= aasworld.numfaces)
		{
			botimport.Print(PRT_ERROR, "facenum %d out of range\n", facenum);
		}						//end if
		face = &aasworld.faces[facenum];
		//ground faces only
		if(groundfacesonly)
		{
			if(!(face->faceflags & (FACE_GROUND | FACE_LADDER)))
				continue;
		}						//end if
		AAS_ShowFacePolygon(facenum, color, face->frontarea != areanum);
	}							//end for
}								//end of the function AAS_ShowAreaPolygons

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_DrawCross(vec3_t origin, float size, int color)
{
	int             i;
	vec3_t          start, end;

	for(i = 0; i < 3; i++)
	{
		VectorCopy(origin, start);
		start[i] += size;
		VectorCopy(origin, end);
		end[i] -= size;
		AAS_DebugLine(start, end, color);
	}							//end for
}								//end of the function AAS_DrawCross

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_PrintTravelType(int traveltype)
{
#ifdef _DEBUG
	char           *str;

	//
	switch (traveltype & TRAVELTYPE_MASK)
	{
		case TRAVEL_INVALID:
			str = "TRAVEL_INVALID";
			break;
		case TRAVEL_WALK:
			str = "TRAVEL_WALK";
			break;
		case TRAVEL_CROUCH:
			str = "TRAVEL_CROUCH";
			break;
		case TRAVEL_BARRIERJUMP:
			str = "TRAVEL_BARRIERJUMP";
			break;
		case TRAVEL_JUMP:
			str = "TRAVEL_JUMP";
			break;
		case TRAVEL_LADDER:
			str = "TRAVEL_LADDER";
			break;
		case TRAVEL_WALKOFFLEDGE:
			str = "TRAVEL_WALKOFFLEDGE";
			break;
		case TRAVEL_SWIM:
			str = "TRAVEL_SWIM";
			break;
		case TRAVEL_WATERJUMP:
			str = "TRAVEL_WATERJUMP";
			break;
		case TRAVEL_TELEPORT:
			str = "TRAVEL_TELEPORT";
			break;
		case TRAVEL_ELEVATOR:
			str = "TRAVEL_ELEVATOR";
			break;
		case TRAVEL_ROCKETJUMP:
			str = "TRAVEL_ROCKETJUMP";
			break;
		case TRAVEL_BFGJUMP:
			str = "TRAVEL_BFGJUMP";
			break;
		case TRAVEL_GRAPPLEHOOK:
			str = "TRAVEL_GRAPPLEHOOK";
			break;
		case TRAVEL_JUMPPAD:
			str = "TRAVEL_JUMPPAD";
			break;
		case TRAVEL_FUNCBOB:
			str = "TRAVEL_FUNCBOB";
			break;
		default:
			str = "UNKNOWN TRAVEL TYPE";
			break;
	}							//end switch
	botimport.Print(PRT_MESSAGE, "%s", str);
#endif
}								//end of the function AAS_PrintTravelType

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_DrawArrow(vec3_t start, vec3_t end, int linecolor, int arrowcolor)
{
	vec3_t          dir, cross, p1, p2, up = { 0, 0, 1 };
	float           dot;

	VectorSubtract(end, start, dir);
	VectorNormalize(dir);
	dot = DotProduct(dir, up);
	if(dot > 0.99 || dot < -0.99)
		VectorSet(cross, 1, 0, 0);
	else
		CrossProduct(dir, up, cross);

	VectorMA(end, -6, dir, p1);
	VectorCopy(p1, p2);
	VectorMA(p1, 6, cross, p1);
	VectorMA(p2, -6, cross, p2);

	AAS_DebugLine(start, end, linecolor);
	AAS_DebugLine(p1, end, arrowcolor);
	AAS_DebugLine(p2, end, arrowcolor);
}								//end of the function AAS_DrawArrow

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_ShowReachability(aas_reachability_t * reach)
{
	vec3_t          dir, cmdmove, velocity;
	float           speed, zvel;
	aas_clientmove_t move;

	AAS_ShowAreaPolygons(reach->areanum, 5, qtrue);
	//AAS_ShowArea(reach->areanum, qtrue);
	AAS_DrawArrow(reach->start, reach->end, LINECOLOR_BLUE, LINECOLOR_YELLOW);
	//
	if((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP || (reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE)
	{
		AAS_HorizontalVelocityForJump(aassettings.phys_jumpvel, reach->start, reach->end, &speed);
		//
		VectorSubtract(reach->end, reach->start, dir);
		dir[2] = 0;
		VectorNormalize(dir);
		//set the velocity
		VectorScale(dir, speed, velocity);
		//set the command movement
		VectorClear(cmdmove);
		cmdmove[2] = aassettings.phys_jumpvel;
		//
		AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
								  velocity, cmdmove, 3, 30, 0.1f,
								  SE_HITGROUND | SE_ENTERWATER | SE_ENTERSLIME | SE_ENTERLAVA | SE_HITGROUNDDAMAGE, 0, qtrue);
		//
		if((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP)
		{
			AAS_JumpReachRunStart(reach, dir);
			AAS_DrawCross(dir, 4, LINECOLOR_BLUE);
		}						//end if
	}							//end if
	else if((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_ROCKETJUMP)
	{
		zvel = AAS_RocketJumpZVelocity(reach->start);
		AAS_HorizontalVelocityForJump(zvel, reach->start, reach->end, &speed);
		//
		VectorSubtract(reach->end, reach->start, dir);
		dir[2] = 0;
		VectorNormalize(dir);
		//get command movement
		VectorScale(dir, speed, cmdmove);
		VectorSet(velocity, 0, 0, zvel);
		//
		AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
								  velocity, cmdmove, 30, 30, 0.1f,
								  SE_ENTERWATER | SE_ENTERSLIME |
								  SE_ENTERLAVA | SE_HITGROUNDDAMAGE | SE_TOUCHJUMPPAD | SE_HITGROUNDAREA, reach->areanum, qtrue);
	}							//end else if
	else if((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMPPAD)
	{
		VectorSet(cmdmove, 0, 0, 0);
		//
		VectorSubtract(reach->end, reach->start, dir);
		dir[2] = 0;
		VectorNormalize(dir);
		//set the velocity
		//NOTE: the edgenum is the horizontal velocity
		VectorScale(dir, reach->edgenum, velocity);
		//NOTE: the facenum is the Z velocity
		velocity[2] = reach->facenum;
		//
		AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue,
								  velocity, cmdmove, 30, 30, 0.1f,
								  SE_ENTERWATER | SE_ENTERSLIME |
								  SE_ENTERLAVA | SE_HITGROUNDDAMAGE | SE_TOUCHJUMPPAD | SE_HITGROUNDAREA, reach->areanum, qtrue);
	}							//end else if
}								//end of the function AAS_ShowReachability

//===========================================================================
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void AAS_ShowReachableAreas(int areanum)
{
	aas_areasettings_t *settings;
	static aas_reachability_t reach;
	static int      index, lastareanum;
	static float    lasttime;

	if(areanum != lastareanum)
	{
		index = 0;
		lastareanum = areanum;
	}							//end if
	settings = &aasworld.areasettings[areanum];
	//
	if(!settings->numreachableareas)
		return;
	//
	if(index >= settings->numreachableareas)
		index = 0;
	//
	if(AAS_Time() - lasttime > 1.5)
	{
		Com_Memcpy(&reach, &aasworld.reachability[settings->firstreachablearea + index], sizeof(aas_reachability_t));
		index++;
		lasttime = AAS_Time();
		AAS_PrintTravelType(reach.traveltype & TRAVELTYPE_MASK);
		botimport.Print(PRT_MESSAGE, "\n");
	}							//end if
	AAS_ShowReachability(&reach);
}								//end of the function ShowReachableAreas

void AAS_FloodAreas_r(int areanum, int cluster, int *done)
{
	int             nextareanum, i, facenum;
	aas_area_t     *area;
	aas_face_t     *face;
	aas_areasettings_t *settings;
	aas_reachability_t *reach;

	AAS_ShowAreaPolygons(areanum, 1, qtrue);
	//pointer to the convex area
	area = &aasworld.areas[areanum];
	settings = &aasworld.areasettings[areanum];
	//walk through the faces of the area
	for(i = 0; i < area->numfaces; i++)
	{
		facenum = abs(aasworld.faceindex[area->firstface + i]);
		face = &aasworld.faces[facenum];
		if(face->frontarea == areanum)
			nextareanum = face->backarea;
		else
			nextareanum = face->frontarea;
		if(!nextareanum)
			continue;
		if(done[nextareanum])
			continue;
		done[nextareanum] = qtrue;
		if(aasworld.areasettings[nextareanum].contents & AREACONTENTS_VIEWPORTAL)
			continue;
		if(AAS_AreaCluster(nextareanum) != cluster)
			continue;
		AAS_FloodAreas_r(nextareanum, cluster, done);
	}							//end for
	//
	for(i = 0; i < settings->numreachableareas; i++)
	{
		reach = &aasworld.reachability[settings->firstreachablearea + i];
		nextareanum = reach->areanum;
		if(!nextareanum)
			continue;
		if(done[nextareanum])
			continue;
		done[nextareanum] = qtrue;
		if(aasworld.areasettings[nextareanum].contents & AREACONTENTS_VIEWPORTAL)
			continue;
		if(AAS_AreaCluster(nextareanum) != cluster)
			continue;
		/*
		   if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE)
		   {
		   AAS_DebugLine(reach->start, reach->end, 1);
		   }
		 */
		AAS_FloodAreas_r(nextareanum, cluster, done);
	}
}

void AAS_FloodAreas(vec3_t origin)
{
	int             areanum, cluster, *done;

	done = (int *)GetClearedMemory(aasworld.numareas * sizeof(int));
	areanum = AAS_PointAreaNum(origin);
	cluster = AAS_AreaCluster(areanum);
	AAS_FloodAreas_r(areanum, cluster, done);
}
