Better steering

- If they're already turning in one direction, they are more likely to steer in that direction for objects
- Bots have to want to turn in 1 direction for a few frames in a row before it'll let them

Prevents twitching & makes them less indecisive in general
This commit is contained in:
Sally Coolatta 2020-05-24 11:12:38 -04:00
parent ca7154f521
commit edfc14c506
6 changed files with 95 additions and 41 deletions

View file

@ -650,7 +650,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->bot_difficulty = players[i].botvars.difficulty; rsp->bot_difficulty = players[i].botvars.difficulty;
rsp->bot_itemdelay = players[i].botvars.itemdelay; rsp->bot_itemdelay = players[i].botvars.itemdelay;
rsp->bot_itemconfirm = players[i].botvars.itemconfirm; rsp->bot_itemconfirm = players[i].botvars.itemconfirm;
rsp->bot_lastturn = players[i].botvars.lastturn; rsp->bot_turnconfirm = players[i].botvars.turnconfirm;
rsp->hasmo = false; rsp->hasmo = false;
//Transfer important mo information if the player has a body. //Transfer important mo information if the player has a body.
@ -779,7 +779,7 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].botvars.difficulty = rsp->bot_difficulty; players[i].botvars.difficulty = rsp->bot_difficulty;
players[i].botvars.itemdelay = rsp->bot_itemdelay; players[i].botvars.itemdelay = rsp->bot_itemdelay;
players[i].botvars.itemconfirm = rsp->bot_itemconfirm; players[i].botvars.itemconfirm = rsp->bot_itemconfirm;
players[i].botvars.lastturn = rsp->bot_lastturn; players[i].botvars.turnconfirm = rsp->bot_turnconfirm;
//We get a packet for each player in game. //We get a packet for each player in game.
if (!playeringame[i]) if (!playeringame[i])

View file

@ -289,7 +289,7 @@ typedef struct
UINT8 bot_difficulty; UINT8 bot_difficulty;
tic_t bot_itemdelay; tic_t bot_itemdelay;
tic_t bot_itemconfirm; tic_t bot_itemconfirm;
INT16 bot_lastturn; SINT8 bot_turnconfirm;
//player->mo stuff //player->mo stuff
UINT8 hasmo; // Boolean UINT8 hasmo; // Boolean

View file

@ -428,7 +428,7 @@ typedef struct botvars_s
tic_t itemdelay; tic_t itemdelay;
tic_t itemconfirm; tic_t itemconfirm;
INT16 lastturn; SINT8 turnconfirm;
} botvars_t; } botvars_t;
// ======================================================================== // ========================================================================

View file

@ -410,6 +410,7 @@ fixed_t distancetocheck = 0;
fixed_t closestlinedist = INT32_MAX; fixed_t closestlinedist = INT32_MAX;
INT16 curturn = 0;
INT16 badsteerglobal = 0; INT16 badsteerglobal = 0;
fixed_t eggboxx, eggboxy; fixed_t eggboxx, eggboxy;
@ -761,30 +762,60 @@ static void K_SteerFromObject(mobj_t *bot, mobj_t *thing, fixed_t fulldist, fixe
{ {
angle_t destangle = R_PointToAngle2(bot->x, bot->y, thing->x, thing->y); angle_t destangle = R_PointToAngle2(bot->x, bot->y, thing->x, thing->y);
angle_t angle; angle_t angle;
SINT8 flip = 1;
amount = (amount * FixedDiv(distancetocheck - fulldist, distancetocheck)) / FRACUNIT; amount = (amount * FixedDiv(distancetocheck - fulldist, distancetocheck)) / FRACUNIT;
if (towards) if (amount == 0)
{ {
if (xdist < (bot->radius + thing->radius)) // Shouldn't happen
{
// Don't need to turn any harder!
return; return;
} }
amount = -amount; if (towards)
}
angle = (bot->angle - destangle);
if (angle < ANGLE_180)
{ {
badsteerglobal -= amount; if (xdist < FixedHypot(bot->radius, thing->radius))
{
// Don't need to turn any harder!
if (abs(badsteerglobal) <= amount)
{
badsteerglobal = 0;
} }
else else
{
if (badsteerglobal > 0)
{
badsteerglobal -= amount;
}
else if (badsteerglobal < 0)
{ {
badsteerglobal += amount; badsteerglobal += amount;
} }
}
return;
}
// Still turning towards it, flip.
flip = -flip;
}
angle = (bot->angle - destangle);
if (angle < ANGLE_180)
{
flip = -flip;
}
// If going in the opposite direction of where you wanted to turn,
// then reduce the amount that you can turn in that direction.
if ((flip == 1 && curturn < 0)
|| (flip == -1 && curturn > 0))
{
amount /= 4;
}
badsteerglobal += amount * flip;
} }
static boolean K_BotSteerObjects(mobj_t *thing) static boolean K_BotSteerObjects(mobj_t *thing)
@ -876,7 +907,7 @@ static boolean K_BotSteerObjects(mobj_t *thing)
K_SteerFromObject(botmo, thing, fulldist, xdist, false, 2 * (KART_FULLTURN + dodge)); K_SteerFromObject(botmo, thing, fulldist, xdist, false, 2 * (KART_FULLTURN + dodge));
break; break;
case MT_RANDOMITEM: case MT_RANDOMITEM:
if (anglediff > 90) if (anglediff >= 60)
{ {
break; break;
} }
@ -887,7 +918,7 @@ static boolean K_BotSteerObjects(mobj_t *thing)
} }
break; break;
case MT_EGGMANITEM: case MT_EGGMANITEM:
if (anglediff > 90) if (anglediff >= 60)
{ {
break; break;
} }
@ -908,7 +939,7 @@ static boolean K_BotSteerObjects(mobj_t *thing)
} }
break; break;
case MT_FLOATINGITEM: case MT_FLOATINGITEM:
if (anglediff > 90) if (anglediff >= 60)
{ {
break; break;
} }
@ -920,7 +951,7 @@ static boolean K_BotSteerObjects(mobj_t *thing)
break; break;
case MT_RING: case MT_RING:
case MT_FLINGRING: case MT_FLINGRING:
if (anglediff > 90) if (anglediff >= 60)
{ {
break; break;
} }
@ -932,8 +963,8 @@ static boolean K_BotSteerObjects(mobj_t *thing)
{ {
K_SteerFromObject(botmo, thing, fulldist, xdist, true, K_SteerFromObject(botmo, thing, fulldist, xdist, true,
(RINGTOTAL(botmo->player) < 3 (RINGTOTAL(botmo->player) < 3
? (2 * (KART_FULLTURN + attack)) ? (4 * (KART_FULLTURN + attack))
: ((KART_FULLTURN + attack) / 2)) : (KART_FULLTURN + attack))
); );
} }
break; break;
@ -985,7 +1016,7 @@ static boolean K_BotSteerObjects(mobj_t *thing)
fixed_t theirweight = K_GetMobjWeight(thing, botmo); fixed_t theirweight = K_GetMobjWeight(thing, botmo);
fixed_t weightdiff = 0; fixed_t weightdiff = 0;
if (anglediff > 90) if (anglediff >= 90)
{ {
weightdiff = theirweight - ourweight; weightdiff = theirweight - ourweight;
} }
@ -1006,6 +1037,11 @@ static boolean K_BotSteerObjects(mobj_t *thing)
} }
break; break;
case MT_BOTHINT: case MT_BOTHINT:
if (anglediff >= 60)
{
break;
}
if (thing->extravalue1 == 0) if (thing->extravalue1 == 0)
{ {
K_SteerFromObject(botmo, thing, fulldist, xdist, false, thing->extravalue2 * (KART_FULLTURN + dodge)); K_SteerFromObject(botmo, thing, fulldist, xdist, false, thing->extravalue2 * (KART_FULLTURN + dodge));
@ -1025,14 +1061,15 @@ static boolean K_BotSteerObjects(mobj_t *thing)
return true; return true;
} }
static INT16 K_BotFindObjects(player_t *player) static INT16 K_BotFindObjects(player_t *player, INT16 turn)
{ {
INT32 xl, xh, yl, yh, bx, by; INT32 xl, xh, yl, yh, bx, by;
badsteerglobal = 0; badsteerglobal = 0;
botmo = player->mo; botmo = player->mo;
distancetocheck = (player->mo->radius * 32) + (player->speed * 4); curturn = turn;
distancetocheck = 2048*mapobjectscale;
xl = (unsigned)(botmo->x - distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; xl = (unsigned)(botmo->x - distancetocheck - bmaporgx)>>MAPBLOCKSHIFT;
xh = (unsigned)(botmo->x + distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; xh = (unsigned)(botmo->x + distancetocheck - bmaporgx)>>MAPBLOCKSHIFT;
@ -1409,11 +1446,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
cmd->forwardmove /= 2; cmd->forwardmove /= 2;
cmd->buttons |= BT_BRAKE; cmd->buttons |= BT_BRAKE;
} }
else if (dirdist <= realrad)
{
// Steer towards/away from objects!
turnamt += K_BotFindObjects(player);
}
if (dirdist <= rad) if (dirdist <= rad)
{ {
@ -1446,6 +1478,12 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
turnamt /= 4; turnamt /= 4;
} }
} }
if (anglediff < 60)
{
// Steer towards/away from objects!
turnamt += K_BotFindObjects(player, turnamt);
}
} }
} }
@ -2169,8 +2207,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
if (turnamt != 0) if (turnamt != 0)
{ {
const INT16 minturn = KART_FULLTURN/2;
if (turnamt > KART_FULLTURN) if (turnamt > KART_FULLTURN)
{ {
turnamt = KART_FULLTURN; turnamt = KART_FULLTURN;
@ -2180,26 +2216,39 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
turnamt = -KART_FULLTURN; turnamt = -KART_FULLTURN;
} }
if ((turnamt > minturn && player->botvars.lastturn >= 0)
|| (turnamt < -minturn && player->botvars.lastturn <= 0))
{
if (turnamt > 0) if (turnamt > 0)
{ {
player->botvars.lastturn = 1; if (player->botvars.turnconfirm < 0)
{
// Reset turn confirm
player->botvars.turnconfirm = 0;
}
if (player->botvars.turnconfirm < BOTTURNCONFIRM)
{
player->botvars.turnconfirm++;
}
} }
else if (turnamt < 0) else if (turnamt < 0)
{ {
player->botvars.lastturn = -1; if (player->botvars.turnconfirm > 0)
{
// Reset turn confirm
player->botvars.turnconfirm = 0;
} }
if (player->botvars.turnconfirm > -BOTTURNCONFIRM)
{
player->botvars.turnconfirm--;
}
}
if (abs(player->botvars.turnconfirm) >= BOTTURNCONFIRM)
{
// You're probably commiting to your turn, here you go.
cmd->driftturn = turnamt; cmd->driftturn = turnamt;
cmd->angleturn += K_GetKartTurnValue(player, turnamt); cmd->angleturn += K_GetKartTurnValue(player, turnamt);
} }
else
{
// Can reset turn dir
player->botvars.lastturn = 0;
}
} }
if (predict != NULL) if (predict != NULL)

View file

@ -13,8 +13,13 @@
#include "k_waypoint.h" #include "k_waypoint.h"
#include "d_player.h" #include "d_player.h"
// Maximum value of botvars.difficulty
#define MAXBOTDIFFICULTY 9 #define MAXBOTDIFFICULTY 9
// How many tics in a row do you need to turn in this direction before we'll let you turn.
// Made it as small as possible without making it look like the bots are twitching constantly.
#define BOTTURNCONFIRM 7
// Path that bot will attempt to take // Path that bot will attempt to take
typedef struct botprediction_s { typedef struct botprediction_s {
fixed_t x, y; fixed_t x, y;

View file

@ -272,7 +272,7 @@ static void P_NetArchivePlayers(void)
WRITEUINT8(save_p, players[i].botvars.difficulty); WRITEUINT8(save_p, players[i].botvars.difficulty);
WRITEUINT32(save_p, players[i].botvars.itemdelay); WRITEUINT32(save_p, players[i].botvars.itemdelay);
WRITEUINT32(save_p, players[i].botvars.itemconfirm); WRITEUINT32(save_p, players[i].botvars.itemconfirm);
WRITEINT16(save_p, players[i].botvars.lastturn); WRITESINT8(save_p, players[i].botvars.turnconfirm);
} }
} }
@ -448,7 +448,7 @@ static void P_NetUnArchivePlayers(void)
players[i].botvars.difficulty = READUINT8(save_p); players[i].botvars.difficulty = READUINT8(save_p);
players[i].botvars.itemdelay = READUINT32(save_p); players[i].botvars.itemdelay = READUINT32(save_p);
players[i].botvars.itemconfirm = READUINT32(save_p); players[i].botvars.itemconfirm = READUINT32(save_p);
players[i].botvars.lastturn = READINT16(save_p); players[i].botvars.turnconfirm = READSINT8(save_p);
} }
} }