📄 be_ai_move.c
字号:
//
return bestreachnum;
} //end of the function BotGetReachabilityToGoal
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotAddToTarget(vec3_t start, vec3_t end, float maxdist, float *dist, vec3_t target)
{
vec3_t dir;
float curdist;
VectorSubtract(end, start, dir);
curdist = VectorNormalize(dir);
if (*dist + curdist < maxdist)
{
VectorCopy(end, target);
*dist += curdist;
return qfalse;
} //end if
else
{
VectorMA(start, maxdist - *dist, dir, target);
*dist = maxdist;
return qtrue;
} //end else
} //end of the function BotAddToTarget
int BotMovementViewTarget(int movestate, bot_goal_t *goal, int travelflags, float lookahead, vec3_t target)
{
aas_reachability_t reach;
int reachnum, lastareanum;
bot_movestate_t *ms;
vec3_t end;
float dist;
ms = BotMoveStateFromHandle(movestate);
if (!ms) return qfalse;
reachnum = 0;
//if the bot has no goal or no last reachability
if (!ms->lastreachnum || !goal) return qfalse;
reachnum = ms->lastreachnum;
VectorCopy(ms->origin, end);
lastareanum = ms->lastareanum;
dist = 0;
while(reachnum && dist < lookahead)
{
AAS_ReachabilityFromNum(reachnum, &reach);
if (BotAddToTarget(end, reach.start, lookahead, &dist, target)) return qtrue;
//never look beyond teleporters
if ((reach.traveltype & TRAVELTYPE_MASK) == TRAVEL_TELEPORT) return qtrue;
//never look beyond the weapon jump point
if ((reach.traveltype & TRAVELTYPE_MASK) == TRAVEL_ROCKETJUMP) return qtrue;
if ((reach.traveltype & TRAVELTYPE_MASK) == TRAVEL_BFGJUMP) return qtrue;
//don't add jump pad distances
if ((reach.traveltype & TRAVELTYPE_MASK) != TRAVEL_JUMPPAD &&
(reach.traveltype & TRAVELTYPE_MASK) != TRAVEL_ELEVATOR &&
(reach.traveltype & TRAVELTYPE_MASK) != TRAVEL_FUNCBOB)
{
if (BotAddToTarget(reach.start, reach.end, lookahead, &dist, target)) return qtrue;
} //end if
reachnum = BotGetReachabilityToGoal(reach.end, reach.areanum,
ms->lastgoalareanum, lastareanum,
ms->avoidreach, ms->avoidreachtimes, ms->avoidreachtries,
goal, travelflags, travelflags, NULL, 0, NULL);
VectorCopy(reach.end, end);
lastareanum = reach.areanum;
if (lastareanum == goal->areanum)
{
BotAddToTarget(reach.end, goal->origin, lookahead, &dist, target);
return qtrue;
} //end if
} //end while
//
return qfalse;
} //end of the function BotMovementViewTarget
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotVisible(int ent, vec3_t eye, vec3_t target)
{
bsp_trace_t trace;
trace = AAS_Trace(eye, NULL, NULL, target, ent, CONTENTS_SOLID|CONTENTS_PLAYERCLIP);
if (trace.fraction >= 1) return qtrue;
return qfalse;
} //end of the function BotVisible
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotPredictVisiblePosition(vec3_t origin, int areanum, bot_goal_t *goal, int travelflags, vec3_t target)
{
aas_reachability_t reach;
int reachnum, lastgoalareanum, lastareanum, i;
int avoidreach[MAX_AVOIDREACH];
float avoidreachtimes[MAX_AVOIDREACH];
int avoidreachtries[MAX_AVOIDREACH];
vec3_t end;
//if the bot has no goal or no last reachability
if (!goal) return qfalse;
//if the areanum is not valid
if (!areanum) return qfalse;
//if the goal areanum is not valid
if (!goal->areanum) return qfalse;
Com_Memset(avoidreach, 0, MAX_AVOIDREACH * sizeof(int));
lastgoalareanum = goal->areanum;
lastareanum = areanum;
VectorCopy(origin, end);
//only do 20 hops
for (i = 0; i < 20 && (areanum != goal->areanum); i++)
{
//
reachnum = BotGetReachabilityToGoal(end, areanum,
lastgoalareanum, lastareanum,
avoidreach, avoidreachtimes, avoidreachtries,
goal, travelflags, travelflags, NULL, 0, NULL);
if (!reachnum) return qfalse;
AAS_ReachabilityFromNum(reachnum, &reach);
//
if (BotVisible(goal->entitynum, goal->origin, reach.start))
{
VectorCopy(reach.start, target);
return qtrue;
} //end if
//
if (BotVisible(goal->entitynum, goal->origin, reach.end))
{
VectorCopy(reach.end, target);
return qtrue;
} //end if
//
if (reach.areanum == goal->areanum)
{
VectorCopy(reach.end, target);
return qtrue;
} //end if
//
lastareanum = areanum;
areanum = reach.areanum;
VectorCopy(reach.end, end);
//
} //end while
//
return qfalse;
} //end of the function BotPredictVisiblePosition
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void MoverBottomCenter(aas_reachability_t *reach, vec3_t bottomcenter)
{
int modelnum;
vec3_t mins, maxs, origin, mids;
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);
} //end if
//get a point just above the plat in the bottom position
VectorAdd(mins, maxs, mids);
VectorMA(origin, 0.5, mids, bottomcenter);
bottomcenter[2] = reach->start[2];
} //end of the function MoverBottomCenter
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
float BotGapDistance(vec3_t origin, vec3_t hordir, int entnum)
{
float dist, startz;
vec3_t start, end;
aas_trace_t trace;
//do gap checking
startz = origin[2];
//this enables walking down stairs more fluidly
{
VectorCopy(origin, start);
VectorCopy(origin, end);
end[2] -= 60;
trace = AAS_TraceClientBBox(start, end, PRESENCE_CROUCH, entnum);
if (trace.fraction >= 1) return 1;
startz = trace.endpos[2] + 1;
}
//
for (dist = 8; dist <= 100; dist += 8)
{
VectorMA(origin, dist, hordir, start);
start[2] = startz + 24;
VectorCopy(start, end);
end[2] -= 48 + sv_maxbarrier->value;
trace = AAS_TraceClientBBox(start, end, PRESENCE_CROUCH, entnum);
//if solid is found the bot can't walk any further and fall into a gap
if (!trace.startsolid)
{
//if it is a gap
if (trace.endpos[2] < startz - sv_maxstep->value - 8)
{
VectorCopy(trace.endpos, end);
end[2] -= 20;
if (AAS_PointContents(end) & CONTENTS_WATER) break;
//if a gap is found slow down
//botimport.Print(PRT_MESSAGE, "gap at %f\n", dist);
return dist;
} //end if
startz = trace.endpos[2];
} //end if
} //end for
return 0;
} //end of the function BotGapDistance
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotCheckBarrierJump(bot_movestate_t *ms, vec3_t dir, float speed)
{
vec3_t start, hordir, end;
aas_trace_t trace;
VectorCopy(ms->origin, end);
end[2] += sv_maxbarrier->value;
//trace right up
trace = AAS_TraceClientBBox(ms->origin, end, PRESENCE_NORMAL, ms->entitynum);
//this shouldn't happen... but we check anyway
if (trace.startsolid) return qfalse;
//if very low ceiling it isn't possible to jump up to a barrier
if (trace.endpos[2] - ms->origin[2] < sv_maxstep->value) return qfalse;
//
hordir[0] = dir[0];
hordir[1] = dir[1];
hordir[2] = 0;
VectorNormalize(hordir);
VectorMA(ms->origin, ms->thinktime * speed * 0.5, hordir, end);
VectorCopy(trace.endpos, start);
end[2] = trace.endpos[2];
//trace from previous trace end pos horizontally in the move direction
trace = AAS_TraceClientBBox(start, end, PRESENCE_NORMAL, ms->entitynum);
//again this shouldn't happen
if (trace.startsolid) return qfalse;
//
VectorCopy(trace.endpos, start);
VectorCopy(trace.endpos, end);
end[2] = ms->origin[2];
//trace down from the previous trace end pos
trace = AAS_TraceClientBBox(start, end, PRESENCE_NORMAL, ms->entitynum);
//if solid
if (trace.startsolid) return qfalse;
//if no obstacle at all
if (trace.fraction >= 1.0) return qfalse;
//if less than the maximum step height
if (trace.endpos[2] - ms->origin[2] < sv_maxstep->value) return qfalse;
//
EA_Jump(ms->client);
EA_Move(ms->client, hordir, speed);
ms->moveflags |= MFL_BARRIERJUMP;
//there is a barrier
return qtrue;
} //end of the function BotCheckBarrierJump
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotSwimInDirection(bot_movestate_t *ms, vec3_t dir, float speed, int type)
{
vec3_t normdir;
VectorCopy(dir, normdir);
VectorNormalize(normdir);
EA_Move(ms->client, normdir, speed);
return qtrue;
} //end of the function BotSwimInDirection
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotWalkInDirection(bot_movestate_t *ms, vec3_t dir, float speed, int type)
{
vec3_t hordir, cmdmove, velocity, tmpdir, origin;
int presencetype, maxframes, cmdframes, stopevent;
aas_clientmove_t move;
float dist;
if (AAS_OnGround(ms->origin, ms->presencetype, ms->entitynum)) ms->moveflags |= MFL_ONGROUND;
//if the bot is on the ground
if (ms->moveflags & MFL_ONGROUND)
{
//if there is a barrier the bot can jump on
if (BotCheckBarrierJump(ms, dir, speed)) return qtrue;
//remove barrier jump flag
ms->moveflags &= ~MFL_BARRIERJUMP;
//get the presence type for the movement
if ((type & MOVE_CROUCH) && !(type & MOVE_JUMP)) presencetype = PRESENCE_CROUCH;
else presencetype = PRESENCE_NORMAL;
//horizontal direction
hordir[0] = dir[0];
hordir[1] = dir[1];
hordir[2] = 0;
VectorNormalize(hordir);
//if the bot is not supposed to jump
if (!(type & MOVE_JUMP))
{
//if there is a gap, try to jump over it
if (BotGapDistance(ms->origin, hordir, ms->entitynum) > 0) type |= MOVE_JUMP;
} //end if
//get command movement
VectorScale(hordir, speed, cmdmove);
VectorCopy(ms->velocity, velocity);
//
if (type & MOVE_JUMP)
{
//botimport.Print(PRT_MESSAGE, "trying jump\n");
cmdmove[2] = 400;
maxframes = PREDICTIONTIME_JUMP / 0.1;
cmdframes = 1;
stopevent = SE_HITGROUND|SE_HITGROUNDDAMAGE|
SE_ENTERWATER|SE_ENTERSLIME|SE_ENTERLAVA;
} //end if
else
{
maxframes = 2;
cmdframes = 2;
stopevent = SE_HITGROUNDDAMAGE|
SE_ENTERWATER|SE_ENTERSLIME|SE_ENTERLAVA;
} //end else
//AAS_ClearShownDebugLines();
//
VectorCopy(ms->origin, origin);
origin[2] += 0.5;
AAS_PredictClientMovement(&move, ms->entitynum, origin, presencetype, qtrue,
velocity, cmdmove, cmdframes, maxframes, 0.1f,
stopevent, 0, qfalse);//qtrue);
//if prediction time wasn't enough to fully predict the movement
if (move.frames >= maxframes && (type & MOVE_JUMP))
{
//botimport.Print(PRT_MESSAGE, "client %d: max prediction frames\n", ms->client);
return qfalse;
} //end if
//don't enter slime or lava and don't fall from too high
if (move.stopevent & (SE_ENTERSLIME|SE_ENTERLAVA|SE_HITGROUNDDAMAGE))
{
//botimport.Print(PRT_MESSAGE, "client %d: would be hurt ", ms->client);
//if (move.stopevent & SE_ENTERSLIME) botimport.Print(PRT_MESSAGE, "slime\n");
//if (move.stopevent & SE_ENTERLAVA) botimport.Print(PRT_MESSAGE, "lava\n");
//if (move.stopevent & SE_HITGROUNDDAMAGE) botimport.Print(PRT_MESSAGE, "hitground\n");
return qfalse;
} //end if
//if ground was hit
if (move.stopevent & SE_HITGROUND)
{
//check for nearby gap
VectorNormalize2(move.velocity, tmpdir);
dist = BotGapDistance(move.endpos, tmpdir, ms->entitynum);
if (dist > 0) return qfalse;
//
dist = BotGapDistance(move.endpos, hordir, ms->entitynum);
if (dist > 0) return qfalse;
} //end if
//get horizontal movement
tmpdir[0] = move.endpos[0] - ms->origin[0];
tmpdir[1] = move.endpos[1] - ms->origin[1];
tmpdir[2] = 0;
//
//AAS_DrawCross(move.endpos, 4, LINECOLOR_BLUE);
//the bot is blocked by something
if (VectorLength(tmpdir) < speed * ms->thinktime * 0.5) return qfalse;
//perform the movement
if (type & MOVE_JUMP) EA_Jump(ms->client);
if (type & MOVE_CROUCH) EA_Crouch(ms->client);
EA_Move(ms->client, hordir, speed);
//movement was succesfull
return qtrue;
} //end if
else
{
if (ms->moveflags & MFL_BARRIERJUMP)
{
//if near the top or going down
if (ms->velocity[2] < 50)
{
EA_Move(ms->client, dir, speed);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -