Esempio n. 1
0
int AAS_ClipToBBox(aas_trace_t *trace, vector3 *start, vector3 *end, int presencetype, vector3 *mins, vector3 *maxs) {
	int i, side;
	float front, back, frac, planedist;
	vector3 bboxmins, bboxmaxs, absmins, absmaxs, dir, mid;

	AAS_PresenceTypeBoundingBox(presencetype, &bboxmins, &bboxmaxs);
	VectorSubtract(mins, &bboxmaxs, &absmins);
	VectorSubtract(maxs, &bboxmins, &absmaxs);
	//
	VectorCopy(end, &trace->endpos);
	trace->fraction = 1;
	for (i = 0; i < 3; i++)
	{
		if (start->data[i] < absmins.data[i] && end->data[i] < absmins.data[i]) return qfalse;
		if (start->data[i] > absmaxs.data[i] && end->data[i] > absmaxs.data[i]) return qfalse;
	}
	//check bounding box collision
	VectorSubtract(end, start, &dir);
	frac = 1;
	for (i = 0; i < 3; i++)
	{
		//get plane to test collision with for the current axis direction
		if (dir.data[i] > 0) planedist = absmins.data[i];
		else planedist = absmaxs.data[i];
		//calculate collision fraction
		front = start->data[i] - planedist;
		back = end->data[i] - planedist;
		frac = front / (front-back);
		//check if between bounding planes of next axis
		side = i + 1;
		if (side > 2) side = 0;
		mid.data[side] = start->data[side] + dir.data[side] * frac;
		if (mid.data[side] > absmins.data[side] && mid.data[side] < absmaxs.data[side])
		{
			//check if between bounding planes of next axis
			side++;
			if (side > 2) side = 0;
			mid.data[side] = start->data[side] + dir.data[side] * frac;
			if (mid.data[side] > absmins.data[side] && mid.data[side] < absmaxs.data[side])
			{
				mid.data[i] = planedist;
				break;
			}
		}
	}
	//if there was a collision
	if (i != 3)
	{
		trace->startsolid = qfalse;
		trace->fraction = frac;
		trace->ent = 0;
		trace->planenum = 0;
		trace->area = 0;
		trace->lastarea = 0;
		//trace endpos
		VectorMA( start, frac, &dir, &trace->endpos );
		return qtrue;
	}
	return qfalse;
}
Esempio n. 2
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
qboolean AAS_AreaEntityCollision( int areanum, vec3_t start, vec3_t end,
								  int presencetype, int passent, aas_trace_t *trace ) {
	int collision;
	vec3_t boxmins, boxmaxs;
	aas_link_t *link;
	bsp_trace_t bsptrace;

	AAS_PresenceTypeBoundingBox( presencetype, boxmins, boxmaxs );

	memset( &bsptrace, 0, sizeof( bsp_trace_t ) ); //make compiler happy
	//assume no collision
	bsptrace.fraction = 1;
	collision = qfalse;
	for ( link = ( *aasworld ).arealinkedentities[areanum]; link; link = link->next_ent )
	{
		//ignore the pass entity
		if ( link->entnum == passent ) {
			continue;
		}
		//
		if ( AAS_EntityCollision( link->entnum, start, boxmins, boxmaxs, end,
								  CONTENTS_SOLID | CONTENTS_PLAYERCLIP, &bsptrace ) ) {
			collision = qtrue;
		} //end if
	} //end for
	if ( collision ) {
		trace->startsolid = bsptrace.startsolid;
		trace->ent = bsptrace.ent;
		VectorCopy( bsptrace.endpos, trace->endpos );
		trace->area = 0;
		trace->planenum = 0;
		return qtrue;
	} //end if
	return qfalse;
} //end of the function AAS_AreaEntityCollision
Esempio n. 3
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
aas_link_t *AAS_LinkEntityClientBBox( vec3_t absmins, vec3_t absmaxs, int entnum, int presencetype ) {
	vec3_t mins, maxs;
	vec3_t newabsmins, newabsmaxs;

	AAS_PresenceTypeBoundingBox( presencetype, mins, maxs );
	VectorSubtract( absmins, maxs, newabsmins );
	VectorSubtract( absmaxs, mins, newabsmaxs );
	//relink the entity
	return AAS_AASLinkEntity( newabsmins, newabsmaxs, entnum );
} //end of the function AAS_LinkEntityClientBBox
Esempio n. 4
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
qboolean AAS_AreaEntityCollision(int areanum, vec3_t start, vec3_t end,
										int presencetype, int passent, int contentmask, aas_trace_t *trace)
{
	int collision;
	vec3_t boxmins, boxmaxs;
	aas_link_t *link;
	bsp_trace_t bsptrace;

	AAS_PresenceTypeBoundingBox(presencetype, boxmins, boxmaxs);

	Com_Memset(&bsptrace, 0, sizeof(bsp_trace_t)); //make compiler happy
	//assume no collision
	bsptrace.fraction = 1;
	collision = qfalse;
	for (link = aasworld.arealinkedentities[areanum]; link; link = link->next_ent)
	{
		//ignore the pass entity
		if (link->entnum == passent) continue;
		//
		if (AAS_EntityCollision(link->entnum, start, boxmins, boxmaxs, end,
												contentmask, &bsptrace))
		{
			collision = qtrue;
		} //end if
	} //end for
	if (collision)
	{
		trace->startsolid = bsptrace.startsolid;
		trace->ent = bsptrace.entityNum;
		VectorCopy(bsptrace.endpos, trace->endpos);
		trace->area = 0;
		trace->planenum = 0;
		VectorCopy(bsptrace.plane.normal, trace->plane.normal);
		trace->plane.dist = bsptrace.plane.dist;
		// ZTM: FIXME: Are AAS plane type and BSP plane type the same values?
		trace->plane.type = bsptrace.plane.type;
		return qtrue;
	} //end if
	return qfalse;
} //end of the function AAS_AreaEntityCollision
Esempio n. 5
0
//===========================================================================
// returns qtrue if the bot is on the ground
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int AAS_OnGround(vec3_t origin, int presencetype, int passent)
{
	//aas_trace_t trace;
	bsp_trace_t trace;
	vec3_t      end, up = { 0, 0, 1 };
	//aas_plane_t *plane;
	vec3_t mins, maxs;

	VectorCopy(origin, end);
	end[2] -= 10;

	//trace = AAS_TraceClientBBox(origin, end, presencetype, passent);
	AAS_PresenceTypeBoundingBox(presencetype, mins, maxs);
	trace = AAS_Trace(origin, mins, maxs, end, passent, CONTENTS_SOLID | CONTENTS_PLAYERCLIP);

	//if in solid
	if (trace.startsolid)
	{
		return qtrue;                  //qfalse;
	}
	//if nothing hit at all
	if (trace.fraction >= 1.0)
	{
		return qfalse;
	}
	//if too far from the hit plane
	if (origin[2] - trace.endpos[2] > 10)
	{
		return qfalse;
	}
	//check if the plane isn't too steep
	//plane = AAS_PlaneFromNum(trace.planenum);
	if (DotProduct(trace.plane.normal, up) < aassettings.sv_maxsteepness)
	{
		return qfalse;
	}
	//the bot is on the ground
	return qtrue;
} //end of the function AAS_OnGround
Esempio n. 6
0
static bool BotTouchingGoal( const vec3_t origin, const bot_goal_t* goal ) {
	int i;
	vec3_t boxmins, boxmaxs;
	vec3_t absmins, absmaxs;
	vec3_t safety_maxs = {0, 0, 0};	//{4, 4, 10};
	vec3_t safety_mins = {0, 0, 0};	//{-4, -4, 0};

	AAS_PresenceTypeBoundingBox( PRESENCE_NORMAL, boxmins, boxmaxs );
	VectorSubtract( goal->mins, boxmaxs, absmins );
	VectorSubtract( goal->maxs, boxmins, absmaxs );
	VectorAdd( absmins, goal->origin, absmins );
	VectorAdd( absmaxs, goal->origin, absmaxs );
	//make the box a little smaller for safety
	VectorSubtract( absmaxs, safety_maxs, absmaxs );
	VectorSubtract( absmins, safety_mins, absmins );

	for ( i = 0; i < 3; i++ ) {
		if ( origin[ i ] < absmins[ i ] || origin[ i ] > absmaxs[ i ] ) {
			return false;
		}
	}
	return true;
}
Esempio n. 7
0
void AAS_AddTeleporterPortals(void)
{
	int j, area2num, facenum, otherareanum;
	char *target, *targetname, *classname;
	bsp_entity_t *entities, *ent, *dest;
	vec3_t origin, destorigin, mins, maxs, end;
	vec3_t bbmins, bbmaxs;
	aas_area_t *area;
	aas_face_t *face;
	aas_trace_t trace;
	aas_link_t *areas, *link;

	entities = AAS_ParseBSPEntities();

	for (ent = entities; ent; ent = ent->next)
	{
		classname = AAS_ValueForBSPEpairKey(ent, "classname");
		if (classname && !strcmp(classname, "misc_teleporter"))
		{
			if (!AAS_VectorForBSPEpairKey(ent, "origin", origin))
			{
				botimport.Print(PRT_ERROR, "teleporter (%s) without origin\n", target);
				continue;
			} //end if
			//
			target = AAS_ValueForBSPEpairKey(ent, "target");
			if (!target)
			{
				botimport.Print(PRT_ERROR, "teleporter (%s) without target\n", target);
				continue;
			} //end if
			for (dest = entities; dest; dest = dest->next)
			{
				classname = AAS_ValueForBSPEpairKey(dest, "classname");
				if (classname && !strcmp(classname, "misc_teleporter_dest"))
				{
					targetname = AAS_ValueForBSPEpairKey(dest, "targetname");
					if (targetname && !strcmp(targetname, target))
					{
						break;
					} //end if
				} //end if
			} //end for
			if (!dest)
			{
				botimport.Print(PRT_ERROR, "teleporter without destination (%s)\n", target);
				continue;
			} //end if
			if (!AAS_VectorForBSPEpairKey(dest, "origin", destorigin))
			{
				botimport.Print(PRT_ERROR, "teleporter destination (%s) without origin\n", target);
				continue;
			} //end if
			destorigin[2] += 24; //just for q2e1m2, the dork has put the telepads in the ground
			VectorCopy(destorigin, end);
			end[2] -= 100;
			trace = AAS_TraceClientBBox(destorigin, end, PRESENCE_CROUCH, -1);
			if (trace.startsolid)
			{
				botimport.Print(PRT_ERROR, "teleporter destination (%s) in solid\n", target);
				continue;
			} //end if
			VectorCopy(trace.endpos, destorigin);
			area2num = AAS_PointAreaNum(destorigin);
			//reset all cluster fields
			for (j = 0; j < aasworld.numareas; j++)
			{
				aasworld.areasettings[j].cluster = 0;
			} //end for
			//
			VectorSet(mins, -8, -8, 8);
			VectorSet(maxs, 8, 8, 24);
			//
			AAS_PresenceTypeBoundingBox(PRESENCE_CROUCH, bbmins, bbmaxs);
			//
			VectorAdd(origin, mins, mins);
			VectorAdd(origin, maxs, maxs);
			//add bounding box size
			VectorSubtract(mins, bbmaxs, mins);
			VectorSubtract(maxs, bbmins, maxs);
			//link an invalid (-1) entity
			areas = AAS_AASLinkEntity(mins, maxs, -1);
			//
			for (link = areas; link; link = link->next_area)
			{
				if (!AAS_AreaGrounded(link->areanum)) continue;
				//add the teleporter portal mark
				aasworld.areasettings[link->areanum].contents |= AREACONTENTS_CLUSTERPORTAL |
																			AREACONTENTS_TELEPORTAL;
			} //end for
			//
			for (link = areas; link; link = link->next_area)
			{
				if (!AAS_AreaGrounded(link->areanum)) continue;
				//find a non-portal area adjacent to the portal area and flood
				//the cluster from there
				area = &aasworld.areas[link->areanum];
				for (j = 0; j < area->numfaces; j++)
				{
					facenum = abs(aasworld.faceindex[area->firstface + j]);
					face = &aasworld.faces[facenum];
					//
					if (face->frontarea != link->areanum) otherareanum = face->frontarea;
					else otherareanum = face->backarea;
					//
					if (!otherareanum) continue;
					//
					if (aasworld.areasettings[otherareanum].contents & AREACONTENTS_CLUSTERPORTAL)
					{
						continue;
					} //end if
					//
					AAS_FloodCluster_r(otherareanum, 1);
				} //end for
			} //end for
			//if the teleport destination IS in the same cluster
			if (aasworld.areasettings[area2num].cluster)
			{
				for (link = areas; link; link = link->next_area)
				{
					if (!AAS_AreaGrounded(link->areanum)) continue;
					//add the teleporter portal mark
					aasworld.areasettings[link->areanum].contents &= ~(AREACONTENTS_CLUSTERPORTAL |
																				AREACONTENTS_TELEPORTAL);
				} //end for
			} //end if
		} //end if
	} //end for
	AAS_FreeBSPEntities(entities);
} //end of the function AAS_AddTeleporterPortals
Esempio n. 8
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
int AAS_ClipToBBox(aas_trace_t *trace, vec3_t start, vec3_t end, int presencetype, vec3_t mins, vec3_t maxs)
{
	int i, j, side;
	float front, back, frac, planedist;
	vec3_t bboxmins, bboxmaxs, absmins, absmaxs, dir, mid;

	AAS_PresenceTypeBoundingBox(presencetype, bboxmins, bboxmaxs);
	VectorSubtract(mins, bboxmaxs, absmins);
	VectorSubtract(maxs, bboxmins, absmaxs);
	//
	VectorCopy(end, trace->endpos);
	trace->fraction = 1;
	for (i = 0; i < 3; i++)
	{
		if (start[i] < absmins[i] && end[i] < absmins[i]) return qfalse;
		if (start[i] > absmaxs[i] && end[i] > absmaxs[i]) return qfalse;
	} //end for
	//check bounding box collision
	VectorSubtract(end, start, dir);
	frac = 1;
	for (i = 0; i < 3; i++)
	{
		//get plane to test collision with for the current axis direction
		if (dir[i] > 0) planedist = absmins[i];
		else planedist = absmaxs[i];
		//calculate collision fraction
		front = start[i] - planedist;
		back = end[i] - planedist;
		frac = front / (front-back);
		//check if between bounding planes of next axis
		side = i + 1;
		if (side > 2) side = 0;
		mid[side] = start[side] + dir[side] * frac;
		if (mid[side] > absmins[side] && mid[side] < absmaxs[side])
		{
			//check if between bounding planes of next axis
			side++;
			if (side > 2) side = 0;
			mid[side] = start[side] + dir[side] * frac;
			if (mid[side] > absmins[side] && mid[side] < absmaxs[side])
			{
				mid[i] = planedist;
				break;
			} //end if
		} //end if
	} //end for
	//if there was a collision
	if (i != 3)
	{
		trace->startsolid = qfalse;
		trace->fraction = frac;
		trace->ent = 0;
		trace->planenum = 0;
		trace->area = 0;
		trace->lastarea = 0;
		//trace endpos
		for (j = 0; j < 3; j++) trace->endpos[j] = start[j] + dir[j] * frac;
		return qtrue;
	} //end if
	return qfalse;
} //end of the function AAS_ClipToBBox
Esempio n. 9
0
//===========================================================================
// predicts the movement
// assumes regular bounding box sizes
// NOTE: out of water jumping is not included
// NOTE: grappling hook is not included
//
// Parameter:				origin			: origin to start with
//								presencetype	: presence type to start with
//								velocity			: velocity to start with
//								cmdmove			: client command movement
//								cmdframes		: number of frame cmdmove is valid
//								maxframes		: maximum number of predicted frames
//								frametime		: duration of one predicted frame
//								stopevent		: events that stop the prediction
//						stopareanum		: stop as soon as entered this area
// Returns:					aas_clientmove_t
// Changes Globals:		-
//===========================================================================
int AAS_PredictClientMovement( struct aas_clientmove_s *move,
							   int entnum, vec3_t origin,

#if !defined RTCW_ET
							   int presencetype, int onground,
#else
							   int hitent, int onground,
#endif // RTCW_XX

							   vec3_t velocity, vec3_t cmdmove,
							   int cmdframes,
							   int maxframes, float frametime,
							   int stopevent, int stopareanum, int visualize ) {
	float sv_friction, sv_stopspeed, sv_gravity, sv_waterfriction;
	float sv_watergravity;
	float sv_walkaccelerate, sv_airaccelerate, sv_swimaccelerate;
	float sv_maxwalkvelocity, sv_maxcrouchvelocity, sv_maxswimvelocity;
	float sv_maxstep, sv_maxsteepness, sv_jumpvel, friction;
	float gravity, delta, maxvel, wishspeed, accelerate;
	//float velchange, newvel;
	int n, i, j, pc, step, swimming, ax, crouch, event, jump_frame, areanum;
	int areas[20], numareas;

#if !defined RTCW_ET
	vec3_t points[20];
	vec3_t org, end, feet, start, stepend, lastorg, wishdir;
	vec3_t frame_test_vel, old_frame_test_vel, left_test_vel;
	vec3_t up = {0, 0, 1};
	aas_plane_t *plane, *plane2;
	aas_trace_t trace, steptrace;
#else
	vec3_t points[20], mins, maxs;
	vec3_t org, end, feet, start, stepend, lastorg, wishdir;
	vec3_t frame_test_vel, old_frame_test_vel, left_test_vel, savevel;
	vec3_t up = {0, 0, 1};
	cplane_t *plane, *plane2, *lplane;
	//aas_trace_t trace, steptrace;
	bsp_trace_t trace, steptrace;

	if ( visualize ) {

// These debugging tools are not currently available in bspc. Mad Doctor I, 1/27/2003.
#ifndef BSPC
		AAS_ClearShownPolygons();
		AAS_ClearShownDebugLines();
#endif

	}

	// don't let us succeed on interaction with area 0
	if ( stopareanum == 0 ) {
		stopevent &= ~( SE_ENTERAREA | SE_HITGROUNDAREA );
	}
#endif // RTCW_XX


	if ( frametime <= 0 ) {
		frametime = 0.1;
	}
	//
	sv_friction = aassettings.sv_friction;
	sv_stopspeed = aassettings.sv_stopspeed;
	sv_gravity = aassettings.sv_gravity;
	sv_waterfriction = aassettings.sv_waterfriction;
	sv_watergravity = aassettings.sv_watergravity;
	sv_maxwalkvelocity = aassettings.sv_maxwalkvelocity; // * frametime;
	sv_maxcrouchvelocity = aassettings.sv_maxcrouchvelocity; // * frametime;
	sv_maxswimvelocity = aassettings.sv_maxswimvelocity; // * frametime;
	sv_walkaccelerate = aassettings.sv_walkaccelerate;
	sv_airaccelerate = aassettings.sv_airaccelerate;
	sv_swimaccelerate = aassettings.sv_swimaccelerate;
	sv_maxstep = aassettings.sv_maxstep;
	sv_maxsteepness = aassettings.sv_maxsteepness;
	sv_jumpvel = aassettings.sv_jumpvel * frametime;
	//
	memset( move, 0, sizeof( aas_clientmove_t ) );

#if !defined RTCW_ET
	memset( &trace, 0, sizeof( aas_trace_t ) );
#else
	memset( &trace, 0, sizeof( bsp_trace_t ) );
	AAS_PresenceTypeBoundingBox( PRESENCE_NORMAL, mins, maxs );
#endif // RTCW_XX

	//start at the current origin
	VectorCopy( origin, org );
	org[2] += 0.25;

#if defined RTCW_ET
	// test this position, if it's in solid, move it up to adjust for capsules
	//trace = AAS_TraceClientBBox(org, org, PRESENCE_NORMAL, entnum);
	trace = AAS_Trace( org, mins, maxs, org, entnum, ( CONTENTS_SOLID | CONTENTS_PLAYERCLIP ) & ~CONTENTS_BODY );
	while ( trace.startsolid ) {
		org[2] += 8;
		//trace = AAS_TraceClientBBox(org, org, PRESENCE_NORMAL, entnum);
		trace = AAS_Trace( org, mins, maxs, org, entnum, ( CONTENTS_SOLID | CONTENTS_PLAYERCLIP ) & ~CONTENTS_BODY );
		if ( trace.startsolid && ( org[2] - origin[2] > 16 ) ) {
			move->stopevent = SE_NONE;
			return qfalse;
		}
	}
#endif // RTCW_XX

	//velocity to test for the first frame
	VectorScale( velocity, frametime, frame_test_vel );
	//
	jump_frame = -1;

#if defined RTCW_ET
	lplane = NULL;
#endif // RTCW_XX

	//predict a maximum of 'maxframes' ahead
	for ( n = 0; n < maxframes; n++ )
	{
		swimming = AAS_Swimming( org );
		//get gravity depending on swimming or not
		gravity = swimming ? sv_watergravity : sv_gravity;
		//apply gravity at the START of the frame
		frame_test_vel[2] = frame_test_vel[2] - ( gravity * 0.1 * frametime );
		//if on the ground or swimming
		if ( onground || swimming ) {
			friction = swimming ? sv_friction : sv_waterfriction;
			//apply friction
			VectorScale( frame_test_vel, 1 / frametime, frame_test_vel );
			AAS_ApplyFriction( frame_test_vel, friction, sv_stopspeed, frametime );
			VectorScale( frame_test_vel, frametime, frame_test_vel );
		} //end if
		crouch = qfalse;
		//apply command movement

#if !defined RTCW_ET
		if ( n < cmdframes ) {
#else
		if ( cmdframes < 0 ) {
			// cmdmove is the destination, we should keep moving towards it
			VectorSubtract( cmdmove, org, wishdir );
			VectorNormalize( wishdir );
			VectorScale( wishdir, sv_maxwalkvelocity, wishdir );
			VectorCopy( frame_test_vel, savevel );
			VectorScale( wishdir, frametime, frame_test_vel );
			if ( !swimming ) {
				frame_test_vel[2] = savevel[2];
			}
		} else if ( n < cmdframes ) {
#endif // RTCW_XX

			ax = 0;
			maxvel = sv_maxwalkvelocity;
			accelerate = sv_airaccelerate;
			VectorCopy( cmdmove, wishdir );
			if ( onground ) {
				if ( cmdmove[2] < -300 ) {
					crouch = qtrue;
					maxvel = sv_maxcrouchvelocity;
				} //end if
				  //if not swimming and upmove is positive then jump
				if ( !swimming && cmdmove[2] > 1 ) {
					//jump velocity minus the gravity for one frame + 5 for safety
					frame_test_vel[2] = sv_jumpvel - ( gravity * 0.1 * frametime ) + 5;
					jump_frame = n;
					//jumping so air accelerate
					accelerate = sv_airaccelerate;
				} //end if
				else
				{
					accelerate = sv_walkaccelerate;
				} //end else
				ax = 2;
			} //end if
			if ( swimming ) {
				maxvel = sv_maxswimvelocity;
				accelerate = sv_swimaccelerate;
				ax = 3;
			} //end if
			else
			{
				wishdir[2] = 0;
			} //end else
			  //
			wishspeed = VectorNormalize( wishdir );
			if ( wishspeed > maxvel ) {
				wishspeed = maxvel;
			}
			VectorScale( frame_test_vel, 1 / frametime, frame_test_vel );
			AAS_Accelerate( frame_test_vel, frametime, wishdir, wishspeed, accelerate );
			VectorScale( frame_test_vel, frametime, frame_test_vel );
			/*
			for (i = 0; i < ax; i++)
			{
				velchange = (cmdmove[i] * frametime) - frame_test_vel[i];
				if (velchange > sv_maxacceleration) velchange = sv_maxacceleration;
				else if (velchange < -sv_maxacceleration) velchange = -sv_maxacceleration;
				newvel = frame_test_vel[i] + velchange;
				//
				if (frame_test_vel[i] <= maxvel && newvel > maxvel) frame_test_vel[i] = maxvel;
				else if (frame_test_vel[i] >= -maxvel && newvel < -maxvel) frame_test_vel[i] = -maxvel;
				else frame_test_vel[i] = newvel;
			} //end for
			*/
		} //end if

#if !defined RTCW_ET
		if ( crouch ) {
			presencetype = PRESENCE_CROUCH;
		} //end if
		else if ( presencetype == PRESENCE_CROUCH ) {
			if ( AAS_PointPresenceType( org ) & PRESENCE_NORMAL ) {
				presencetype = PRESENCE_NORMAL;
			} //end if
		} //end else
#else
		  //if (crouch)
		  //{
		  //	presencetype = PRESENCE_CROUCH;
		  //} //end if
		  //else if (presencetype == PRESENCE_CROUCH)
		  //{
		  //	if (AAS_PointPresenceType(org) & PRESENCE_NORMAL)
		  //	{
		  //		presencetype = PRESENCE_NORMAL;
		  //	} //end if
		  //} //end else
#endif // RTCW_XX

		  //save the current origin
		VectorCopy( org, lastorg );
		//move linear during one frame
		VectorCopy( frame_test_vel, left_test_vel );
		j = 0;
		do
		{
			VectorAdd( org, left_test_vel, end );
			//trace a bounding box

#if !defined RTCW_ET
			trace = AAS_TraceClientBBox( org, end, presencetype, entnum );
#else
			//trace = AAS_TraceClientBBox(org, end, PRESENCE_NORMAL, entnum);
			trace = AAS_Trace( org, mins, maxs, end, entnum, ( CONTENTS_SOLID | CONTENTS_PLAYERCLIP ) & ~CONTENTS_BODY );
#endif // RTCW_XX

			//
//#ifdef AAS_MOVE_DEBUG
			if ( visualize ) {

#if !defined RTCW_ET
				if ( trace.startsolid ) {
					botimport.Print( PRT_MESSAGE, "PredictMovement: start solid\n" );
				}
#else
				//if (trace.startsolid)
				//botimport.Print(PRT_MESSAGE, "PredictMovement: start solid\n");
#endif // RTCW_XX

				AAS_DebugLine( org, trace.endpos, LINECOLOR_RED );
			} //end if
//#endif //AAS_MOVE_DEBUG
			//

#if defined RTCW_ET
			if ( stopevent & SE_HITENT ) {
				if ( trace.fraction < 1.0 && trace.ent == hitent ) {
					areanum = AAS_PointAreaNum( org );
					VectorCopy( org, move->endpos );
					VectorScale( frame_test_vel, 1 / frametime, move->velocity );
					move->trace = trace;
					move->stopevent = SE_HITENT;
					move->presencetype = ( *aasworld ).areasettings[areanum].presencetype;
					move->endcontents = 0;
					move->time = n * frametime;
					move->frames = n;
					return qtrue;
				}
			}
#endif // RTCW_XX

			if ( stopevent & SE_ENTERAREA ) {
				numareas = AAS_TraceAreas( org, trace.endpos, areas, points, 20 );
				for ( i = 0; i < numareas; i++ )
				{
					if ( areas[i] == stopareanum ) {
						VectorCopy( points[i], move->endpos );
						VectorScale( frame_test_vel, 1 / frametime, move->velocity );
						move->trace = trace;
						move->stopevent = SE_ENTERAREA;

#if !defined RTCW_ET
						move->presencetype = presencetype;
#else
						move->presencetype = ( *aasworld ).areasettings[areas[i]].presencetype;
#endif // RTCW_XX

						move->endcontents = 0;
						move->time = n * frametime;
						move->frames = n;
						return qtrue;
					} //end if
				} //end for
			} //end if

#if defined RTCW_ET
			if ( stopevent & SE_STUCK ) {
				if ( trace.fraction < 1.0 ) {
					plane = &trace.plane;
					//if (Q_fabs(plane->normal[2]) <= sv_maxsteepness) {
					VectorNormalize2( frame_test_vel, wishdir );
					if ( DotProduct( plane->normal, wishdir ) < -0.8 ) {
						areanum = AAS_PointAreaNum( org );
						VectorCopy( org, move->endpos );
						VectorScale( frame_test_vel, 1 / frametime, move->velocity );
						move->trace = trace;
						move->stopevent = SE_STUCK;
						move->presencetype = ( *aasworld ).areasettings[areanum].presencetype;
						move->endcontents = 0;
						move->time = n * frametime;
						move->frames = n;
						return qtrue;
					}
				}
			}
#endif // RTCW_XX

			  //move the entity to the trace end point
			VectorCopy( trace.endpos, org );
			//if there was a collision
			if ( trace.fraction < 1.0 ) {
				//get the plane the bounding box collided with

#if !defined RTCW_ET
				plane = AAS_PlaneFromNum( trace.planenum );
#else
				plane = &trace.plane;
#endif // RTCW_XX

				//
				if ( stopevent & SE_HITGROUNDAREA ) {
					if ( DotProduct( plane->normal, up ) > sv_maxsteepness ) {
						VectorCopy( org, start );
						start[2] += 0.5;

#if !defined RTCW_ET
						if ( AAS_PointAreaNum( start ) == stopareanum ) {
#else
						if ( ( stopareanum < 0 && AAS_PointAreaNum( start ) ) || ( AAS_PointAreaNum( start ) == stopareanum ) ) {
#endif // RTCW_XX

							VectorCopy( start, move->endpos );
							VectorScale( frame_test_vel, 1 / frametime, move->velocity );
							move->trace = trace;
							move->stopevent = SE_HITGROUNDAREA;

#if !defined RTCW_ET
							move->presencetype = presencetype;
#else
							move->presencetype = ( *aasworld ).areasettings[stopareanum].presencetype;
#endif // RTCW_XX

							move->endcontents = 0;
							move->time = n * frametime;
							move->frames = n;
							return qtrue;
						} //end if
					} //end if
				} //end if
				  //assume there's no step
				step = qfalse;
				//if it is a vertical plane and the bot didn't jump recently
				if ( plane->normal[2] == 0 && ( jump_frame < 0 || n - jump_frame > 2 ) ) {
					//check for a step
					VectorMA( org, -0.25, plane->normal, start );
					VectorCopy( start, stepend );
					start[2] += sv_maxstep;

#if !defined RTCW_ET
					steptrace = AAS_TraceClientBBox( start, stepend, presencetype, entnum );
#else
					//steptrace = AAS_TraceClientBBox(start, stepend, PRESENCE_NORMAL, entnum);
					steptrace = AAS_Trace( start, mins, maxs, stepend, entnum, ( CONTENTS_SOLID | CONTENTS_PLAYERCLIP ) & ~CONTENTS_BODY );
#endif // RTCW_XX

					//
					if ( !steptrace.startsolid ) {

#if !defined RTCW_ET
						plane2 = AAS_PlaneFromNum( steptrace.planenum );
#else
						plane2 = &steptrace.plane;
#endif // RTCW_XX

						if ( DotProduct( plane2->normal, up ) > sv_maxsteepness ) {
							VectorSubtract( end, steptrace.endpos, left_test_vel );
							left_test_vel[2] = 0;
							frame_test_vel[2] = 0;
//#ifdef AAS_MOVE_DEBUG
							if ( visualize ) {
								if ( steptrace.endpos[2] - org[2] > 0.125 ) {
									VectorCopy( org, start );
									start[2] = steptrace.endpos[2];
									AAS_DebugLine( org, start, LINECOLOR_BLUE );
								} //end if
							} //end if
//#endif //AAS_MOVE_DEBUG
							org[2] = steptrace.endpos[2];
							step = qtrue;
						} //end if
					} //end if
				} //end if
				  //
				if ( !step ) {
					//velocity left to test for this frame is the projection
					//of the current test velocity into the hit plane
					VectorMA( left_test_vel, -DotProduct( left_test_vel, plane->normal ),
							  plane->normal, left_test_vel );

#if defined RTCW_ET
					// RF: from PM_SlideMove()
					// if this is the same plane we hit before, nudge velocity
					// out along it, which fixes some epsilon issues with
					// non-axial planes
					if ( lplane && DotProduct( lplane->normal, plane->normal ) > 0.99 ) {
						VectorAdd( plane->normal, left_test_vel, left_test_vel );
					}
					lplane = plane;
#endif // RTCW_XX

					//store the old velocity for landing check
					VectorCopy( frame_test_vel, old_frame_test_vel );
					//test velocity for the next frame is the projection
					//of the velocity of the current frame into the hit plane
					VectorMA( frame_test_vel, -DotProduct( frame_test_vel, plane->normal ),
							  plane->normal, frame_test_vel );
					//check for a landing on an almost horizontal floor
					if ( DotProduct( plane->normal, up ) > sv_maxsteepness ) {
						onground = qtrue;
					} //end if
					if ( stopevent & SE_HITGROUNDDAMAGE ) {
						delta = 0;
						if ( old_frame_test_vel[2] < 0 &&
							 frame_test_vel[2] > old_frame_test_vel[2] &&
							 !onground ) {
							delta = old_frame_test_vel[2];
						} //end if
						else if ( onground ) {
							delta = frame_test_vel[2] - old_frame_test_vel[2];
						} //end else
						if ( delta ) {
							delta = delta * 10;
							delta = delta * delta * 0.0001;
							if ( swimming ) {
								delta = 0;
							}
							// never take falling damage if completely underwater
							/*
							if (ent->waterlevel == 3) return;
							if (ent->waterlevel == 2) delta *= 0.25;
							if (ent->waterlevel == 1) delta *= 0.5;
							*/
							if ( delta > 40 ) {
								VectorCopy( org, move->endpos );
								VectorCopy( frame_test_vel, move->velocity );
								move->trace = trace;
								move->stopevent = SE_HITGROUNDDAMAGE;

#if !defined RTCW_ET
								move->presencetype = presencetype;
#else
								areanum = AAS_PointAreaNum( org );
								if ( areanum ) {
									move->presencetype = ( *aasworld ).areasettings[areanum].presencetype;
								}
#endif // RTCW_XX

								move->endcontents = 0;
								move->time = n * frametime;
								move->frames = n;
								return qtrue;
							} //end if
						} //end if
					} //end if
				} //end if
			} //end if
			  //extra check to prevent endless loop
			if ( ++j > 20 ) {
				return qfalse;
			}
			//while there is a plane hit
		} while ( trace.fraction < 1.0 );
		//if going down
		if ( frame_test_vel[2] <= 10 ) {
			//check for a liquid at the feet of the bot
			VectorCopy( org, feet );
			feet[2] -= 22;
			pc = AAS_PointContents( feet );
			//get event from pc
			event = SE_NONE;
			if ( pc & CONTENTS_LAVA ) {
				event |= SE_ENTERLAVA;
			}
			if ( pc & CONTENTS_SLIME ) {
				event |= SE_ENTERSLIME;
			}
			if ( pc & CONTENTS_WATER ) {
				event |= SE_ENTERWATER;
			}
			//
			areanum = AAS_PointAreaNum( org );
			if ( ( *aasworld ).areasettings[areanum].contents & AREACONTENTS_LAVA ) {
				event |= SE_ENTERLAVA;
			}
			if ( ( *aasworld ).areasettings[areanum].contents & AREACONTENTS_SLIME ) {
				event |= SE_ENTERSLIME;
			}
			if ( ( *aasworld ).areasettings[areanum].contents & AREACONTENTS_WATER ) {
				event |= SE_ENTERWATER;
			}
			//if in lava or slime
			if ( event & stopevent ) {
				VectorCopy( org, move->endpos );
				VectorScale( frame_test_vel, 1 / frametime, move->velocity );
				move->stopevent = event & stopevent;

#if !defined RTCW_ET
				move->presencetype = presencetype;
#else
				move->presencetype = ( *aasworld ).areasettings[areanum].presencetype;
#endif // RTCW_XX

				move->endcontents = pc;
				move->time = n * frametime;
				move->frames = n;
				return qtrue;
			} //end if
		} //end if
		  //

#if !defined RTCW_ET
		onground = AAS_OnGround( org, presencetype, entnum );
#else
		onground = AAS_OnGround( org, PRESENCE_NORMAL, entnum );
#endif // RTCW_XX

		//if onground and on the ground for at least one whole frame
		if ( onground ) {
			if ( stopevent & SE_HITGROUND ) {
				VectorCopy( org, move->endpos );
				VectorScale( frame_test_vel, 1 / frametime, move->velocity );
				move->trace = trace;
				move->stopevent = SE_HITGROUND;

#if !defined RTCW_ET
				move->presencetype = presencetype;
#else
				areanum = AAS_PointAreaNum( org );
				if ( areanum ) {
					move->presencetype = ( *aasworld ).areasettings[areanum].presencetype;
				}
#endif // RTCW_XX

				move->endcontents = 0;
				move->time = n * frametime;
				move->frames = n;
				return qtrue;
			} //end if
		} //end if
		else if ( stopevent & SE_LEAVEGROUND ) {
			VectorCopy( org, move->endpos );
			VectorScale( frame_test_vel, 1 / frametime, move->velocity );
			move->trace = trace;
			move->stopevent = SE_LEAVEGROUND;

#if !defined RTCW_ET
			move->presencetype = presencetype;
#else
			areanum = AAS_PointAreaNum( org );
			if ( areanum ) {
				move->presencetype = ( *aasworld ).areasettings[areanum].presencetype;
			}
#endif // RTCW_XX

			move->endcontents = 0;
			move->time = n * frametime;
			move->frames = n;
			return qtrue;
		} //end else if
		else if ( stopevent & SE_GAP ) {

#if !defined RTCW_ET
			aas_trace_t gaptrace;
#else
			bsp_trace_t gaptrace;
#endif // RTCW_XX

			VectorCopy( org, start );
			VectorCopy( start, end );
			end[2] -= 48 + aassettings.sv_maxbarrier;

#if !defined RTCW_ET
			gaptrace = AAS_TraceClientBBox( start, end, PRESENCE_CROUCH, -1 );
#else
			//gaptrace = AAS_TraceClientBBox(start, end, PRESENCE_CROUCH, -1);
			gaptrace = AAS_Trace( start, mins, maxs, end, -1, ( CONTENTS_SOLID | CONTENTS_PLAYERCLIP ) & ~CONTENTS_BODY );
#endif // RTCW_XX

			//if solid is found the bot cannot walk any further and will not fall into a gap
			if ( !gaptrace.startsolid ) {
				//if it is a gap (lower than one step height)
				if ( gaptrace.endpos[2] < org[2] - aassettings.sv_maxstep - 1 ) {
					if ( !( AAS_PointContents( end ) & ( CONTENTS_WATER | CONTENTS_SLIME ) ) ) { //----(SA)	modified since slime is no longer deadly
//					if (!(AAS_PointContents(end) & CONTENTS_WATER))
						VectorCopy( lastorg, move->endpos );
						VectorScale( frame_test_vel, 1 / frametime, move->velocity );
						move->trace = trace;
						move->stopevent = SE_GAP;

#if !defined RTCW_ET
						move->presencetype = presencetype;
#else
						areanum = AAS_PointAreaNum( org );
						if ( areanum ) {
							move->presencetype = ( *aasworld ).areasettings[areanum].presencetype;
						}
#endif // RTCW_XX

						move->endcontents = 0;
						move->time = n * frametime;
						move->frames = n;
						return qtrue;
					} //end if
				} //end if
			} //end if
		} //end else if
		if ( stopevent & SE_TOUCHJUMPPAD ) {
			if ( ( *aasworld ).areasettings[AAS_PointAreaNum( org )].contents & AREACONTENTS_JUMPPAD ) {
				VectorCopy( org, move->endpos );
				VectorScale( frame_test_vel, 1 / frametime, move->velocity );
				move->trace = trace;
				move->stopevent = SE_TOUCHJUMPPAD;

#if !defined RTCW_ET
				move->presencetype = presencetype;
#else
				areanum = AAS_PointAreaNum( org );
				if ( areanum ) {
					move->presencetype = ( *aasworld ).areasettings[areanum].presencetype;
				}
#endif // RTCW_XX

				move->endcontents = 0;
				move->time = n * frametime;
				move->frames = n;
				return qtrue;
			} //end if
		} //end if
		if ( stopevent & SE_TOUCHTELEPORTER ) {
			if ( ( *aasworld ).areasettings[AAS_PointAreaNum( org )].contents & AREACONTENTS_TELEPORTER ) {
				VectorCopy( org, move->endpos );
				VectorScale( frame_test_vel, 1 / frametime, move->velocity );
				move->trace = trace;
				move->stopevent = SE_TOUCHTELEPORTER;

#if !defined RTCW_ET
				move->presencetype = presencetype;
#else
				areanum = AAS_PointAreaNum( org );
				if ( areanum ) {
					move->presencetype = ( *aasworld ).areasettings[areanum].presencetype;
				}
#endif // RTCW_XX

				move->endcontents = 0;
				move->time = n * frametime;
				move->frames = n;
				return qtrue;
			} //end if
		} //end if
	} //end for
	  //

#if defined RTCW_ET
	areanum = AAS_PointAreaNum( org );
#endif // RTCW_XX

	VectorCopy( org, move->endpos );
	VectorScale( frame_test_vel, 1 / frametime, move->velocity );
	move->stopevent = SE_NONE;

#if !defined RTCW_ET
	move->presencetype = presencetype;
#else
	move->presencetype = aasworld->areasettings ? aasworld->areasettings[areanum].presencetype : 0;
#endif // RTCW_XX

	move->endcontents = 0;
	move->time = n * frametime;
	move->frames = n;
	//
	return qtrue;
} //end of the function AAS_PredictClientMovement
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_TestMovementPrediction( int entnum, vec3_t origin, vec3_t dir ) {
	vec3_t velocity, cmdmove;
	aas_clientmove_t move;

	VectorClear( velocity );
	if ( !AAS_Swimming( origin ) ) {
		dir[2] = 0;
	}
	VectorNormalize( dir );
	VectorScale( dir, 400, cmdmove );
	cmdmove[2] = 224;
	AAS_ClearShownDebugLines();
	AAS_PredictClientMovement( &move, entnum, origin, PRESENCE_NORMAL, qtrue,
							   velocity, cmdmove, 13, 13, 0.1, SE_HITGROUND, 0, qtrue );    //SE_LEAVEGROUND);
	if ( move.stopevent & SE_LEAVEGROUND ) {
		botimport.Print( PRT_MESSAGE, "leave ground\n" );
	} //end if
} //end of the function TestMovementPrediction
//===========================================================================
// calculates the horizontal velocity needed to perform a jump from start
// to end
//
// Parameter:				zvel		: z velocity for jump
//								start		: start position of jump
//								end		: end position of jump
//								*speed	: returned speed for jump
// Returns:					qfalse if too high or too far from start to end
// Changes Globals:		-
//===========================================================================
int AAS_HorizontalVelocityForJump( float zvel, vec3_t start, vec3_t end, float *velocity ) {
	float sv_gravity, sv_maxvelocity;
	float maxjump, height2fall, t, top;
	vec3_t dir;

	sv_gravity = aassettings.sv_gravity;
	sv_maxvelocity = aassettings.sv_maxvelocity;

	//maximum height a player can jump with the given initial z velocity
	maxjump = 0.5 * sv_gravity * ( zvel / sv_gravity ) * ( zvel / sv_gravity );
	//top of the parabolic jump
	top = start[2] + maxjump;
	//height the bot will fall from the top
	height2fall = top - end[2];
	//if the goal is to high to jump to
	if ( height2fall < 0 ) {
		*velocity = sv_maxvelocity;
		return 0;
	} //end if
	  //time a player takes to fall the height
	t = c::sqrt( height2fall / ( 0.5 * sv_gravity ) );
	//direction from start to end
	VectorSubtract( end, start, dir );
	//calculate horizontal speed
	*velocity = c::sqrt( dir[0] * dir[0] + dir[1] * dir[1] ) / ( t + zvel / sv_gravity );
	//the horizontal speed must be lower than the max speed
	if ( *velocity > sv_maxvelocity ) {
		*velocity = sv_maxvelocity;
		return 0;
	} //end if
	return 1;
} //end of the function AAS_HorizontalVelocityForJump
Esempio n. 10
0
//===========================================================================
// returns qtrue if the bot is against a ladder
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int AAS_AgainstLadder( vec3_t origin, int ms_areanum ) {
	int areanum, i, facenum, side;
	vec3_t org;
	aas_plane_t *plane;
	aas_face_t *face;
	aas_area_t *area;

	VectorCopy( origin, org );
	areanum = AAS_PointAreaNum( org );
	if ( !areanum ) {
		org[0] += 1;
		areanum = AAS_PointAreaNum( org );
		if ( !areanum ) {
			org[1] += 1;
			areanum = AAS_PointAreaNum( org );
			if ( !areanum ) {
				org[0] -= 2;
				areanum = AAS_PointAreaNum( org );
				if ( !areanum ) {
					org[1] -= 2;
					areanum = AAS_PointAreaNum( org );
				} //end if
			} //end if
		} //end if
	} //end if
	  //if in solid... wrrr shouldn't happen
	  //if (!areanum) return qfalse;
	  // RF, it does if they're in a monsterclip brush
	if ( !areanum ) {
		areanum = ms_areanum;
	}
	//if not in a ladder area
	if ( !( ( *aasworld ).areasettings[areanum].areaflags & AREA_LADDER ) ) {
		return qfalse;
	}
	//if a crouch only area
	if ( !( ( *aasworld ).areasettings[areanum].presencetype & PRESENCE_NORMAL ) ) {
		return qfalse;
	}
	//
	area = &( *aasworld ).areas[areanum];
	for ( i = 0; i < area->numfaces; i++ )
	{
		facenum = ( *aasworld ).faceindex[area->firstface + i];
		side = facenum < 0;
		face = &( *aasworld ).faces[c::abs( facenum )];
		//if the face isn't a ladder face
		if ( !( face->faceflags & FACE_LADDER ) ) {
			continue;
		}
		//get the plane the face is in
		plane = &( *aasworld ).planes[face->planenum ^ side];
		//if the origin is pretty close to the plane

#if !defined RTCW_ET
		if ( c::abs( DotProduct( plane->normal, origin ) - plane->dist ) < 3 ) {
			if ( AAS_PointInsideFace( c::abs( facenum ), origin, 0.1 ) ) {
#else
		if ( c::abs( DotProduct( plane->normal, origin ) - plane->dist ) < 7 ) {
			// RF, if hanging on to the edge of a ladder, we have to account for bounding box touching
			//if (AAS_PointInsideFace(c::abs(facenum), origin, 0.1)) return qtrue;
			if ( AAS_PointInsideFace( c::abs( facenum ), origin, 2.0 ) ) {
#endif // RTCW_XX

				return qtrue;
			}
		} //end if
	} //end for
	return qfalse;
} //end of the function AAS_AgainstLadder
//===========================================================================
// returns qtrue if the bot is on the ground
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int AAS_OnGround( vec3_t origin, int presencetype, int passent ) {

#if !defined RTCW_ET
	aas_trace_t trace;
#else
	//aas_trace_t trace;
	bsp_trace_t trace;
#endif // RTCW_XX

	vec3_t end, up = {0, 0, 1};

#if !defined RTCW_ET
	aas_plane_t *plane;
#else
	//aas_plane_t *plane;
	vec3_t mins, maxs;
#endif // RTCW_XX


	VectorCopy( origin, end );
	end[2] -= 10;

#if !defined RTCW_ET
	trace = AAS_TraceClientBBox( origin, end, presencetype, passent );
#else
	//trace = AAS_TraceClientBBox(origin, end, presencetype, passent);
	AAS_PresenceTypeBoundingBox( presencetype, mins, maxs );
	trace = AAS_Trace( origin, mins, maxs, end, passent, CONTENTS_SOLID | CONTENTS_PLAYERCLIP );
#endif // RTCW_XX


	//if in solid
	if ( trace.startsolid ) {

#if !defined RTCW_MP
		return qtrue;                  //qfalse;
#else
		return qfalse;
#endif // RTCW_XX

	}
	//if nothing hit at all
	if ( trace.fraction >= 1.0 ) {
		return qfalse;
	}
	//if too far from the hit plane
	if ( origin[2] - trace.endpos[2] > 10 ) {
		return qfalse;
	}
	//check if the plane isn't too steep

#if !defined RTCW_ET
	plane = AAS_PlaneFromNum( trace.planenum );
	if ( DotProduct( plane->normal, up ) < aassettings.sv_maxsteepness ) {
#else
	//plane = AAS_PlaneFromNum(trace.planenum);
	if ( DotProduct( trace.plane.normal, up ) < aassettings.sv_maxsteepness ) {
#endif // RTCW_XX

		return qfalse;
	}
	//the bot is on the ground
	return qtrue;
} //end of the function AAS_OnGround
//===========================================================================
// returns qtrue if a bot at the given position is swimming
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int AAS_Swimming( vec3_t origin ) {
	vec3_t testorg;

	VectorCopy( origin, testorg );
	testorg[2] -= 2;
	if ( AAS_PointContents( testorg ) & ( CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER ) ) {
		return qtrue;
	}
	return qfalse;
} //end of the function AAS_Swimming
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
vec3_t VEC_UP           = {0, -1,  0};
vec3_t MOVEDIR_UP       = {0,  0,  1};
vec3_t VEC_DOWN     = {0, -2,  0};
vec3_t MOVEDIR_DOWN = {0,  0, -1};

void AAS_SetMovedir( vec3_t angles, vec3_t movedir ) {
	if ( VectorCompare( angles, VEC_UP ) ) {
		VectorCopy( MOVEDIR_UP, movedir );
	} //end if
	else if ( VectorCompare( angles, VEC_DOWN ) ) {
		VectorCopy( MOVEDIR_DOWN, movedir );
	} //end else if
	else
	{
		AngleVectors( angles, movedir, NULL, NULL );
	} //end else
} //end of the function AAS_SetMovedir
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_JumpReachRunStart( aas_reachability_t *reach, vec3_t runstart ) {
	vec3_t hordir, start, cmdmove;
	aas_clientmove_t move;

	//
	hordir[0] = reach->start[0] - reach->end[0];
	hordir[1] = reach->start[1] - reach->end[1];
	hordir[2] = 0;
	VectorNormalize( hordir );
	//start point
	VectorCopy( reach->start, start );
	start[2] += 1;
	//get command movement
	VectorScale( hordir, 400, cmdmove );
	//
	AAS_PredictClientMovement( &move, -1, start, PRESENCE_NORMAL, qtrue,
							   vec3_origin, cmdmove, 1, 2, 0.1,
							   SE_ENTERWATER | SE_ENTERSLIME | SE_ENTERLAVA |
							   SE_HITGROUNDDAMAGE | SE_GAP, 0, qfalse );
	VectorCopy( move.endpos, runstart );
	//don't enter slime or lava and don't fall from too high
	if ( move.stopevent & ( SE_ENTERLAVA | SE_HITGROUNDDAMAGE ) ) { //----(SA)	modified since slime is no longer deadly
//	if (move.stopevent & (SE_ENTERSLIME|SE_ENTERLAVA|SE_HITGROUNDDAMAGE))
		VectorCopy( start, runstart );
	} //end if
} //end of the function AAS_JumpReachRunStart