示例#1
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int BotItemGoalInVisButNotVisible( int viewer, vec3_t eye, vec3_t viewangles, bot_goal_t *goal ) {
	aas_entityinfo_t entinfo;
	bsp_trace_t trace;
	vec3_t middle;

	if ( !( goal->flags & GFL_ITEM ) ) {
		return qfalse;
	}
	//
	VectorAdd( goal->mins, goal->mins, middle );
	VectorScale( middle, 0.5, middle );
	VectorAdd( goal->origin, middle, middle );
	//
	trace = AAS_Trace( eye, NULL, NULL, middle, viewer, CONTENTS_SOLID );
	//if the goal middle point is visible
	if ( trace.fraction >= 1 ) {
		//the goal entity number doesn't have to be valid
		//just assume it's valid
		if ( goal->entitynum <= 0 ) {
			return qfalse;
		}
		//
		//if the entity data isn't valid
		AAS_EntityInfo( goal->entitynum, &entinfo );
		//NOTE: for some wacko reason entities are sometimes
		// not updated
		//if (!entinfo.valid) return qtrue;
		if ( entinfo.ltime < AAS_Time() - 0.5 ) {
			return qtrue;
		}
	} //end if
	return qfalse;
} //end of the function BotItemGoalInVisButNotVisible
示例#2
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int AAS_DropToFloor( vec3_t origin, vec3_t mins, vec3_t maxs ) {
	vec3_t end;
	bsp_trace_t trace;

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

#if !defined RTCW_ET
	trace = AAS_Trace( origin, mins, maxs, end, 0, CONTENTS_SOLID );
#else
	trace = AAS_Trace( origin, mins, maxs, end, 0, ( CONTENTS_SOLID | CONTENTS_PLAYERCLIP ) & ~CONTENTS_BODY );
#endif // RTCW_XX

	if ( trace.startsolid ) {
		return qfalse;
	}
	VectorCopy( trace.endpos, origin );
	return qtrue;
} //end of the function AAS_DropToFloor
示例#3
0
文件: be_aas_move.c 项目: Razish/QtZ
int AAS_DropToFloor(vector3 *origin, vector3 *mins, vector3 *maxs) {
	vector3 end;
	bsp_trace_t trace;

	VectorCopy(origin, &end);
	end.z -= 100;
	trace = AAS_Trace(origin, mins, maxs, &end, 0, CONTENTS_SOLID);
	if (trace.startsolid) return qfalse;
	VectorCopy(&trace.endpos, origin);
	return qtrue;
}
示例#4
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
int AAS_DropToFloor(vec3_t origin, vec3_t mins, vec3_t maxs)
{
	vec3_t end;
	bsp_trace_t trace;

	VectorCopy(origin, end);
	end[2] -= 100;
	trace = AAS_Trace(origin, mins, maxs, end, 0, CONTENTS_SOLID);
	if (trace.startsolid) return qfalse;
	VectorCopy(trace.endpos, origin);
	return qtrue;
} //end of the function AAS_DropToFloor
示例#5
0
//===========================================================================
// returns the Z velocity when rocket jumping at the origin
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
float AAS_WeaponJumpZVelocity(vec3_t origin, float radiusdamage)
{
	vec3_t      kvel, v, start, end, forward, right, viewangles, dir;
	float       mass, knockback, points;
	vec3_t      rocketoffset = { 8, 8, -8 };
	vec3_t      botmins      = { -16, -16, -24 };
	vec3_t      botmaxs      = { 16, 16, 32 };
	bsp_trace_t bsptrace;

	//look down (90 degrees)
	viewangles[PITCH] = 90;
	viewangles[YAW]   = 0;
	viewangles[ROLL]  = 0;
	//get the start point shooting from
	VectorCopy(origin, start);
	start[2] += 8; //view offset Z
	AngleVectors(viewangles, forward, right, NULL);
	start[0] += forward[0] * rocketoffset[0] + right[0] * rocketoffset[1];
	start[1] += forward[1] * rocketoffset[0] + right[1] * rocketoffset[1];
	start[2] += forward[2] * rocketoffset[0] + right[2] * rocketoffset[1] + rocketoffset[2];
	//end point of the trace
	VectorMA(start, 500, forward, end);
	//trace a line to get the impact point
	bsptrace = AAS_Trace(start, NULL, NULL, end, 1, CONTENTS_SOLID);
	//calculate the damage the bot will get from the rocket impact
	VectorAdd(botmins, botmaxs, v);
	VectorMA(origin, 0.5, v, v);
	VectorSubtract(bsptrace.endpos, v, v);
	//
	points = radiusdamage - 0.5 * VectorLength(v);
	if (points < 0)
	{
		points = 0;
	}
	//the owner of the rocket gets half the damage
	points *= 0.5;
	//mass of the bot (p_client.c: PutClientInServer)
	mass = 200;
	//knockback is the same as the damage points
	knockback = points;
	//direction of the damage (from trace.endpos to bot origin)
	VectorSubtract(origin, bsptrace.endpos, dir);
	VectorNormalize(dir);
	//damage velocity
	VectorScale(dir, 1600.0 * (float)knockback / mass, kvel);     //the rocket jump hack...
	//rocket impact velocity + jump velocity
	return kvel[2] + aassettings.sv_jumpvel;
} //end of the function AAS_WeaponJumpZVelocity
示例#6
0
文件: be_aas_move.c 项目: Razish/QtZ
// returns the Z velocity when rocket jumping at the origin
float AAS_WeaponJumpZVelocity(vector3 *origin, float radiusdamage) {
	vector3 kvel, v, start, end, forward, right, viewangles, dir;
	float	mass, knockback, points;
	vector3 rocketoffset = {8, 8, -8};
	vector3 botmins = {-16, -16, -24};
	vector3 botmaxs = {16, 16, 32};
	bsp_trace_t bsptrace;

	//look down (90 degrees)
	viewangles.pitch = 90;
	viewangles.yaw = 0;
	viewangles.roll = 0;
	//get the start point shooting from
	VectorCopy(origin, &start);
	start.z += 8; //view offset Z
	AngleVectors(&viewangles, &forward, &right, NULL);
	start.x += forward.x * rocketoffset.x + right.x * rocketoffset.y;
	start.y += forward.y * rocketoffset.x + right.y * rocketoffset.y;
	start.z += forward.z * rocketoffset.x + right.z * rocketoffset.y + rocketoffset.z;
	//end point of the trace
	VectorMA(&start, 500, &forward, &end);
	//trace a line to get the impact point
	bsptrace = AAS_Trace(&start, NULL, NULL, &end, 1, CONTENTS_SOLID);
	//calculate the damage the bot will get from the rocket impact
	VectorAdd(&botmins, &botmaxs, &v);
	VectorMA(origin, 0.5f, &v, &v);
	VectorSubtract(&bsptrace.endpos, &v, &v);
	//
	points = radiusdamage - 0.5f * VectorLength(&v);
	if (points < 0) points = 0;
	//the owner of the rocket gets half the damage
	points *= 0.5f;
	//mass of the bot (p_client.c: PutClientInServer)
	mass = 200;
	//knockback is the same as the damage points
	knockback = points;
	//direction of the damage (from trace.endpos to bot origin)
	VectorSubtract(origin, &bsptrace.endpos, &dir);
	VectorNormalize(&dir);
	//damage velocity
	VectorScale(&dir, 1600.0f * (float)knockback / mass, &kvel);	//the rocket jump hack...
	//rocket impact velocity + jump velocity
	return kvel.z + aassettings.phys_jumpvel;
}
示例#7
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
示例#8
0
int BotExportTest(int parm0, char *parm1, vec3_t parm2, vec3_t parm3)
{

//	return AAS_PointLight(parm2, NULL, NULL, NULL);

#ifdef DEBUG
	static int area = -1;
	static int line[2];
	int newarea, i, highlightarea, flood;
//	int reachnum;
	vec3_t eye, forward, right, end, origin;
//	vec3_t bottomcenter;
//	aas_trace_t trace;
//	aas_face_t *face;
//	aas_entity_t *ent;
//	bsp_trace_t bsptrace;
//	aas_reachability_t reach;
//	bot_goal_t goal;

	// clock_t start_time, end_time;
	vec3_t mins = {-16, -16, -24};
	vec3_t maxs = {16, 16, 32};

//	int areas[10], numareas;


	//return 0;

	if (!aasworld.loaded) return 0;

	/*
	if (parm0 & 1)
	{
		AAS_ClearShownPolygons();
		AAS_FloodAreas(parm2);
	} //end if
	return 0;
	*/
	for (i = 0; i < 2; i++) if (!line[i]) line[i] = botimport.DebugLineCreate();

//	AAS_ClearShownDebugLines();

	//if (AAS_AgainstLadder(parm2)) botimport.Print(PRT_MESSAGE, "against ladder\n");
	//BotOnGround(parm2, PRESENCE_NORMAL, 1, &newarea, &newarea);
	//botimport.Print(PRT_MESSAGE, "%f %f %f\n", parm2[0], parm2[1], parm2[2]);
	//*
	highlightarea = LibVarGetValue("bot_highlightarea");
	if (highlightarea > 0)
	{
		newarea = highlightarea;
	} //end if
	else
	{
		VectorCopy(parm2, origin);
		origin[2] += 0.5;
		//newarea = AAS_PointAreaNum(origin);
		newarea = BotFuzzyPointReachabilityArea(origin);
	} //end else

	botimport.Print(PRT_MESSAGE, "\rtravel time to goal (%d) = %d  ", botlibglobals.goalareanum,
		AAS_AreaTravelTimeToGoalArea(newarea, origin, botlibglobals.goalareanum, TFL_DEFAULT));
	//newarea = BotReachabilityArea(origin, qtrue);
	if (newarea != area)
	{
		botimport.Print(PRT_MESSAGE, "origin = %f, %f, %f\n", origin[0], origin[1], origin[2]);
		area = newarea;
		botimport.Print(PRT_MESSAGE, "new area %d, cluster %d, presence type %d\n",
					area, AAS_AreaCluster(area), AAS_PointPresenceType(origin));
		botimport.Print(PRT_MESSAGE, "area contents: ");
		if (aasworld.areasettings[area].contents & AREACONTENTS_WATER)
		{
			botimport.Print(PRT_MESSAGE, "water &");
		} //end if
		if (aasworld.areasettings[area].contents & AREACONTENTS_LAVA)
		{
			botimport.Print(PRT_MESSAGE, "lava &");
		} //end if
		if (aasworld.areasettings[area].contents & AREACONTENTS_SLIME)
		{
			botimport.Print(PRT_MESSAGE, "slime &");
		} //end if
		if (aasworld.areasettings[area].contents & AREACONTENTS_JUMPPAD)
		{
			botimport.Print(PRT_MESSAGE, "jump pad &");
		} //end if
		if (aasworld.areasettings[area].contents & AREACONTENTS_CLUSTERPORTAL)
		{
			botimport.Print(PRT_MESSAGE, "cluster portal &");
		} //end if
		if (aasworld.areasettings[area].contents & AREACONTENTS_VIEWPORTAL)
		{
			botimport.Print(PRT_MESSAGE, "view portal &");
		} //end if
		if (aasworld.areasettings[area].contents & AREACONTENTS_DONOTENTER)
		{
			botimport.Print(PRT_MESSAGE, "do not enter &");
		} //end if
		if (aasworld.areasettings[area].contents & AREACONTENTS_MOVER)
		{
			botimport.Print(PRT_MESSAGE, "mover &");
		} //end if
		if (!aasworld.areasettings[area].contents)
		{
			botimport.Print(PRT_MESSAGE, "empty");
		} //end if
		botimport.Print(PRT_MESSAGE, "\n");
		botimport.Print(PRT_MESSAGE, "travel time to goal (%d) = %d\n", botlibglobals.goalareanum,
					AAS_AreaTravelTimeToGoalArea(newarea, origin, botlibglobals.goalareanum, TFL_DEFAULT|TFL_ROCKETJUMP));
		/*
		VectorCopy(origin, end);
		end[2] += 5;
		numareas = AAS_TraceAreas(origin, end, areas, NULL, 10);
		AAS_TraceClientBBox(origin, end, PRESENCE_CROUCH, -1);
		botimport.Print(PRT_MESSAGE, "num areas = %d, area = %d\n", numareas, areas[0]);
		*/
		/*
		botlibglobals.goalareanum = newarea;
		VectorCopy(parm2, botlibglobals.goalorigin);
		botimport.Print(PRT_MESSAGE, "new goal %2.1f %2.1f %2.1f area %d\n",
								origin[0], origin[1], origin[2], newarea);
		*/
	} //end if
	//*
	flood = LibVarGetValue("bot_flood");
	if (parm0 & 1)
	{
		if (flood)
		{
			AAS_ClearShownPolygons();
			AAS_ClearShownDebugLines();
			AAS_FloodAreas(parm2);
		}
		else
		{
			botlibglobals.goalareanum = newarea;
			VectorCopy(parm2, botlibglobals.goalorigin);
			botimport.Print(PRT_MESSAGE, "new goal %2.1f %2.1f %2.1f area %d\n",
									origin[0], origin[1], origin[2], newarea);
		}
	} //end if*/
	if (flood)
		return 0;
//	if (parm0 & BUTTON_USE)
//	{
//		botlibglobals.runai = !botlibglobals.runai;
//		if (botlibglobals.runai) botimport.Print(PRT_MESSAGE, "started AI\n");
//		else botimport.Print(PRT_MESSAGE, "stopped AI\n");
		//* /
		/*
		goal.areanum = botlibglobals.goalareanum;
		reachnum = BotGetReachabilityToGoal(parm2, newarea, 1,
										ms.avoidreach, ms.avoidreachtimes,
										&goal, TFL_DEFAULT);
		if (!reachnum)
		{
			botimport.Print(PRT_MESSAGE, "goal not reachable\n");
		} //end if
		else
		{
			AAS_ReachabilityFromNum(reachnum, &reach);
			AAS_ClearShownDebugLines();
			AAS_ShowArea(area, qtrue);
			AAS_ShowArea(reach.areanum, qtrue);
			AAS_DrawCross(reach.start, 6, LINECOLOR_BLUE);
			AAS_DrawCross(reach.end, 6, LINECOLOR_RED);
			//
			if ((reach.traveltype & TRAVELTYPE_MASK) == TRAVEL_ELEVATOR)
			{
				ElevatorBottomCenter(&reach, bottomcenter);
				AAS_DrawCross(bottomcenter, 10, LINECOLOR_GREEN);
			} //end if
		} //end else*/
//		botimport.Print(PRT_MESSAGE, "travel time to goal = %d\n",
//					AAS_AreaTravelTimeToGoalArea(area, origin, botlibglobals.goalareanum, TFL_DEFAULT));
//		botimport.Print(PRT_MESSAGE, "test rj from 703 to 716\n");
//		AAS_Reachability_WeaponJump(703, 716);
//	} //end if*/

/*	face = AAS_AreaGroundFace(newarea, parm2);
	if (face)
	{
		AAS_ShowFace(face - aasworld.faces);
	} //end if*/
	/*
	AAS_ClearShownDebugLines();
	AAS_ShowArea(newarea, parm0 & BUTTON_USE);
	AAS_ShowReachableAreas(area);
	*/
	AAS_ClearShownPolygons();
	AAS_ClearShownDebugLines();
	AAS_ShowAreaPolygons(newarea, 1, parm0 & 4);
	if (parm0 & 2) AAS_ShowReachableAreas(area);
	else
	{
		static int lastgoalareanum, lastareanum;
		static int avoidreach[MAX_AVOIDREACH];
		static float avoidreachtimes[MAX_AVOIDREACH];
		static int avoidreachtries[MAX_AVOIDREACH];
		int reachnum, resultFlags;
		bot_goal_t goal;
		aas_reachability_t reach;

		/*
		goal.areanum = botlibglobals.goalareanum;
		VectorCopy(botlibglobals.goalorigin, goal.origin);
		reachnum = BotGetReachabilityToGoal(origin, newarea,
									  lastgoalareanum, lastareanum,
									  avoidreach, avoidreachtimes, avoidreachtries,
									  &goal, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP,
									  NULL, 0, &resultFlags);
		AAS_ReachabilityFromNum(reachnum, &reach);
		AAS_ShowReachability(&reach);
		*/
		int curarea;
		vec3_t curorigin;

		goal.areanum = botlibglobals.goalareanum;
		VectorCopy(botlibglobals.goalorigin, goal.origin);
		VectorCopy(origin, curorigin);
		curarea = newarea;
		for ( i = 0; i < 100; i++ ) {
			if ( curarea == goal.areanum ) {
				break;
			}
			reachnum = BotGetReachabilityToGoal(curorigin, curarea,
										  lastgoalareanum, lastareanum,
										  avoidreach, avoidreachtimes, avoidreachtries,
										  &goal, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP, TFL_DEFAULT|TFL_FUNCBOB|TFL_ROCKETJUMP,
										  NULL, 0, &resultFlags);
			AAS_ReachabilityFromNum(reachnum, &reach);
			AAS_ShowReachability(&reach);
			VectorCopy(reach.end, origin);
			lastareanum = curarea;
			curarea = reach.areanum;
		}
	} //end else
	VectorClear(forward);
	//BotGapDistance(origin, forward, 0);
	/*
	if (parm0 & BUTTON_USE)
	{
		botimport.Print(PRT_MESSAGE, "test rj from 703 to 716\n");
		AAS_Reachability_WeaponJump(703, 716);
	} //end if*/

	AngleVectors(parm3, forward, right, NULL);
	//get the eye 16 units to the right of the origin
	VectorMA(parm2, 8, right, eye);
	//get the eye 24 units up
	eye[2] += 24;
	//get the end point for the line to be traced
	VectorMA(eye, 800, forward, end);

//	AAS_TestMovementPrediction(1, parm2, forward);
/*
    //trace the line to find the hit point
	trace = AAS_TraceClientBBox(eye, end, PRESENCE_NORMAL, 1);
	if (!line[0]) line[0] = botimport.DebugLineCreate();
	botimport.DebugLineShow(line[0], eye, trace.endpos, LINECOLOR_BLUE);
	//
	AAS_ClearShownDebugLines();
	if (trace.ent)
	{
		ent = &aasworld.entities[trace.ent];
		AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
	} //end if
*/

/*
	start_time = clock();
	for (i = 0; i < 2000; i++)
	{
		AAS_Trace2(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
//		AAS_TraceClientBBox(eye, end, PRESENCE_NORMAL, 1);
	} //end for
	end_time = clock();
	botimport.Print(PRT_MESSAGE, "me %lu clocks, %lu CLOCKS_PER_SEC\n", end_time - start_time, CLOCKS_PER_SEC);
	start_time = clock();
	for (i = 0; i < 2000; i++)
	{
		AAS_Trace(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
	} //end for
	end_time = clock();
	botimport.Print(PRT_MESSAGE, "id %lu clocks, %lu CLOCKS_PER_SEC\n", end_time - start_time, CLOCKS_PER_SEC);
*/

    // TTimo: nested comments are BAD for gcc -Werror, use #if 0 instead..
#if 0
	AAS_ClearShownDebugLines();
	//bsptrace = AAS_Trace(eye, NULL, NULL, end, 1, MASK_PLAYERSOLID);
	bsptrace = AAS_Trace(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
	if (!line[0]) line[0] = botimport.DebugLineCreate();
	botimport.DebugLineShow(line[0], eye, bsptrace.endpos, LINECOLOR_YELLOW);
	if (bsptrace.fraction < 1.0)
	{
		face = AAS_TraceEndFace(&trace);
		if (face)
		{
			AAS_ShowFace(face - aasworld.faces);
		} //end if
		
		AAS_DrawPlaneCross(bsptrace.endpos,
									bsptrace.plane.normal,
									bsptrace.plane.dist + bsptrace.exp_dist,
									bsptrace.plane.type, LINECOLOR_GREEN);
		if (trace.ent)
		{
			ent = &aasworld.entities[trace.ent];
			AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
		} //end if
	} //end if
	//bsptrace = AAS_Trace2(eye, NULL, NULL, end, 1, MASK_PLAYERSOLID);
	bsptrace = AAS_Trace2(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
	botimport.DebugLineShow(line[1], eye, bsptrace.endpos, LINECOLOR_BLUE);
	if (bsptrace.fraction < 1.0)
	{
		AAS_DrawPlaneCross(bsptrace.endpos,
									bsptrace.plane.normal,
									bsptrace.plane.dist,// + bsptrace.exp_dist,
									bsptrace.plane.type, LINECOLOR_RED);
		if (bsptrace.ent)
		{
			ent = &aasworld.entities[bsptrace.ent];
			AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
		} //end if
	} //end if
#endif
#endif
	return 0;
} //end of the function BotExportTest
示例#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
示例#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
示例#11
0
void BotInitLevelItems() {
	//initialize the map locations and camp spots
	BotInitInfoEntities();

	//initialize the level item heap
	InitLevelItemHeap();
	levelitems = NULL;
	numlevelitems = 0;

	itemconfig_t* ic = itemconfig;
	if ( !ic ) {
		return;
	}

	//if there's no AAS file loaded
	if ( !AAS_Loaded() ) {
		return;
	}

	//update the modelindexes of the item info
	for ( int i = 0; i < ic->numiteminfo; i++ ) {
		if ( !ic->iteminfo[ i ].modelindex ) {
			Log_Write( "item %s has modelindex 0", ic->iteminfo[ i ].classname );
		}
	}

	for ( int ent = AAS_NextBSPEntity( 0 ); ent; ent = AAS_NextBSPEntity( ent ) ) {
		char classname[ MAX_EPAIRKEY ];
		if ( !AAS_ValueForBSPEpairKey( ent, "classname", classname, MAX_EPAIRKEY ) ) {
			continue;
		}

		int spawnflags = 0;
		AAS_IntForBSPEpairKey( ent, "spawnflags", &spawnflags );

		int i;
		for ( i = 0; i < ic->numiteminfo; i++ ) {
			if ( !String::Cmp( classname, ic->iteminfo[ i ].classname ) ) {
				break;
			}
		}
		if ( i >= ic->numiteminfo ) {
			Log_Write( "entity %s unknown item\r\n", classname );
			continue;
		}
		//get the origin of the item
		vec3_t origin;
		if ( !AAS_VectorForBSPEpairKey( ent, "origin", origin ) ) {
			BotImport_Print( PRT_ERROR, "item %s without origin\n", classname );
			continue;
		}

		int goalareanum = 0;
		//if it is a floating item
		if ( spawnflags & 1 ) {
			if ( !( GGameType & GAME_Quake3 ) ) {
				continue;
			}
			//if the item is not floating in water
			if ( !( AAS_PointContents( origin ) & BSP46CONTENTS_WATER ) ) {
				vec3_t end;
				VectorCopy( origin, end );
				end[ 2 ] -= 32;
				bsp_trace_t trace = AAS_Trace( origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs, end, -1, BSP46CONTENTS_SOLID | BSP46CONTENTS_PLAYERCLIP );
				//if the item not near the ground
				if ( trace.fraction >= 1 ) {
					//if the item is not reachable from a jumppad
					goalareanum = AAS_BestReachableFromJumpPadArea( origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs );
					Log_Write( "item %s reachable from jumppad area %d\r\n", ic->iteminfo[ i ].classname, goalareanum );
					if ( !goalareanum ) {
						continue;
					}
				}
			}
		}

		levelitem_t* li = AllocLevelItem();
		if ( !li ) {
			return;
		}

		li->number = ++numlevelitems;
		li->timeout = 0;
		li->entitynum = 0;

		li->flags = 0;
		int value;
		AAS_IntForBSPEpairKey( ent, "notfree", &value );
		if ( value ) {
			li->flags |= IFL_NOTFREE;
		}
		AAS_IntForBSPEpairKey( ent, "notteam", &value );
		if ( value ) {
			li->flags |= IFL_NOTTEAM;
		}
		AAS_IntForBSPEpairKey( ent, "notsingle", &value );
		if ( value ) {
			li->flags |= IFL_NOTSINGLE;
		}
		if ( GGameType & GAME_Quake3 ) {
			AAS_IntForBSPEpairKey( ent, "notbot", &value );
			if ( value ) {
				li->flags |= IFL_NOTBOT;
			}
			if ( !String::Cmp( classname, "item_botroam" ) ) {
				li->flags |= IFL_ROAM;
				AAS_FloatForBSPEpairKey( ent, "weight", &li->weight );
			}
		}
		//if not a stationary item
		if ( !( spawnflags & 1 ) ) {
			if ( !AAS_DropToFloor( origin, ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs ) ) {
				BotImport_Print( PRT_MESSAGE, "%s in solid at (%1.1f %1.1f %1.1f)\n",
					classname, origin[ 0 ], origin[ 1 ], origin[ 2 ] );
			}
		}
		//item info of the level item
		li->iteminfo = i;
		//origin of the item
		VectorCopy( origin, li->origin );

		if ( goalareanum ) {
			li->goalareanum = goalareanum;
			VectorCopy( origin, li->goalorigin );
		} else {
			//get the item goal area and goal origin
			li->goalareanum = AAS_BestReachableArea( origin,
				ic->iteminfo[ i ].mins, ic->iteminfo[ i ].maxs,
				li->goalorigin );
			if ( !li->goalareanum ) {
				BotImport_Print( PRT_MESSAGE, "%s not reachable for bots at (%1.1f %1.1f %1.1f)\n",
					classname, origin[ 0 ], origin[ 1 ], origin[ 2 ] );
			}
		}

		AddLevelItemToList( li );
	}
	BotImport_Print( PRT_MESSAGE, "found %d level items\n", numlevelitems );
}