int AAS_AlternativeRouteGoals(vec3_t start, vec3_t goal, int travelflags, aas_altroutegoal_t *altroutegoals, int maxaltroutegoals, int color) { #ifndef ENABLE_ALTROUTING return 0; #else int i, j, startareanum, goalareanum, bestareanum; int numaltroutegoals, nummidrangeareas; int starttime, goaltime, goaltraveltime; float dist, bestdist; vec3_t mid, dir; int reachnum, time; int a1, a2; /*#ifdef DEBUG int startmillisecs; startmillisecs = Sys_MilliSeconds(); #endif*/ startareanum = AAS_PointAreaNum(start); if (!startareanum) { return 0; } goalareanum = AAS_PointAreaNum(goal); if (!goalareanum) { VectorCopy(goal, dir); dir[2] += 30; goalareanum = AAS_PointAreaNum(dir); if (!goalareanum) { return 0; } } //travel time towards the goal area goaltraveltime = AAS_AreaTravelTimeToGoalArea(startareanum, start, goalareanum, travelflags); //clear the midrange areas memset(midrangeareas, 0, (*aasworld).numareas * sizeof(midrangearea_t)); numaltroutegoals = 0; // nummidrangeareas = 0; // for (i = 1; i < (*aasworld).numareas; i++) { // if (!((*aasworld).areasettings[i].contents & AREACONTENTS_ROUTEPORTAL) && !((*aasworld).areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL)) { continue; } //if the area has no reachabilities if (!AAS_AreaReachability(i)) { continue; } //tavel time from the area to the start area starttime = AAS_AreaTravelTimeToGoalArea(startareanum, start, i, travelflags); if (!starttime) { continue; } //if the travel time from the start to the area is greater than the shortest goal travel time if (starttime > 500 + 3.0 * goaltraveltime) { continue; } //travel time from the area to the goal area goaltime = AAS_AreaTravelTimeToGoalArea(i, NULL, goalareanum, travelflags); if (!goaltime) { continue; } //if the travel time from the area to the goal is greater than the shortest goal travel time if (goaltime > 500 + 3.0 * goaltraveltime) { continue; } //this is a mid range area midrangeareas[i].valid = qtrue; midrangeareas[i].starttime = starttime; midrangeareas[i].goaltime = goaltime; Log_Write("%d midrange area %d", nummidrangeareas, i); nummidrangeareas++; } //end for // for (i = 1; i < (*aasworld).numareas; i++) { if (!midrangeareas[i].valid) { continue; } //get the areas in one cluster numclusterareas = 0; AAS_AltRoutingFloodCluster_r(i); //now we've got a cluster with areas through which an alternative route could go //get the 'center' of the cluster VectorClear(mid); for (j = 0; j < numclusterareas; j++) { VectorAdd(mid, (*aasworld).areas[clusterareas[j]].center, mid); } //end for VectorScale(mid, 1.0 / numclusterareas, mid); //get the area closest to the center of the cluster bestdist = 999999; bestareanum = 0; for (j = 0; j < numclusterareas; j++) { VectorSubtract(mid, (*aasworld).areas[clusterareas[j]].center, dir); dist = VectorLength(dir); if (dist < bestdist) { bestdist = dist; bestareanum = clusterareas[j]; } //end if } //end for // make sure the route to the destination isn't in the same direction as the route to the source if (!AAS_AreaRouteToGoalArea(bestareanum, (*aasworld).areawaypoints[bestareanum], goalareanum, travelflags, &time, &reachnum)) { continue; } a1 = (*aasworld).reachability[reachnum].areanum; if (!AAS_AreaRouteToGoalArea(bestareanum, (*aasworld).areawaypoints[bestareanum], startareanum, travelflags, &time, &reachnum)) { continue; } a2 = (*aasworld).reachability[reachnum].areanum; if (a1 == a2) { continue; } //now we've got an area for an alternative route //FIXME: add alternative goal origin VectorCopy((*aasworld).areawaypoints[bestareanum], altroutegoals[numaltroutegoals].origin); altroutegoals[numaltroutegoals].areanum = bestareanum; altroutegoals[numaltroutegoals].starttraveltime = midrangeareas[bestareanum].starttime; altroutegoals[numaltroutegoals].goaltraveltime = midrangeareas[bestareanum].goaltime; altroutegoals[numaltroutegoals].extratraveltime = (midrangeareas[bestareanum].starttime + midrangeareas[bestareanum].goaltime) - goaltraveltime; numaltroutegoals++; // /*#ifdef DEBUG botimport.Print(PRT_MESSAGE, "alternative route goal area %d, numclusterareas = %d\n", bestareanum, numclusterareas); if (color) { AAS_DrawPermanentCross((*aasworld).areas[bestareanum].center, 10, color); } //end if //AAS_ShowArea(bestarea, qtrue); #endif*/ //don't return more than the maximum alternative route goals if (numaltroutegoals >= maxaltroutegoals) { break; } } //end for //botimport.Print(PRT_MESSAGE, "%d alternative route goals\n", numaltroutegoals); #ifdef DEBUG // botimport.Print(PRT_MESSAGE, "alternative route goals in %d msec\n", Sys_MilliSeconds() - startmillisecs); #endif return numaltroutegoals; #endif } //end of the function AAS_AlternativeRouteGoals
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int AAS_AlternativeRouteGoals(vec3_t start, int startareanum, vec3_t goal, int goalareanum, int travelflags, aas_altroutegoal_t *altroutegoals, int maxaltroutegoals, int type) { #ifndef ENABLE_ALTROUTING return 0; #else int i, j, bestareanum; int numaltroutegoals, nummidrangeareas; int starttime, goaltime, goaltraveltime; float dist, bestdist; vec3_t mid, dir; #ifdef ALTROUTE_DEBUG int startmillisecs; startmillisecs = Sys_MilliSeconds(); #endif if (!startareanum || !goalareanum) return 0; //travel time towards the goal area goaltraveltime = AAS_AreaTravelTimeToGoalArea(startareanum, start, goalareanum, travelflags); //clear the midrange areas Com_Memset(midrangeareas, 0, aasworld.numareas * sizeof(midrangearea_t)); numaltroutegoals = 0; // nummidrangeareas = 0; // for (i = 1; i < aasworld.numareas; i++) { // if (!(type & ALTROUTEGOAL_ALL)) { if (!(type & ALTROUTEGOAL_CLUSTERPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_CLUSTERPORTAL))) { if (!(type & ALTROUTEGOAL_VIEWPORTALS && (aasworld.areasettings[i].contents & AREACONTENTS_VIEWPORTAL))) { continue; } //end if } //end if } //end if //if the area has no reachabilities if (!AAS_AreaReachability(i)) continue; //tavel time from the area to the start area starttime = AAS_AreaTravelTimeToGoalArea(startareanum, start, i, travelflags); if (!starttime) continue; //if the travel time from the start to the area is greater than the shortest goal travel time if (starttime > (float) 1.1 * goaltraveltime) continue; //travel time from the area to the goal area goaltime = AAS_AreaTravelTimeToGoalArea(i, NULL, goalareanum, travelflags); if (!goaltime) continue; //if the travel time from the area to the goal is greater than the shortest goal travel time if (goaltime > (float) 0.8 * goaltraveltime) continue; //this is a mid range area midrangeareas[i].valid = qtrue; midrangeareas[i].starttime = starttime; midrangeareas[i].goaltime = goaltime; Log_Write("%d midrange area %d", nummidrangeareas, i); nummidrangeareas++; } //end for // for (i = 1; i < aasworld.numareas; i++) { if (!midrangeareas[i].valid) continue; //get the areas in one cluster numclusterareas = 0; AAS_AltRoutingFloodCluster_r(i); //now we've got a cluster with areas through which an alternative route could go //get the 'center' of the cluster VectorClear(mid); for (j = 0; j < numclusterareas; j++) { VectorAdd(mid, aasworld.areas[clusterareas[j]].center, mid); } //end for VectorScale(mid, 1.0 / numclusterareas, mid); //get the area closest to the center of the cluster bestdist = 999999; bestareanum = 0; for (j = 0; j < numclusterareas; j++) { VectorSubtract(mid, aasworld.areas[clusterareas[j]].center, dir); dist = VectorLength(dir); if (dist < bestdist) { bestdist = dist; bestareanum = clusterareas[j]; } //end if } //end for //now we've got an area for an alternative route //FIXME: add alternative goal origin VectorCopy(aasworld.areas[bestareanum].center, altroutegoals[numaltroutegoals].origin); altroutegoals[numaltroutegoals].areanum = bestareanum; altroutegoals[numaltroutegoals].starttraveltime = midrangeareas[bestareanum].starttime; altroutegoals[numaltroutegoals].goaltraveltime = midrangeareas[bestareanum].goaltime; altroutegoals[numaltroutegoals].extratraveltime = (midrangeareas[bestareanum].starttime + midrangeareas[bestareanum].goaltime) - goaltraveltime; numaltroutegoals++; // #ifdef ALTROUTE_DEBUG AAS_ShowAreaPolygons(bestareanum, 1, qtrue); #endif //don't return more than the maximum alternative route goals if (numaltroutegoals >= maxaltroutegoals) break; } //end for #ifdef ALTROUTE_DEBUG botimport.Print(PRT_MESSAGE, "alternative route goals in %d msec\n", Sys_MilliSeconds() - startmillisecs); #endif return numaltroutegoals; #endif } //end of the function AAS_AlternativeRouteGoals
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
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
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int BotChooseNBGItem( int goalstate, vec3_t origin, int *inventory, int travelflags, bot_goal_t *ltg, float maxtime ) { int areanum, t, weightnum, ltg_time; float weight, bestweight, avoidtime; iteminfo_t *iteminfo; itemconfig_t *ic; levelitem_t *li, *bestitem; bot_goal_t goal; bot_goalstate_t *gs; gs = BotGoalStateFromHandle( goalstate ); if ( !gs ) { return qfalse; } if ( !gs->itemweightconfig ) { return qfalse; } //get the area the bot is in areanum = BotReachabilityArea( origin, gs->client ); //if the bot is in solid or if the area the bot is in has no reachability links if ( !areanum || !AAS_AreaReachability( areanum ) ) { //use the last valid area the bot was in areanum = gs->lastreachabilityarea; } //end if //remember the last area with reachabilities the bot was in gs->lastreachabilityarea = areanum; //if still in solid if ( !areanum ) { return qfalse; } // if ( ltg ) { ltg_time = AAS_AreaTravelTimeToGoalArea( areanum, origin, ltg->areanum, travelflags ); } else { ltg_time = 99999;} //the item configuration ic = itemconfig; if ( !itemconfig ) { return qfalse; } //best weight and item so far bestweight = 0; bestitem = NULL; memset( &goal, 0, sizeof( bot_goal_t ) ); //go through the items in the level for ( li = levelitems; li; li = li->next ) { if ( g_gametype == GT_SINGLE_PLAYER ) { if ( li->notsingle ) { continue; } } else if ( g_gametype >= GT_TEAM ) { if ( li->notteam ) { continue; } } else { if ( li->notfree ) { continue; } } //if the item is in a possible goal area if ( !li->goalareanum ) { continue; } //get the fuzzy weight function for this item iteminfo = &ic->iteminfo[li->iteminfo]; weightnum = gs->itemweightindex[iteminfo->number]; if ( weightnum < 0 ) { continue; } //if this goal is in the avoid goals if ( BotAvoidGoalTime( goalstate, li->number ) > 0 ) { continue; } // #ifdef UNDECIDEDFUZZY weight = FuzzyWeightUndecided( inventory, gs->itemweightconfig, weightnum ); #else weight = FuzzyWeight( inventory, gs->itemweightconfig, weightnum ); #endif //UNDECIDEDFUZZY #ifdef DROPPEDWEIGHT //HACK: to make dropped items more attractive if ( li->timeout ) { weight += 1000; } #endif //DROPPEDWEIGHT if ( weight > 0 ) { //get the travel time towards the goal area t = AAS_AreaTravelTimeToGoalArea( areanum, origin, li->goalareanum, travelflags ); //if the goal is reachable if ( t > 0 && t < maxtime ) { weight /= (float) t * TRAVELTIME_SCALE; // if ( weight > bestweight ) { t = 0; if ( ltg && !li->timeout ) { //get the travel time from the goal to the long term goal t = AAS_AreaTravelTimeToGoalArea( li->goalareanum, li->goalorigin, ltg->areanum, travelflags ); } //end if //if the travel back is possible and doesn't take too long if ( t <= ltg_time ) { bestweight = weight; bestitem = li; } //end if } //end if } //end if } //end if } //end for //if no goal item found if ( !bestitem ) { return qfalse; } //create a bot goal for this item iteminfo = &ic->iteminfo[bestitem->iteminfo]; VectorCopy( bestitem->goalorigin, goal.origin ); VectorCopy( iteminfo->mins, goal.mins ); VectorCopy( iteminfo->maxs, goal.maxs ); goal.areanum = bestitem->goalareanum; goal.entitynum = bestitem->entitynum; goal.number = bestitem->number; goal.flags = GFL_ITEM; goal.iteminfo = bestitem->iteminfo; //add the chosen goal to the goals to avoid for a while avoidtime = iteminfo->respawntime * 0.5; if ( avoidtime < 10 ) { avoidtime = AVOID_TIME; } //if it's a dropped item if ( bestitem->timeout ) { avoidtime = AVOIDDROPPED_TIME; } BotAddToAvoidGoals( gs, bestitem->number, avoidtime ); //push the goal on the stack BotPushGoal( goalstate, &goal ); // #ifdef DEBUG_AI_GOAL if ( bestitem->timeout ) { botimport.Print( PRT_MESSAGE, "new nbg dropped item %s\n", ic->iteminfo[bestitem->iteminfo].classname ); } //end if iteminfo = &ic->iteminfo[bestitem->iteminfo]; botimport.Print( PRT_MESSAGE, "new nbg \"%s\"\n", iteminfo->classname ); #endif //DEBUG_AI_GOAL return qtrue; } //end of the function BotChooseNBGItem
qboolean AAS_RT_GetHidePos( vec3_t srcpos, int srcnum, int srcarea, vec3_t destpos, int destnum, int destarea, vec3_t returnPos ) { static int tfl = TFL_DEFAULT & ~( TFL_JUMPPAD | TFL_ROCKETJUMP | TFL_BFGJUMP | TFL_GRAPPLEHOOK | TFL_DOUBLEJUMP | TFL_RAMPJUMP | TFL_STRAFEJUMP | TFL_LAVA ); //----(SA) modified since slime is no longer deadly // static int tfl = TFL_DEFAULT & ~(TFL_JUMPPAD|TFL_ROCKETJUMP|TFL_BFGJUMP|TFL_GRAPPLEHOOK|TFL_DOUBLEJUMP|TFL_RAMPJUMP|TFL_STRAFEJUMP|TFL_SLIME|TFL_LAVA); #if 1 // use MrE's breadth first method int hideareanum; // int pretime; // disabled this so grenade hiding works //if (!srcarea || !destarea) // return qfalse; // pretime = -Sys_MilliSeconds(); hideareanum = AAS_NearestHideArea( srcnum, srcpos, srcarea, destnum, destpos, destarea, tfl ); if ( !hideareanum ) { // botimport.Print(PRT_MESSAGE, "Breadth First HidePos FAILED: %i ms\n", pretime + Sys_MilliSeconds()); return qfalse; } // we found a valid hiding area VectorCopy( ( *aasworld ).areawaypoints[hideareanum], returnPos ); // botimport.Print(PRT_MESSAGE, "Breadth First HidePos: %i ms\n", pretime + Sys_MilliSeconds()); return qtrue; #else // look around at random parent areas, if any of them have a center point // that isn't visible from "destpos", then return it's position in returnPos int i, j, pathArea, dir; unsigned short int destTravelTime; aas_rt_parent_t *srcParent, *travParent, *destParent; aas_rt_child_t *srcChild, *destChild, *travChild; aas_rt_route_t *route; vec3_t destVec; float destTravelDist; static float lastTime; static int frameCount, maxPerFrame = 2; int firstreach; aas_reachability_t *reachability, *reach; qboolean startVisible; unsigned short int bestTravelTime, thisTravelTime, elapsedTravelTime; #define MAX_HIDE_TRAVELTIME 1000 // 10 seconds is a very long way away unsigned char destVisLookup[MAX_PARENTS]; unsigned short int *destVisTrav; aas_rt_t *rt; const int MAX_CHECK_VISPARENTS = 100; int visparents_count, total_parents_checked; int thisParentIndex; int pretime; if ( !( rt = aasworld->routetable ) ) { // no route table present return qfalse; } /* if (lastTime > (AAS_Time() - 0.1)) { if (frameCount++ > maxPerFrame) { return qfalse; } } else { frameCount = 0; lastTime = AAS_Time(); } */ pretime = -Sys_MilliSeconds(); // is the src area grounded? if ( !( srcChild = AAS_RT_GetChild( srcarea ) ) ) { return qfalse; } // does it have a parent? // all valid areas have a parent // if (!srcChild->numParentLinks) { // return qfalse; // } // get the dest (enemy) area if ( !( destChild = AAS_RT_GetChild( destarea ) ) ) { return qfalse; } destParent = &rt->parents[ rt->parentLinks[destChild->startParentLinks].parent ]; // // populate the destVisAreas memset( destVisLookup, 0, sizeof( destVisLookup ) ); destVisTrav = rt->visibleParents + destParent->startVisibleParents; for ( i = 0; i < destParent->numVisibleParents; i++, destVisTrav++ ) { destVisLookup[*destVisTrav] = 1; } // // use the first parent to source the vis areas from srcParent = &rt->parents[ rt->parentLinks[srcChild->startParentLinks].parent ]; // // set the destTravelTime if ( route = AAS_RT_GetRoute( srcarea, srcpos, destarea ) ) { destTravelTime = route->travel_time; } else { destTravelTime = 0; } bestTravelTime = MAX_HIDE_TRAVELTIME; // ignore any routes longer than 10 seconds away // set the destVec VectorSubtract( destpos, srcpos, destVec ); destTravelDist = VectorNormalize( destVec ); // // randomize the direction we traverse the list, so the hiding spot isn't always the same if ( rand() % 2 ) { dir = 1; // forward } else { dir = -1; // reverse } // randomize the starting area if ( srcParent->numVisibleParents ) { i = rand() % srcParent->numVisibleParents; } else { // prevent divide by zero i = 0; } // // setup misc stuff reachability = ( *aasworld ).reachability; startVisible = botimport.AICast_VisibleFromPos( destpos, destnum, srcpos, srcnum, qfalse ); // // set the firstreach to prevent having to do an array and pointer lookup for each destination firstreach = ( *aasworld ).areasettings[srcarea].firstreachablearea; // // just check random parent areas, traversing the route until we find an area that can't be seen from the dest area for ( visparents_count = 0, total_parents_checked = 0; visparents_count < MAX_CHECK_VISPARENTS && total_parents_checked < rt->numParents; total_parents_checked++ ) { thisParentIndex = rand() % rt->numParents; travParent = &rt->parents[ thisParentIndex ]; // // never go to the enemy's areas if ( travParent->areanum == destarea ) { continue; } // // if it's visible from dest, ignore it if ( destVisLookup[thisParentIndex] ) { continue; } // visparents_count++; // they might be visible, check to see if the path to the area, takes us towards the // enemy we are trying to hide from { qboolean invalidRoute; vec3_t curPos, lastVec; #define GETHIDE_MAX_CHECK_PATHS 15 // invalidRoute = qfalse; // initialize the pathArea pathArea = srcarea; VectorCopy( srcpos, curPos ); // now evaluate the path for ( j = 0; j < GETHIDE_MAX_CHECK_PATHS; j++ ) { // get the reachability to the travParent if ( !( route = AAS_RT_GetRoute( pathArea, curPos, travParent->areanum ) ) ) { // we can't get to the travParent, so don't bother checking it invalidRoute = qtrue; break; } // set the pathArea reach = &reachability[route->reachable_index]; // how far have we travelled so far? elapsedTravelTime = AAS_AreaTravelTimeToGoalArea( pathArea, curPos, reach->areanum, tfl ); // add the travel to the center of the area elapsedTravelTime += AAS_AreaTravelTime( reach->areanum, reach->end, ( *aasworld ).areas[reach->areanum].center ); // have we gone too far already? if ( elapsedTravelTime > bestTravelTime ) { invalidRoute = qtrue; break; } else { thisTravelTime = route->travel_time; } // // if this travel would have us do something wierd if ( ( reach->traveltype == TRAVEL_WALKOFFLEDGE ) && ( reach->traveltime > 500 ) ) { invalidRoute = qtrue; break; } // pathArea = reach->areanum; VectorCopy( reach->end, curPos ); // // if this moves us into the enemies area, skip it if ( pathArea == destarea ) { invalidRoute = qtrue; break; } // if we are very close, don't get any closer under any circumstances { vec3_t vec; float dist; // VectorSubtract( destpos, reachability[firstreach + route->reachable_index].end, vec ); dist = VectorNormalize( vec ); // if ( destTravelTime < 400 ) { if ( dist < destTravelDist ) { invalidRoute = qtrue; break; } if ( DotProduct( destVec, vec ) < 0.2 ) { invalidRoute = qtrue; break; } } else { if ( dist < destTravelDist * 0.7 ) { invalidRoute = qtrue; break; } } // // check the directions to make sure we're not trying to run through them if ( j > 0 ) { if ( DotProduct( vec, lastVec ) < 0.2 ) { invalidRoute = qtrue; break; } } else if ( DotProduct( destVec, vec ) < 0.2 ) { invalidRoute = qtrue; break; } // VectorCopy( vec, lastVec ); } // // if this area isn't in the visible list for the enemy's area, it's a good hiding spot if ( !( travChild = AAS_RT_GetChild( pathArea ) ) ) { invalidRoute = qtrue; break; } if ( !destVisLookup[rt->parentLinks[travChild->startParentLinks].parent] ) { // success ? if ( !botimport.AICast_VisibleFromPos( destpos, destnum, ( *aasworld ).areas[pathArea].center, srcnum, qfalse ) ) { // SUCESS !! travParent = &rt->parents[rt->parentLinks[travChild->startParentLinks].parent]; break; } } else { // if we weren't visible when starting, make sure we don't move into their view if ( !startVisible ) { //botimport.AICast_VisibleFromPos( destpos, destnum, reachability[firstreach + route->reachable_index].end, srcnum, qfalse )) { invalidRoute = qtrue; break; } } // // if this is the travParent, then stop checking if ( pathArea == travParent->areanum ) { invalidRoute = qtrue; // we didn't find a hiding spot break; } } // end for areas in route // // if the route is invalid, skip this travParent if ( invalidRoute ) { continue; } } // // now last of all, check that this area is a safe hiding spot // if (botimport.AICast_VisibleFromPos( destpos, destnum, (*aasworld).areas[travParent->areanum].center, srcnum, qfalse )) { // continue; // } // // we've found a good hiding spot, so use it VectorCopy( ( *aasworld ).areas[travParent->areanum].center, returnPos ); bestTravelTime = elapsedTravelTime; // if ( thisTravelTime < 300 ) { botimport.Print( PRT_MESSAGE, "Fuzzy RT HidePos: %i ms\n", pretime + Sys_MilliSeconds() ); return qtrue; } } // // did we find something? if ( bestTravelTime < MAX_HIDE_TRAVELTIME ) { botimport.Print( PRT_MESSAGE, "Fuzzy RT HidePos: %i ms\n", pretime + Sys_MilliSeconds() ); return qtrue; } // // couldn't find anything botimport.Print( PRT_MESSAGE, "Fuzzy RT HidePos FAILED: %i ms\n", pretime + Sys_MilliSeconds() ); return qfalse; #endif }
static bool BotChooseNBGItem( int goalstate, const vec3_t origin, const int* inventory, int travelflags, const bot_goal_t* ltg, float maxtime ) { bot_goalstate_t* gs = BotGoalStateFromHandle( goalstate ); if ( !gs ) { return false; } if ( !gs->itemweightconfig ) { return false; } //get the area the bot is in int areanum = BotReachabilityArea( origin, gs->client ); //if the bot is in solid or if the area the bot is in has no reachability links if ( !areanum || !AAS_AreaReachability( areanum ) ) { //use the last valid area the bot was in areanum = gs->lastreachabilityarea; } //remember the last area with reachabilities the bot was in gs->lastreachabilityarea = areanum; //if still in solid if ( !areanum ) { return false; } int ltg_time; if ( ltg ) { ltg_time = AAS_AreaTravelTimeToGoalArea( areanum, origin, ltg->areanum, travelflags ); } else { ltg_time = 99999; } //the item configuration itemconfig_t* ic = itemconfig; if ( !itemconfig ) { return false; } //best weight and item so far float bestweight = 0; levelitem_t* bestitem = NULL; //go through the items in the level for ( levelitem_t* li = levelitems; li; li = li->next ) { if ( GGameType & GAME_ET ) { if ( g_singleplayer ) { if ( li->flags & IFL_NOTSINGLE ) { continue; } } } else { if ( g_gametype == Q3GT_SINGLE_PLAYER ) { if ( li->flags & IFL_NOTSINGLE ) { continue; } } else if ( g_gametype >= Q3GT_TEAM ) { if ( li->flags & IFL_NOTTEAM ) { continue; } } else { if ( li->flags & IFL_NOTFREE ) { continue; } } } if ( GGameType & GAME_Quake3 && li->flags & IFL_NOTBOT ) { continue; } //if the item is in a possible goal area if ( !li->goalareanum ) { continue; } //FIXME: is this a good thing? added this for items that never spawned into the game (f.i. CTF flags in obelisk) if ( GGameType & GAME_Quake3 && !li->entitynum && !( li->flags & IFL_ROAM ) ) { continue; } //get the fuzzy weight function for this item iteminfo_t* iteminfo = &ic->iteminfo[ li->iteminfo ]; int weightnum = gs->itemweightindex[ iteminfo->number ]; if ( weightnum < 0 ) { continue; } //if this goal is in the avoid goals if ( !( GGameType & GAME_Quake3 ) && BotAvoidGoalTime( goalstate, li->number ) > 0 ) { continue; } float weight = FuzzyWeightUndecided( inventory, gs->itemweightconfig, weightnum ); //HACK: to make dropped items more attractive if ( li->timeout ) { weight += GGameType & GAME_Quake3 ? droppedweight->value : 1000; } //use weight scale for item_botroam if ( GGameType & GAME_Quake3 && li->flags & IFL_ROAM ) { weight *= li->weight; } if ( weight > 0 ) { //get the travel time towards the goal area int t = AAS_AreaTravelTimeToGoalArea( areanum, origin, li->goalareanum, travelflags ); //if the goal is reachable if ( t > 0 && t < maxtime ) { if ( GGameType & GAME_Quake3 ) { //if this item won't respawn before we get there float avoidtime = BotAvoidGoalTime( goalstate, li->number ); if ( avoidtime - t * 0.009 > 0 ) { continue; } } weight /= ( float )t * TRAVELTIME_SCALE; if ( weight > bestweight ) { t = 0; if ( ltg && !li->timeout ) { //get the travel time from the goal to the long term goal t = AAS_AreaTravelTimeToGoalArea( li->goalareanum, li->goalorigin, ltg->areanum, travelflags ); } //if the travel back is possible and doesn't take too long if ( t <= ltg_time ) { bestweight = weight; bestitem = li; } } } } } //if no goal item found if ( !bestitem ) { return false; } //create a bot goal for this item bot_goal_t goal; Com_Memset( &goal, 0, sizeof ( bot_goal_t ) ); iteminfo_t* iteminfo = &ic->iteminfo[ bestitem->iteminfo ]; VectorCopy( bestitem->goalorigin, goal.origin ); VectorCopy( iteminfo->mins, goal.mins ); VectorCopy( iteminfo->maxs, goal.maxs ); goal.areanum = bestitem->goalareanum; goal.entitynum = bestitem->entitynum; goal.number = bestitem->number; goal.flags = GFL_ITEM; if ( GGameType & GAME_Quake3 ) { if ( bestitem->timeout ) { goal.flags |= GFL_DROPPED; } if ( bestitem->flags & IFL_ROAM ) { goal.flags |= GFL_ROAM; } } goal.iteminfo = bestitem->iteminfo; float avoidtime; if ( GGameType & GAME_Quake3 ) { //if it's a dropped item if ( bestitem->timeout ) { avoidtime = AVOID_DROPPED_TIME; } else { avoidtime = iteminfo->respawntime; if ( !avoidtime ) { avoidtime = AVOID_DEFAULT_TIME; } if ( avoidtime < AVOID_MINIMUM_TIME ) { avoidtime = AVOID_MINIMUM_TIME; } } } else { avoidtime = iteminfo->respawntime * 0.5; if ( avoidtime < 10 ) { avoidtime = AVOID_DEFAULT_TIME; } //if it's a dropped item if ( bestitem->timeout ) { avoidtime = AVOID_DROPPED_TIME_WOLF; } } //add the chosen goal to the goals to avoid for a while BotAddToAvoidGoals( gs, bestitem->number, avoidtime ); //push the goal on the stack BotPushGoal( goalstate, &goal, sizeof ( goal ) ); return true; }