mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-28 04:51:42 +00:00
Improve bot traversal for the prediction
HatesSector was returning false positive for intangible FOFs, making them play really poorly in Desert Palace
This commit is contained in:
parent
ee5e96b65e
commit
bfa3c40033
3 changed files with 45 additions and 45 deletions
25
src/k_bot.c
25
src/k_bot.c
|
|
@ -685,11 +685,23 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
||||||
{
|
{
|
||||||
wp = (waypoint_t *)pathtofinish.array[i].nodedata;
|
wp = (waypoint_t *)pathtofinish.array[i].nodedata;
|
||||||
|
|
||||||
if (i > 0)
|
if (i == 0)
|
||||||
|
{
|
||||||
|
prevwpmobj = player->mo;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
prevwpmobj = ((waypoint_t *)pathtofinish.array[ i - 1 ].nodedata)->mobj;
|
prevwpmobj = ((waypoint_t *)pathtofinish.array[ i - 1 ].nodedata)->mobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (P_TraceBotTraversal(player->mo, wp->mobj) == false)
|
||||||
|
{
|
||||||
|
// If we can't get a direct path to this waypoint, stop predicting.
|
||||||
|
distanceleft = 0;
|
||||||
|
radreduce = FRACUNIT >> 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
angletonext = R_PointToAngle2(prevwpmobj->x, prevwpmobj->y, wp->mobj->x, wp->mobj->y);
|
angletonext = R_PointToAngle2(prevwpmobj->x, prevwpmobj->y, wp->mobj->x, wp->mobj->y);
|
||||||
disttonext = P_AproxDistance(prevwpmobj->x - wp->mobj->x, prevwpmobj->y - wp->mobj->y) / FRACUNIT;
|
disttonext = P_AproxDistance(prevwpmobj->x - wp->mobj->x, prevwpmobj->y - wp->mobj->y) / FRACUNIT;
|
||||||
|
|
||||||
|
|
@ -698,13 +710,6 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
||||||
smallestradius = wp->mobj->radius;
|
smallestradius = wp->mobj->radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (P_TraceBotTraversal(player->mo, wp->mobj) == false)
|
|
||||||
{
|
|
||||||
// If we can't get a direct path to this waypoint, predict less.
|
|
||||||
disttonext <<= 2;
|
|
||||||
radreduce = FRACUNIT >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
distanceleft -= disttonext;
|
distanceleft -= disttonext;
|
||||||
|
|
||||||
if (distanceleft <= 0)
|
if (distanceleft <= 0)
|
||||||
|
|
@ -733,8 +738,8 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
|
||||||
if (distanceleft > 0)
|
if (distanceleft > 0)
|
||||||
{
|
{
|
||||||
// Scaled with the leftover anglemul!
|
// Scaled with the leftover anglemul!
|
||||||
predict->x += P_ReturnThrustX(NULL, angletonext, distanceleft * FRACUNIT);
|
predict->x += P_ReturnThrustX(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT);
|
||||||
predict->y += P_ReturnThrustY(NULL, angletonext, distanceleft * FRACUNIT);
|
predict->y += P_ReturnThrustY(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return predict;
|
return predict;
|
||||||
|
|
|
||||||
|
|
@ -172,26 +172,24 @@ static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec)
|
||||||
boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y)
|
boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y)
|
||||||
{
|
{
|
||||||
const boolean flip = (player->mo->eflags & MFE_VERTICALFLIP);
|
const boolean flip = (player->mo->eflags & MFE_VERTICALFLIP);
|
||||||
INT32 specialflag = 0;
|
|
||||||
fixed_t highestfloor = INT32_MAX;
|
fixed_t highestfloor = INT32_MAX;
|
||||||
sector_t *bestsector = NULL;
|
sector_t *bestsector = NULL;
|
||||||
ffloor_t *rover;
|
ffloor_t *rover;
|
||||||
|
|
||||||
|
// TODO: Properly support SF_FLIPSPECIAL_FLOOR / SF_FLIPSPECIAL_CEILING.
|
||||||
|
// An earlier attempt at it caused lots of false positives and other weird
|
||||||
|
// quirks with intangible FOFs.
|
||||||
|
|
||||||
if (flip == true)
|
if (flip == true)
|
||||||
{
|
{
|
||||||
specialflag = SF_FLIPSPECIAL_CEILING;
|
|
||||||
highestfloor = P_GetZAt(sec->c_slope, x, y, sec->ceilingheight);
|
highestfloor = P_GetZAt(sec->c_slope, x, y, sec->ceilingheight);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
specialflag = SF_FLIPSPECIAL_FLOOR;
|
|
||||||
highestfloor = P_GetZAt(sec->f_slope, x, y, sec->floorheight);
|
highestfloor = P_GetZAt(sec->f_slope, x, y, sec->floorheight);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sec->flags & specialflag)
|
bestsector = sec;
|
||||||
{
|
|
||||||
bestsector = sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||||
{
|
{
|
||||||
|
|
@ -209,15 +207,13 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t
|
||||||
if (!(rover->flags & FF_BLOCKPLAYER))
|
if (!(rover->flags & FF_BLOCKPLAYER))
|
||||||
{
|
{
|
||||||
if ((top >= player->mo->z) && (bottom <= player->mo->z + player->mo->height)
|
if ((top >= player->mo->z) && (bottom <= player->mo->z + player->mo->height)
|
||||||
&& K_BotHatesThisSectorsSpecial(player, rover->master->frontsector))
|
&& K_BotHatesThisSectorsSpecial(player, rover->master->frontsector))
|
||||||
{
|
{
|
||||||
// Bad intangible sector at our height, so we DEFINITELY want to avoid
|
// Bad intangible sector at our height, so we DEFINITELY want to avoid
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((rover->flags & FF_BLOCKPLAYER) && !(rover->master->frontsector->flags & specialflag))
|
// Ignore them, we want the one below it.
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,7 +221,7 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t
|
||||||
if (flip == true)
|
if (flip == true)
|
||||||
{
|
{
|
||||||
if (bottom < highestfloor
|
if (bottom < highestfloor
|
||||||
&& bottom >= player->mo->z + player->mo->height)
|
&& bottom >= player->mo->z + player->mo->height)
|
||||||
{
|
{
|
||||||
bestsector = rover->master->frontsector;
|
bestsector = rover->master->frontsector;
|
||||||
highestfloor = bottom;
|
highestfloor = bottom;
|
||||||
|
|
@ -234,7 +230,7 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (top > highestfloor
|
if (top > highestfloor
|
||||||
&& top <= player->mo->z)
|
&& top <= player->mo->z)
|
||||||
{
|
{
|
||||||
bestsector = rover->master->frontsector;
|
bestsector = rover->master->frontsector;
|
||||||
highestfloor = top;
|
highestfloor = top;
|
||||||
|
|
|
||||||
|
|
@ -516,6 +516,7 @@ typedef struct {
|
||||||
divline_t strace; // from t1 to t2
|
divline_t strace; // from t1 to t2
|
||||||
fixed_t bbox[4];
|
fixed_t bbox[4];
|
||||||
mobj_t *compareThing;
|
mobj_t *compareThing;
|
||||||
|
boolean alreadyHates;
|
||||||
} traceblocking_t;
|
} traceblocking_t;
|
||||||
|
|
||||||
static boolean P_CrossBlockingSubsector(size_t num, register traceblocking_t *tb)
|
static boolean P_CrossBlockingSubsector(size_t num, register traceblocking_t *tb)
|
||||||
|
|
@ -664,6 +665,7 @@ boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2)
|
||||||
tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y;
|
tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y;
|
||||||
|
|
||||||
tb.compareThing = t1;
|
tb.compareThing = t1;
|
||||||
|
tb.alreadyHates = false;
|
||||||
|
|
||||||
// the head node is the last node output
|
// the head node is the last node output
|
||||||
return P_CrossBSPNodeBlocking((INT32)numnodes - 1, &tb);
|
return P_CrossBSPNodeBlocking((INT32)numnodes - 1, &tb);
|
||||||
|
|
@ -760,31 +762,17 @@ static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tb->compareThing->player != NULL)
|
if (tb->compareThing->player != NULL && tb->alreadyHates == false)
|
||||||
{
|
{
|
||||||
// Treat damage sectors like walls
|
// Treat damage sectors like walls, if you're not already in a bad sector.
|
||||||
boolean alreadyHates = K_BotHatesThisSector(
|
vertex_t pos;
|
||||||
tb->compareThing->player, tb->compareThing->subsector->sector,
|
P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos);
|
||||||
tb->compareThing->x, tb->compareThing->y
|
|
||||||
);
|
|
||||||
|
|
||||||
if (alreadyHates == false)
|
if (K_BotHatesThisSector(tb->compareThing->player, line->frontsector, pos.x, pos.y)
|
||||||
|
|| K_BotHatesThisSector(tb->compareThing->player, line->backsector, pos.x, pos.y))
|
||||||
{
|
{
|
||||||
INT32 lineside = 0;
|
// This line does not block us, but we don't want to be in it.
|
||||||
vertex_t pos;
|
return false;
|
||||||
|
|
||||||
P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos);
|
|
||||||
lineside = P_PointOnLineSide(tb->compareThing->x, tb->compareThing->y, line);
|
|
||||||
|
|
||||||
if (K_BotHatesThisSector(
|
|
||||||
tb->compareThing->player,
|
|
||||||
((lineside == 1) ? line->frontsector : line->backsector),
|
|
||||||
pos.x, pos.y
|
|
||||||
))
|
|
||||||
{
|
|
||||||
// This line does not block us, but we don't want to be in it.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -864,6 +852,17 @@ boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2)
|
||||||
tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y;
|
tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y;
|
||||||
|
|
||||||
tb.compareThing = t1;
|
tb.compareThing = t1;
|
||||||
|
if (t1->player != NULL)
|
||||||
|
{
|
||||||
|
tb.alreadyHates = K_BotHatesThisSector(
|
||||||
|
t1->player, t1->subsector->sector,
|
||||||
|
t1->x, t1->y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tb.alreadyHates = false;
|
||||||
|
}
|
||||||
|
|
||||||
// the head node is the last node output
|
// the head node is the last node output
|
||||||
return P_CrossBSPNodeBotTraversal((INT32)numnodes - 1, &tb);
|
return P_CrossBSPNodeBotTraversal((INT32)numnodes - 1, &tb);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue