Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions src/botlib/ai_move/bot_move.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,31 @@ static float VectorNormalizeTo(const vec3_t src, vec3_t dst)
return VectorNormalizeInline(dst);
}

/*
=============
BotMove_VisiblePosition

Checks if a point is visible from a viewpoint.
=============
*/
static bool BotMove_VisiblePosition(int ent, const vec3_t eye, const vec3_t target)
{
if (eye == NULL || target == NULL)
{
return false;
}

vec3_t start;
vec3_t end;
VectorCopy(eye, start);
VectorCopy(target, end);

vec3_t mins = {0.0f, 0.0f, 0.0f};
vec3_t maxs = {0.0f, 0.0f, 0.0f};
bsp_trace_t trace = Q2_Trace(start, mins, maxs, end, ent, CONTENTS_SOLID | CONTENTS_PLAYERCLIP);
return trace.fraction >= 1.0f;
}

static int BotMove_FindAreaForPoint(const vec3_t origin)
{
if (!aasworld.loaded || aasworld.areas == NULL || aasworld.numAreas <= 0)
Expand Down Expand Up @@ -1511,3 +1536,59 @@ void BotMove_ResetAvoidReach(int movestate)
memset(ms->avoidreachtries, 0, sizeof(ms->avoidreachtries));
}

/*
=============
BotPredictVisiblePosition

Predicts a reachability point that remains visible from the goal.
=============
*/
int BotPredictVisiblePosition(vec3_t origin, int areanum, bot_goal_t *goal, int travelflags, vec3_t target)
{
if (goal == NULL || target == NULL)
{
return false;
}

if (!areanum || !goal->areanum)
{
return false;
}

bot_movestate_t temp_state;
memset(&temp_state, 0, sizeof(temp_state));

for (int i = 0; i < 20 && areanum != goal->areanum; ++i)
{
aas_reachability_t reach;
temp_state.areanum = areanum;

int reachnum = BotGetReachabilityToGoal(&temp_state, goal, travelflags, &reach, NULL);
if (!reachnum)
{
return false;
}

if (BotMove_VisiblePosition(goal->entitynum, goal->origin, reach.start))
{
VectorCopy(reach.start, target);
return true;
}

if (BotMove_VisiblePosition(goal->entitynum, goal->origin, reach.end))
{
VectorCopy(reach.end, target);
return true;
}

if (reach.areanum == goal->areanum)
{
VectorCopy(reach.end, target);
return true;
}

areanum = reach.areanum;
}

return false;
}
3 changes: 2 additions & 1 deletion src/botlib/ai_move/bot_move.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ int BotMoveInDirection(int movestate, const vec3_t dir, float speed, int type);

void BotMove_ResetAvoidReach(int movestate);

int BotPredictVisiblePosition(vec3_t origin, int areanum, bot_goal_t *goal, int travelflags, vec3_t target);

void AI_MoveFrame(bot_moveresult_t *result,
int movestate,
const bot_goal_t *goal,
Expand All @@ -176,4 +178,3 @@ bot_moveresult_t BotTravel_Grapple(bot_movestate_t *ms, const struct aas_reachab
#ifdef __cplusplus
} /* extern "C" */
#endif

23 changes: 22 additions & 1 deletion src/botlib/interface/bot_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -3170,6 +3170,27 @@ static void BotInterface_BotResetAvoidReach(int movestate)
BotMove_ResetAvoidReach(movestate);
}

/*
=============
BotInterface_BotPredictVisiblePosition

Routes the visibility prediction request to the bot movement module.
=============
*/
static int BotInterface_BotPredictVisiblePosition(vec3_t origin,
int areanum,
bot_goal_t *goal,
int travelflags,
vec3_t target)
{
if (!BotInterface_EnsureLibraryReady("BotPredictVisiblePosition"))
{
return 0;
}

return BotPredictVisiblePosition(origin, areanum, goal, travelflags, target);
}

static int BotInterface_BotAllocWeaponState(void)
{
if (!BotInterface_EnsureLibraryReady("BotAllocWeaponState"))
Expand Down Expand Up @@ -3454,6 +3475,7 @@ GLADIATOR_API bot_export_t *GetBotAPI(bot_import_t *import)
exportTable.BotMoveToGoal = BotInterface_BotMoveToGoal;
exportTable.BotMoveInDirection = BotInterface_BotMoveInDirection;
exportTable.BotResetAvoidReach = BotInterface_BotResetAvoidReach;
exportTable.BotPredictVisiblePosition = BotInterface_BotPredictVisiblePosition;
exportTable.BotLoadCharacter = BotLoadCharacter;
exportTable.BotFreeCharacter = BotFreeCharacter;
exportTable.BotLoadCharacterSkill = BotLoadCharacterSkill;
Expand Down Expand Up @@ -3485,4 +3507,3 @@ GLADIATOR_API bot_export_t *GetBotAPI(bot_import_t *import)

return &exportTable;
}

1 change: 1 addition & 0 deletions src/q2bridge/botlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ typedef struct bot_export_s {
void (*BotMoveToGoal)(bot_moveresult_t *result, int movestate, const bot_goal_t *goal, int travelflags);
int (*BotMoveInDirection)(int movestate, const vec3_t dir, float speed, int type);
void (*BotResetAvoidReach)(int movestate);
int (*BotPredictVisiblePosition)(vec3_t origin, int areanum, bot_goal_t *goal, int travelflags, vec3_t target);
int (*BotLoadCharacter)(const char *character_file, float skill);
void (*BotFreeCharacter)(int handle);
int (*BotLoadCharacterSkill)(const char *character_file, float skill);
Expand Down
Loading