📄 be_ai_move.c
字号:
VectorCopy(org, end);
end[0] += x * 8;
end[1] += y * 8;
end[2] += z * 12;
numareas = AAS_TraceAreas(org, end, areas, points, 10);
for (j = 0; j < numareas; j++)
{
if (AAS_AreaReachability(areas[j]))
{
VectorSubtract(points[j], org, v);
dist = VectorLength(v);
if (dist < bestdist)
{
bestareanum = areas[j];
bestdist = dist;
} //end if
} //end if
} //end for
} //end for
} //end for
if (bestareanum) return bestareanum;
} //end for
if (!testground) break;
} //end for
//#ifdef DEBUG
//botimport.Print(PRT_MESSAGE, "no reachability area\n");
//#endif //DEBUG
return firstareanum;
} //end of the function BotReachabilityArea*/
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotOnMover(vec3_t origin, int entnum, aas_reachability_t *reach)
{
int i, modelnum;
vec3_t mins, maxs, modelorigin, org, end;
vec3_t angles = {0, 0, 0};
vec3_t boxmins = {-16, -16, -8}, boxmaxs = {16, 16, 8};
bsp_trace_t trace;
modelnum = reach->facenum & 0x0000FFFF;
//get some bsp model info
AAS_BSPModelMinsMaxsOrigin(modelnum, angles, mins, maxs, NULL);
//
if (!AAS_OriginOfMoverWithModelNum(modelnum, modelorigin))
{
botimport.Print(PRT_MESSAGE, "no entity with model %d\n", modelnum);
return qfalse;
} //end if
//
for (i = 0; i < 2; i++)
{
if (origin[i] > modelorigin[i] + maxs[i] + 16) return qfalse;
if (origin[i] < modelorigin[i] + mins[i] - 16) return qfalse;
} //end for
//
VectorCopy(origin, org);
org[2] += 24;
VectorCopy(origin, end);
end[2] -= 48;
//
trace = AAS_Trace(org, boxmins, boxmaxs, end, entnum, CONTENTS_SOLID|CONTENTS_PLAYERCLIP);
if (!trace.startsolid && !trace.allsolid)
{
//NOTE: the reachability face number is the model number of the elevator
if (trace.ent != ENTITYNUM_NONE && AAS_EntityModelNum(trace.ent) == modelnum)
{
return qtrue;
} //end if
} //end if
return qfalse;
} //end of the function BotOnMover
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int MoverDown(aas_reachability_t *reach)
{
int modelnum;
vec3_t mins, maxs, origin;
vec3_t angles = {0, 0, 0};
modelnum = reach->facenum & 0x0000FFFF;
//get some bsp model info
AAS_BSPModelMinsMaxsOrigin(modelnum, angles, mins, maxs, origin);
//
if (!AAS_OriginOfMoverWithModelNum(modelnum, origin))
{
botimport.Print(PRT_MESSAGE, "no entity with model %d\n", modelnum);
return qfalse;
} //end if
//if the top of the plat is below the reachability start point
if (origin[2] + maxs[2] < reach->start[2]) return qtrue;
return qfalse;
} //end of the function MoverDown
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
void BotSetBrushModelTypes(void)
{
int ent, modelnum;
char classname[MAX_EPAIRKEY], model[MAX_EPAIRKEY];
Com_Memset(modeltypes, 0, MAX_MODELS * sizeof(int));
//
for (ent = AAS_NextBSPEntity(0); ent; ent = AAS_NextBSPEntity(ent))
{
if (!AAS_ValueForBSPEpairKey(ent, "classname", classname, MAX_EPAIRKEY)) continue;
if (!AAS_ValueForBSPEpairKey(ent, "model", model, MAX_EPAIRKEY)) continue;
if (model[0]) modelnum = atoi(model+1);
else modelnum = 0;
if (modelnum < 0 || modelnum > MAX_MODELS)
{
botimport.Print(PRT_MESSAGE, "entity %s model number out of range\n", classname);
continue;
} //end if
if (!Q_stricmp(classname, "func_bobbing"))
modeltypes[modelnum] = MODELTYPE_FUNC_BOB;
else if (!Q_stricmp(classname, "func_plat"))
modeltypes[modelnum] = MODELTYPE_FUNC_PLAT;
else if (!Q_stricmp(classname, "func_door"))
modeltypes[modelnum] = MODELTYPE_FUNC_DOOR;
else if (!Q_stricmp(classname, "func_static"))
modeltypes[modelnum] = MODELTYPE_FUNC_STATIC;
} //end for
} //end of the function BotSetBrushModelTypes
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotOnTopOfEntity(bot_movestate_t *ms)
{
vec3_t mins, maxs, end, up = {0, 0, 1};
bsp_trace_t trace;
AAS_PresenceTypeBoundingBox(ms->presencetype, mins, maxs);
VectorMA(ms->origin, -3, up, end);
trace = AAS_Trace(ms->origin, mins, maxs, end, ms->entitynum, CONTENTS_SOLID|CONTENTS_PLAYERCLIP);
if (!trace.startsolid && (trace.ent != ENTITYNUM_WORLD && trace.ent != ENTITYNUM_NONE) )
{
return trace.ent;
} //end if
return -1;
} //end of the function BotOnTopOfEntity
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotValidTravel(vec3_t origin, aas_reachability_t *reach, int travelflags)
{
//if the reachability uses an unwanted travel type
if (AAS_TravelFlagForType(reach->traveltype) & ~travelflags) return qfalse;
//don't go into areas with bad travel types
if (AAS_AreaContentsTravelFlags(reach->areanum) & ~travelflags) return qfalse;
return qtrue;
} //end of the function BotValidTravel
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotAddToAvoidReach(bot_movestate_t *ms, int number, float avoidtime)
{
int i;
for (i = 0; i < MAX_AVOIDREACH; i++)
{
if (ms->avoidreach[i] == number)
{
if (ms->avoidreachtimes[i] > AAS_Time()) ms->avoidreachtries[i]++;
else ms->avoidreachtries[i] = 1;
ms->avoidreachtimes[i] = AAS_Time() + avoidtime;
return;
} //end if
} //end for
//add the reachability to the reachabilities to avoid for a while
for (i = 0; i < MAX_AVOIDREACH; i++)
{
if (ms->avoidreachtimes[i] < AAS_Time())
{
ms->avoidreach[i] = number;
ms->avoidreachtimes[i] = AAS_Time() + avoidtime;
ms->avoidreachtries[i] = 1;
return;
} //end if
} //end for
} //end of the function BotAddToAvoidReach
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float DistanceFromLineSquared(vec3_t p, vec3_t lp1, vec3_t lp2)
{
vec3_t proj, dir;
int j;
AAS_ProjectPointOntoVector(p, lp1, lp2, proj);
for (j = 0; j < 3; j++)
if ((proj[j] > lp1[j] && proj[j] > lp2[j]) ||
(proj[j] < lp1[j] && proj[j] < lp2[j]))
break;
if (j < 3) {
if (fabs(proj[j] - lp1[j]) < fabs(proj[j] - lp2[j]))
VectorSubtract(p, lp1, dir);
else
VectorSubtract(p, lp2, dir);
return VectorLengthSquared(dir);
}
VectorSubtract(p, proj, dir);
return VectorLengthSquared(dir);
} //end of the function DistanceFromLineSquared
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float VectorDistanceSquared(vec3_t p1, vec3_t p2)
{
vec3_t dir;
VectorSubtract(p2, p1, dir);
return VectorLengthSquared(dir);
} //end of the function VectorDistanceSquared
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotAvoidSpots(vec3_t origin, aas_reachability_t *reach, bot_avoidspot_t *avoidspots, int numavoidspots)
{
int checkbetween, i, type;
float squareddist, squaredradius;
switch(reach->traveltype & TRAVELTYPE_MASK)
{
case TRAVEL_WALK: checkbetween = qtrue; break;
case TRAVEL_CROUCH: checkbetween = qtrue; break;
case TRAVEL_BARRIERJUMP: checkbetween = qtrue; break;
case TRAVEL_LADDER: checkbetween = qtrue; break;
case TRAVEL_WALKOFFLEDGE: checkbetween = qfalse; break;
case TRAVEL_JUMP: checkbetween = qfalse; break;
case TRAVEL_SWIM: checkbetween = qtrue; break;
case TRAVEL_WATERJUMP: checkbetween = qtrue; break;
case TRAVEL_TELEPORT: checkbetween = qfalse; break;
case TRAVEL_ELEVATOR: checkbetween = qfalse; break;
case TRAVEL_GRAPPLEHOOK: checkbetween = qfalse; break;
case TRAVEL_ROCKETJUMP: checkbetween = qfalse; break;
case TRAVEL_BFGJUMP: checkbetween = qfalse; break;
case TRAVEL_JUMPPAD: checkbetween = qfalse; break;
case TRAVEL_FUNCBOB: checkbetween = qfalse; break;
default: checkbetween = qtrue; break;
} //end switch
type = AVOID_CLEAR;
for (i = 0; i < numavoidspots; i++)
{
squaredradius = Square(avoidspots[i].radius);
squareddist = DistanceFromLineSquared(avoidspots[i].origin, origin, reach->start);
// if moving towards the avoid spot
if (squareddist < squaredradius &&
VectorDistanceSquared(avoidspots[i].origin, origin) > squareddist)
{
type = avoidspots[i].type;
} //end if
else if (checkbetween) {
squareddist = DistanceFromLineSquared(avoidspots[i].origin, reach->start, reach->end);
// if moving towards the avoid spot
if (squareddist < squaredradius &&
VectorDistanceSquared(avoidspots[i].origin, reach->start) > squareddist)
{
type = avoidspots[i].type;
} //end if
} //end if
else
{
VectorDistanceSquared(avoidspots[i].origin, reach->end);
// if the reachability leads closer to the avoid spot
if (squareddist < squaredradius &&
VectorDistanceSquared(avoidspots[i].origin, reach->start) > squareddist)
{
type = avoidspots[i].type;
} //end if
} //end else
if (type == AVOID_ALWAYS)
return type;
} //end for
return type;
} //end of the function BotAvoidSpots
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotAddAvoidSpot(int movestate, vec3_t origin, float radius, int type)
{
bot_movestate_t *ms;
ms = BotMoveStateFromHandle(movestate);
if (!ms) return;
if (type == AVOID_CLEAR)
{
ms->numavoidspots = 0;
return;
} //end if
if (ms->numavoidspots >= MAX_AVOIDSPOTS)
return;
VectorCopy(origin, ms->avoidspots[ms->numavoidspots].origin);
ms->avoidspots[ms->numavoidspots].radius = radius;
ms->avoidspots[ms->numavoidspots].type = type;
ms->numavoidspots++;
} //end of the function BotAddAvoidSpot
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotGetReachabilityToGoal(vec3_t origin, int areanum,
int lastgoalareanum, int lastareanum,
int *avoidreach, float *avoidreachtimes, int *avoidreachtries,
bot_goal_t *goal, int travelflags, int movetravelflags,
struct bot_avoidspot_s *avoidspots, int numavoidspots, int *flags)
{
int i, t, besttime, bestreachnum, reachnum;
aas_reachability_t reach;
//if not in a valid area
if (!areanum) return 0;
//
if (AAS_AreaDoNotEnter(areanum) || AAS_AreaDoNotEnter(goal->areanum))
{
travelflags |= TFL_DONOTENTER;
movetravelflags |= TFL_DONOTENTER;
} //end if
//use the routing to find the next area to go to
besttime = 0;
bestreachnum = 0;
//
for (reachnum = AAS_NextAreaReachability(areanum, 0); reachnum;
reachnum = AAS_NextAreaReachability(areanum, reachnum))
{
#ifdef AVOIDREACH
//check if it isn't an reachability to avoid
for (i = 0; i < MAX_AVOIDREACH; i++)
{
if (avoidreach[i] == reachnum && avoidreachtimes[i] >= AAS_Time()) break;
} //end for
if (i != MAX_AVOIDREACH && avoidreachtries[i] > AVOIDREACH_TRIES)
{
#ifdef DEBUG
if (bot_developer)
{
botimport.Print(PRT_MESSAGE, "avoiding reachability %d\n", avoidreach[i]);
} //end if
#endif //DEBUG
continue;
} //end if
#endif //AVOIDREACH
//get the reachability from the number
AAS_ReachabilityFromNum(reachnum, &reach);
//NOTE: do not go back to the previous area if the goal didn't change
//NOTE: is this actually avoidance of local routing minima between two areas???
if (lastgoalareanum == goal->areanum && reach.areanum == lastareanum) continue;
//if (AAS_AreaContentsTravelFlags(reach.areanum) & ~travelflags) continue;
//if the travel isn't valid
if (!BotValidTravel(origin, &reach, movetravelflags)) continue;
//get the travel time
t = AAS_AreaTravelTimeToGoalArea(reach.areanum, reach.end, goal->areanum, travelflags);
//if the goal area isn't reachable from the reachable area
if (!t) continue;
//if the bot should not use this reachability to avoid bad spots
if (BotAvoidSpots(origin, &reach, avoidspots, numavoidspots)) {
if (flags) {
*flags |= MOVERESULT_BLOCKEDBYAVOIDSPOT;
}
continue;
}
//add the travel time towards the area
t += reach.traveltime;// + AAS_AreaTravelTime(areanum, origin, reach.start);
//if the travel time is better than the ones already found
if (!besttime || t < besttime)
{
besttime = t;
bestreachnum = reachnum;
} //end if
} //end for
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -