Example #1
0
/*
=======================================================================================================================================
AAS_ShowReachability
=======================================================================================================================================
*/
void AAS_ShowReachability(aas_reachability_t *reach) {
	vec3_t dir, cmdmove, velocity;
	float speed, zvel;
	aas_clientmove_t move;

	AAS_ShowAreaPolygons(reach->areanum, 5, qtrue);
	//AAS_ShowArea(reach->areanum, qtrue);
	AAS_DrawArrow(reach->start, reach->end, LINECOLOR_BLUE, LINECOLOR_YELLOW);

	if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP || (reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_WALKOFFLEDGE) {
		AAS_HorizontalVelocityForJump(aassettings.phys_jumpvel, reach->start, reach->end, &speed);
		VectorSubtract(reach->end, reach->start, dir);

		dir[2] = 0;

		VectorNormalize(dir);
		// set the velocity
		VectorScale(dir, speed, velocity);
		// set the command movement
		VectorClear(cmdmove);

		cmdmove[2] = aassettings.phys_jumpvel;

		AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue, velocity, cmdmove, 3, 30, 0.1f, SE_HITGROUND|SE_ENTERWATER|SE_ENTERSLIME|SE_ENTERLAVA|SE_HITGROUNDDAMAGE, 0, qtrue);

		if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMP) {
			AAS_JumpReachRunStart(reach, dir);
			AAS_DrawCross(dir, 4, LINECOLOR_BLUE);
		}
	} else if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_ROCKETJUMP) {
		zvel = AAS_RocketJumpZVelocity(reach->start);

		AAS_HorizontalVelocityForJump(zvel, reach->start, reach->end, &speed);
		VectorSubtract(reach->end, reach->start, dir);

		dir[2] = 0;

		VectorNormalize(dir);
		// get command movement
		VectorScale(dir, speed, cmdmove);
		VectorSet(velocity, 0, 0, zvel);

		AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue, velocity, cmdmove, 30, 30, 0.1f, SE_ENTERWATER|SE_ENTERSLIME|SE_ENTERLAVA|SE_HITGROUNDDAMAGE|SE_TOUCHJUMPPAD|SE_HITGROUNDAREA, reach->areanum, qtrue);
	} else if ((reach->traveltype & TRAVELTYPE_MASK) == TRAVEL_JUMPPAD) {
		VectorSet(cmdmove, 0, 0, 0);
		VectorSubtract(reach->end, reach->start, dir);

		dir[2] = 0;

		VectorNormalize(dir);
		// set the velocity
		// NOTE: the edgenum is the horizontal velocity
		VectorScale(dir, reach->edgenum, velocity);
		// NOTE: the facenum is the Z velocity
		velocity[2] = reach->facenum;

		AAS_PredictClientMovement(&move, -1, reach->start, PRESENCE_NORMAL, qtrue, velocity, cmdmove, 30, 30, 0.1f, SE_ENTERWATER|SE_ENTERSLIME|SE_ENTERLAVA|SE_HITGROUNDDAMAGE|SE_TOUCHJUMPPAD|SE_HITGROUNDAREA, reach->areanum, qtrue);
	}
}
Example #2
0
void AAS_JumpReachRunStart(aas_reachability_t *reach, vector3 *runstart) {
	vector3 hordir, start, cmdmove;
	aas_clientmove_t move;

	//
	hordir.x = reach->start.x - reach->end.x;
	hordir.y = reach->start.y - reach->end.y;
	hordir.z = 0;
	VectorNormalize(&hordir);
	//start point
	VectorCopy(&reach->start, &start);
	start.z += 1;
	//get command movement
	VectorScale(&hordir, 400, &cmdmove);
	//
	AAS_PredictClientMovement(&move, -1, &start, PRESENCE_NORMAL, qtrue,
								&vec3_origin, &cmdmove, 1, 2, 0.1f,
								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_ENTERSLIME|SE_ENTERLAVA|SE_HITGROUNDDAMAGE))
	{
		VectorCopy(&start, runstart);
	}
}
Example #3
0
//===========================================================================
//
// 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.1f,
								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_ENTERSLIME|SE_ENTERLAVA|SE_HITGROUNDDAMAGE))
	{
		VectorCopy(start, runstart);
	} //end if
} //end of the function AAS_JumpReachRunStart
Example #4
0
void AAS_TestMovementPrediction(int entnum, vector3 *origin, vector3 *dir) {
	vector3 velocity, cmdmove;
	aas_clientmove_t move;

	VectorClear(&velocity);
	if (!AAS_Swimming(origin)) dir->z = 0;
	VectorNormalize(dir);
	VectorScale(dir, 400, &cmdmove);
	cmdmove.z = 224;
	AAS_ClearShownDebugLines();
	AAS_PredictClientMovement(&move, entnum, origin, PRESENCE_NORMAL, qtrue,
									&velocity, &cmdmove, 13, 13, 0.1f, SE_HITGROUND, 0, qtrue);//SE_LEAVEGROUND);
	if (move.stopevent & SE_LEAVEGROUND)
	{
		botimport.Print(PRT_MESSAGE, "leave ground\n");
	}
}
Example #5
0
//===========================================================================
//
// 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
Example #6
0
int BotExportTest( int parm0, char *parm1, vec3_t parm2, vec3_t parm3 ) {

#if !defined RTCW_ET
//	return AAS_PointLight(parm2, NULL, NULL, NULL);

#ifdef DEBUG
	static int area = -1;
	static int line[2];

#if defined RTCW_SP
	int newarea, i, highlightarea, bot_testhidepos, hideposarea, bot_testroutevispos;
#elif defined RTCW_MP
	int newarea, i, highlightarea, bot_testhidepos, hideposarea;
#endif // RTCW_XX

//	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;
	}
	AAS_SetCurrentWorld( 0 );

	for ( i = 0; i < 2; i++ ) if ( !line[i] ) {
			line[i] = botimport.DebugLineCreate();
		}

//	AAS_ClearShownDebugLines();
	bot_testhidepos = LibVarGetValue( "bot_testhidepos" );
	if ( bot_testhidepos ) {
		VectorCopy( parm2, origin );
		newarea = BotFuzzyPointReachabilityArea( origin );
		if ( parm0 & 1 ) {
			botlibglobals.goalareanum = newarea;
			VectorCopy( origin, botlibglobals.goalorigin );
			botimport.Print( PRT_MESSAGE, "new enemy position %2.1f %2.1f %2.1f area %d\n",
							 origin[0], origin[1], origin[2], newarea );
		} //end if
		AAS_ClearShownPolygons();
		AAS_ClearShownDebugLines();

#if defined RTCW_SP
		hideposarea = AAS_NearestHideArea( -1, origin, AAS_PointAreaNum( origin ), 0,
#elif defined RTCW_MP
		hideposarea = AAS_NearestHideArea( 0, origin, AAS_PointAreaNum( origin ), 0,
#endif // RTCW_XX

										   botlibglobals.goalorigin, botlibglobals.goalareanum, TFL_DEFAULT );

#if defined RTCW_SP
		if ( bot_testhidepos > 1 ) {
			if ( hideposarea ) {
				botimport.Print( PRT_MESSAGE, "hidepos (%i) %2.1f %2.1f %2.1f\n",
								 hideposarea,
								 ( *aasworld ).areawaypoints[hideposarea][0],
								 ( *aasworld ).areawaypoints[hideposarea][1],
								 ( *aasworld ).areawaypoints[hideposarea][2] );
			} else {
				botimport.Print( PRT_MESSAGE, "no hidepos found\n" );
			}
		}
#endif // RTCW_XX

		//area we are currently in
		AAS_ShowAreaPolygons( newarea, 1, qtrue );
		//enemy position
		AAS_ShowAreaPolygons( botlibglobals.goalareanum, 2, qtrue );
		//area we should go hide
		AAS_ShowAreaPolygons( hideposarea, 4, qtrue );
		return 0;
	}

#if defined RTCW_SP
	bot_testroutevispos = LibVarGetValue( "bot_testroutevispos" );
	if ( bot_testroutevispos ) {
		VectorCopy( parm2, origin );
		newarea = BotFuzzyPointReachabilityArea( origin );
		if ( parm0 & 1 ) {
			botlibglobals.goalareanum = newarea;
			VectorCopy( origin, botlibglobals.goalorigin );
			botimport.Print( PRT_MESSAGE, "new enemy position %2.1f %2.1f %2.1f area %d\n",
							 origin[0], origin[1], origin[2], newarea );
		} //end if
		AAS_ClearShownPolygons();
		AAS_ClearShownDebugLines();
		AAS_GetRouteFirstVisPos( botlibglobals.goalorigin, origin, TFL_DEFAULT, eye );
		//area we are currently in
		AAS_ShowAreaPolygons( newarea, 1, qtrue );
		//enemy position
		AAS_ShowAreaPolygons( botlibglobals.goalareanum, 2, qtrue );
		//area that is visible in path from enemy pos
		hideposarea = BotFuzzyPointReachabilityArea( eye );
		AAS_ShowAreaPolygons( hideposarea, 4, qtrue );
		return 0;
	}
#endif // RTCW_XX

	//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 ) );
		if ( ( *aasworld ).areasettings[area].areaflags & AREA_LIQUID ) {
			botimport.Print( PRT_MESSAGE, "liquid area\n" );
		} //end if
		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 ");
			botimport.Print( PRT_MESSAGE, "slag " );
		} //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_DONOTENTER ) {
			botimport.Print( PRT_MESSAGE, "do not enter " );
		} //end if
		if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_DONOTENTER_LARGE ) {
			botimport.Print( PRT_MESSAGE, "do not enter large " );
		} //end if
		if ( !( *aasworld ).areasettings[area].contents ) {
			botimport.Print( PRT_MESSAGE, "empty " );
		} //end if
		if ( ( *aasworld ).areasettings[area].areaflags & AREA_DISABLED ) {
			botimport.Print( PRT_MESSAGE, "DISABLED" );
		} //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
	  //*
	if ( parm0 & 1 ) {
		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 (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 == 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;
		bot_goal_t goal;
		aas_reachability_t reach;

		goal.areanum = botlibglobals.goalareanum;
		VectorCopy( botlibglobals.goalorigin, goal.origin );
		reachnum = BotGetReachabilityToGoal( origin, newarea, -1,
											 lastgoalareanum, lastareanum,
											 avoidreach, avoidreachtimes, avoidreachtries,
											 &goal, TFL_DEFAULT | TFL_FUNCBOB, TFL_DEFAULT | TFL_FUNCBOB );
		AAS_ReachabilityFromNum( reachnum, &reach );
		AAS_ShowReachability( &reach );
	} //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);
*/

	/*
	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
#else
	static int area = -1;
	static int line[2];
	int newarea, i, highlightarea, bot_testhidepos, hideposarea, bot_debug;
	vec3_t forward, origin;

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

	if ( !aasworld->loaded ) {
		return 0;
	}

	AAS_SetCurrentWorld( 0 );

	for ( i = 0; i < 2; i++ ) {
		if ( !line[i] ) {
			line[i] = botimport.DebugLineCreate();
		}
	}

//	AAS_ClearShownDebugLines();
	bot_testhidepos = LibVarGetValue( "bot_testhidepos" );
	if ( bot_testhidepos ) {
		VectorCopy( parm2, origin );
		newarea = BotFuzzyPointReachabilityArea( origin );

		if ( parm0 & 1 ) {
			botlibglobals.goalareanum = newarea;
			VectorCopy( origin, botlibglobals.goalorigin );
			botimport.Print( PRT_MESSAGE, "new enemy position %2.1f %2.1f %2.1f area %d\n", origin[0], origin[1], origin[2], newarea );
		} //end if

		AAS_ClearShownPolygons();
		AAS_ClearShownDebugLines();
		hideposarea = AAS_NearestHideArea( 0, origin, AAS_PointAreaNum( origin ), 0,
										   botlibglobals.goalorigin, botlibglobals.goalareanum, TFL_DEFAULT, 99999, NULL );

		//area we are currently in
		AAS_ShowAreaPolygons( newarea, 1, qtrue );

		//enemy position
		AAS_ShowAreaPolygons( botlibglobals.goalareanum, 2, qtrue );

		//area we should go hide
		AAS_ShowAreaPolygons( hideposarea, 4, qtrue );

		return 0;
	}

	highlightarea = LibVarGetValue( "bot_highlightarea" );
	if ( highlightarea > 0 ) {
		newarea = highlightarea;
	} else {
		VectorCopy( parm2, origin );

		//origin[2] += 0.5;
		newarea = BotFuzzyPointReachabilityArea( origin );
	} //end else

	bot_debug = LibVarGetValue( "bot_debug" );
	if ( bot_debug == 9 ) {
		aas_clientmove_t move;
		vec3_t dest;
		qboolean this_success;

		if ( parm0 & 1 ) {
			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 );
		}

		VectorCopy( parm2, origin );
		VectorCopy( botlibglobals.goalorigin, dest );

		// debug direct movement
		VectorSubtract( dest, origin, forward );
		VectorNormalize( forward );
		VectorScale( forward, 300, forward );

		this_success = AAS_PredictClientMovement( &move, 0, origin,
												  -1, qfalse,
												  forward, dest, -1,
												  40, 0.05, SE_ENTERAREA | SE_HITGROUNDDAMAGE | SE_HITENT | SE_HITGROUNDAREA | SE_STUCK | SE_GAP, botlibglobals.goalareanum,
												  qtrue );

		if ( this_success ) {
			switch ( move.stopevent ) {
			case SE_ENTERAREA:
			case SE_HITENT:
			case SE_HITGROUNDAREA:
				break;
			default:
				this_success = qfalse;
			}
		}

		if ( this_success != botlibglobals.lastsuccess ) {
			botimport.Print( PRT_MESSAGE, "DirectMove: %s\n", this_success ? "SUCCESS" : "FAILURE" );
			botlibglobals.lastsuccess = this_success;
		}

		return 0;
	}

	botimport.Print( PRT_MESSAGE, "\rtravel time to goal (%d) = %d  ", botlibglobals.goalareanum, AAS_AreaTravelTimeToGoalArea( newarea, origin, botlibglobals.goalareanum, TFL_DEFAULT ) );
	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 ) );

		if ( aasworld->areasettings[area].areaflags & AREA_LIQUID ) {
			botimport.Print( PRT_MESSAGE, "liquid area\n" );
		} //end if

		botimport.Print( PRT_MESSAGE, "area contents: " );
		if ( aasworld->areasettings[area].contents & AREACONTENTS_MOVER ) {
			botimport.Print( PRT_MESSAGE, "mover " );
		} //end if
		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, "slag " );
		} //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_DONOTENTER ) {
			botimport.Print( PRT_MESSAGE, "do not enter " );
		} //end if
		if ( aasworld->areasettings[area].contents & AREACONTENTS_DONOTENTER_LARGE ) {
			botimport.Print( PRT_MESSAGE, "do not enter large " );
		} //end if
		if ( !aasworld->areasettings[area].contents ) {
			botimport.Print( PRT_MESSAGE, "empty " );
		} //end if

		botimport.Print( PRT_MESSAGE, "\n" );
		botimport.Print( PRT_MESSAGE, "area flags: " );

		if ( aasworld->areasettings[area].areaflags & AREA_LADDER ) {
			botimport.Print( PRT_MESSAGE, "ladder " );
		}
		if ( aasworld->areasettings[area].areaflags & AREA_GROUNDED ) {
			botimport.Print( PRT_MESSAGE, "grounded " );
		}
		if ( aasworld->areasettings[area].areaflags & AREA_LIQUID ) {
			botimport.Print( PRT_MESSAGE, "liquid " );
		}
		if ( aasworld->areasettings[area].areaflags & AREA_DISABLED ) {
			botimport.Print( PRT_MESSAGE, "DISABLED " );
		}
		if ( aasworld->areasettings[area].areaflags & AREA_AVOID ) {
			botimport.Print( PRT_MESSAGE, "AVOID " );
		}

		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 ) );
	}

	if ( parm0 & 1 ) {
		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 );
	}

	AAS_ClearShownPolygons();
	AAS_ClearShownDebugLines();

	if ( parm0 & 8 ) {
		int jk = 0;
		if ( parm0 & 16 ) {
			for ( ; jk < aasworld->numareas; jk++ ) {
				if ( !( aasworld->areasettings[jk].areaflags & AREA_DISABLED ) ) {
					AAS_ShowAreaPolygons( jk, 1, parm0 & 4 );
				}
			}
		} else {
			for ( ; jk < aasworld->numareas; jk++ ) {
				AAS_ShowAreaPolygons( jk, 1, parm0 & 4 );
			}
		}
	} else {
		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;
		bot_goal_t goal;
		aas_reachability_t reach;
		static int lastreach;

		goal.areanum = botlibglobals.goalareanum;
		VectorCopy( botlibglobals.goalorigin, goal.origin );
		reachnum = BotGetReachabilityToGoal( origin, newarea, -1,
											 lastgoalareanum, lastareanum,
											 avoidreach, avoidreachtimes, avoidreachtries,
											 &goal, TFL_DEFAULT | TFL_FUNCBOB, TFL_DEFAULT );
		AAS_ReachabilityFromNum( reachnum, &reach );
		if ( lastreach != reachnum ) {
			botimport.Print( PRT_MESSAGE, "Travel Type: " );
			AAS_PrintTravelType( reach.traveltype );
			botimport.Print( PRT_MESSAGE, "\n" );
		}
		lastreach = reachnum;
		AAS_ShowReachability( &reach );
	} //end else
	VectorClear( forward );
#endif // RTCW_XX

	return 0;
} //end of the function BotExportTest
Example #7
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
Example #8
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