Slightly smarter sneaker usage

- Use sneaker if held for too long without a proper use
- Use sneaker if losing too much speed
- Use sneaker if you have another boost (tether, boosters)
- Add triple sneaker & rocket sneaker support
- Don't go towards shortcut waypoints without a shortcut item
- Bots get naturally better handling
This commit is contained in:
Sally Cochenour 2020-03-30 17:17:20 -04:00
parent 9e2c119b56
commit fb550f2868
6 changed files with 96 additions and 11 deletions

View file

@ -348,6 +348,7 @@ typedef enum
k_wrongway, // Display WRONG WAY on screen k_wrongway, // Display WRONG WAY on screen
k_botitemdelay, k_botitemdelay,
k_botitemconfirm,
NUMKARTSTUFF NUMKARTSTUFF
} kartstufftype_t; } kartstufftype_t;

View file

@ -8607,7 +8607,8 @@ static const char *const KARTSTUFF_LIST[] = {
"KILLFIELD", "KILLFIELD",
"WRONGWAY", "WRONGWAY",
"BOTITEMDELAY" "BOTITEMDELAY",
"BOTITEMCONFIRM"
}; };
#endif #endif

View file

@ -68,7 +68,7 @@ void K_AddBots(SINT8 numbots)
else if (numbots == 2) else if (numbots == 2)
WRITEUINT8(buf_p, 5); WRITEUINT8(buf_p, 5);
else if (numbots == 1) else if (numbots == 1)
WRITEUINT8(buf_p, 7); WRITEUINT8(buf_p, 9);
else else
WRITEUINT8(buf_p, 10); WRITEUINT8(buf_p, 10);
@ -88,6 +88,17 @@ boolean K_PlayerUsesBotMovement(player_t *player)
return false; return false;
} }
boolean K_BotCanTakeCut(player_t *player)
{
if (!K_ApplyOffroad(player)
|| player->kartstuff[k_itemtype] == KITEM_SNEAKER
|| player->kartstuff[k_itemtype] == KITEM_INVINCIBILITY
|| player->kartstuff[k_itemtype] == KITEM_HYUDORO)
return true;
return false;
}
static fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy) static fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy)
{ {
fixed_t v1toc[2] = {cx - v1x, cy - v1y}; fixed_t v1toc[2] = {cx - v1x, cy - v1y};
@ -105,7 +116,7 @@ static fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x,
static botprediction_t *K_CreateBotPrediction(player_t *player) static botprediction_t *K_CreateBotPrediction(player_t *player)
{ {
const INT32 distance = ((256 * player->mo->scale) + (player->speed * 16)) / FRACUNIT; const INT32 distance = (player->speed / FRACUNIT) * TICRATE;
INT32 distanceleft = distance; INT32 distanceleft = distance;
botprediction_t *predictcoords = Z_Calloc(sizeof(botprediction_t), PU_LEVEL, NULL); botprediction_t *predictcoords = Z_Calloc(sizeof(botprediction_t), PU_LEVEL, NULL);
waypoint_t *wp = player->nextwaypoint; waypoint_t *wp = player->nextwaypoint;
@ -113,6 +124,14 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
size_t i; size_t i;
INT32 lp = 0; INT32 lp = 0;
if (distance <= 0)
{
predictcoords->x = wp->mobj->x;
predictcoords->y = wp->mobj->y;
predictcoords->radius = wp->mobj->radius;
return predictcoords;
}
while (distanceleft > 0) while (distanceleft > 0)
{ {
lp++; lp++;
@ -132,6 +151,11 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
for (i = 0; i < wp->numnextwaypoints; i++) for (i = 0; i < wp->numnextwaypoints; i++)
{ {
if (K_GetWaypointIsShortcut(wp->nextwaypoints[i]) && !K_BotCanTakeCut(player))
{
continue;
}
dist = P_AproxDistance( dist = P_AproxDistance(
player->mo->x - wp->nextwaypoints[i]->mobj->x, player->mo->x - wp->nextwaypoints[i]->mobj->x,
player->mo->y - wp->nextwaypoints[i]->mobj->y player->mo->y - wp->nextwaypoints[i]->mobj->y
@ -246,7 +270,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
if (dirdist <= rad) if (dirdist <= rad)
{ {
if (dirdist < rad/2) if (dirdist < 2*rad/3)
{ {
// Don't need to turn! // Don't need to turn!
turnamt = 0; turnamt = 0;
@ -257,12 +281,12 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
turnamt /= 4; turnamt /= 4;
} }
} }
/*else else if (anglediff > 45)
{ {
// Actually, don't go too fast... // Actually, don't go too fast...
cmd->forwardmove /= 2; cmd->forwardmove /= 2;
cmd->buttons |= BT_BRAKE; cmd->buttons |= BT_BRAKE;
}*/ }
} }
if (turnamt != 0) if (turnamt != 0)
@ -282,13 +306,51 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
else else
{ {
if (player->kartstuff[k_botitemdelay]) if (player->kartstuff[k_botitemdelay])
{
player->kartstuff[k_botitemdelay]--;
player->kartstuff[k_botitemconfirm] = 0;
return; return;
}
switch (player->kartstuff[k_itemtype]) switch (player->kartstuff[k_itemtype])
{ {
case KITEM_SNEAKER: case KITEM_SNEAKER:
if (player->kartstuff[k_offroad] || K_GetWaypointIsShortcut(player->nextwaypoint) == true) if ((player->kartstuff[k_offroad] && K_ApplyOffroad(player)) // Stuck in offroad, use it NOW
|| K_GetWaypointIsShortcut(player->nextwaypoint) == true // Going toward a shortcut!
|| player->speed < K_GetKartSpeed(player, false)/2 // Being slowed down too much
|| player->kartstuff[k_speedboost] > 0 // Have another type of boost (tethering)
|| player->kartstuff[k_botitemconfirm] > 4*TICRATE) // Held onto it for too long
{
cmd->buttons |= BT_ATTACK; cmd->buttons |= BT_ATTACK;
player->kartstuff[k_botitemconfirm] -= TICRATE;
}
else
{
player->kartstuff[k_botitemconfirm]++;
}
break;
case KITEM_ROCKETSNEAKER:
if (player->kartstuff[k_rocketsneakertimer] <= 0)
{
cmd->buttons |= BT_ATTACK;
player->kartstuff[k_botitemconfirm] = 0;
}
else
{
if ((player->kartstuff[k_offroad] && K_ApplyOffroad(player)) // Stuck in offroad, use it NOW
|| K_GetWaypointIsShortcut(player->nextwaypoint) == true // Going toward a shortcut!
|| player->speed < K_GetKartSpeed(player, false)/2 // Being slowed down too much
|| player->kartstuff[k_speedboost] > 0 // Have another type of boost (tethering)
|| player->kartstuff[k_botitemconfirm] > TICRATE) // Held onto it for too long
{
cmd->buttons |= BT_ATTACK;
player->kartstuff[k_botitemconfirm] -= TICRATE/2;
}
else
{
player->kartstuff[k_botitemconfirm]++;
}
}
break; break;
case KITEM_INVINCIBILITY: case KITEM_INVINCIBILITY:
case KITEM_SPB: case KITEM_SPB:
@ -297,8 +359,10 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
case KITEM_HYUDORO: case KITEM_HYUDORO:
case KITEM_SUPERRING: case KITEM_SUPERRING:
cmd->buttons |= BT_ATTACK; cmd->buttons |= BT_ATTACK;
player->kartstuff[k_botitemconfirm] = 0;
break; break;
default: default:
player->kartstuff[k_botitemconfirm] = 0;
break; break;
} }
} }

View file

@ -20,4 +20,5 @@ typedef struct botprediction_s {
void K_AddBots(SINT8 numbots); void K_AddBots(SINT8 numbots);
boolean K_PlayerUsesBotMovement(player_t *player); boolean K_PlayerUsesBotMovement(player_t *player);
boolean K_BotCanTakeCut(player_t *player);
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd); void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd);

View file

@ -763,6 +763,7 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem)
hyubgone = 5*TICRATE; hyubgone = 5*TICRATE;
player->kartstuff[k_botitemdelay] = TICRATE; player->kartstuff[k_botitemdelay] = TICRATE;
player->kartstuff[k_botitemconfirm] = 0;
switch (getitem) switch (getitem)
{ {
@ -907,12 +908,14 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp
switch (item) switch (item)
{ {
case KITEM_SNEAKER: case KITEM_SNEAKER:
case KITEM_ROCKETSNEAKER:
case KITEM_INVINCIBILITY: case KITEM_INVINCIBILITY:
case KITEM_SPB: case KITEM_SPB:
case KITEM_GROW: case KITEM_GROW:
case KITEM_SHRINK: case KITEM_SHRINK:
case KITEM_HYUDORO: case KITEM_HYUDORO:
case KITEM_SUPERRING: case KITEM_SUPERRING:
case KRITEM_TRIPLESNEAKER:
break; break;
default: default:
return 0; return 0;
@ -2536,7 +2539,7 @@ void K_MomentumToFacing(player_t *player)
player->mo->momy = FixedMul(player->mo->momy - player->cmomy, player->mo->friction) + player->cmomy; player->mo->momy = FixedMul(player->mo->momy - player->cmomy, player->mo->friction) + player->cmomy;
} }
static boolean K_ApplyOffroad(player_t *player) boolean K_ApplyOffroad(player_t *player)
{ {
if (player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || EITHERSNEAKER(player)) if (player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || EITHERSNEAKER(player))
return false; return false;
@ -6023,9 +6026,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
player->powers[pw_flashing]--; player->powers[pw_flashing]--;
} }
if (player->kartstuff[k_botitemdelay])
player->kartstuff[k_botitemdelay]--;
if (player->kartstuff[k_spinouttimer]) if (player->kartstuff[k_spinouttimer])
{ {
if ((P_IsObjectOnGround(player->mo) if ((P_IsObjectOnGround(player->mo)
@ -6411,6 +6411,13 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
{ {
for (i = 0U; i < waypoint->numnextwaypoints; i++) for (i = 0U; i < waypoint->numnextwaypoints; i++)
{ {
if (K_GetWaypointIsShortcut(waypoint->nextwaypoints[i])
&& K_PlayerUsesBotMovement(player)
&& !K_BotCanTakeCut(player))
{
continue;
}
angletowaypoint = R_PointToAngle2( angletowaypoint = R_PointToAngle2(
player->mo->x, player->mo->y, player->mo->x, player->mo->y,
waypoint->nextwaypoints[i]->mobj->x, waypoint->nextwaypoints[i]->mobj->y); waypoint->nextwaypoints[i]->mobj->x, waypoint->nextwaypoints[i]->mobj->y);
@ -6451,6 +6458,13 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
{ {
for (i = 0U; i < waypoint->numprevwaypoints; i++) for (i = 0U; i < waypoint->numprevwaypoints; i++)
{ {
if (K_GetWaypointIsShortcut(waypoint->prevwaypoints[i])
&& K_PlayerUsesBotMovement(player)
&& !K_BotCanTakeCut(player))
{
continue;
}
angletowaypoint = R_PointToAngle2( angletowaypoint = R_PointToAngle2(
player->mo->x, player->mo->y, player->mo->x, player->mo->y,
waypoint->prevwaypoints[i]->mobj->x, waypoint->prevwaypoints[i]->mobj->y); waypoint->prevwaypoints[i]->mobj->x, waypoint->prevwaypoints[i]->mobj->y);
@ -6746,6 +6760,9 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue)
if (EITHERSNEAKER(player) || player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_growshrinktimer] > 0) if (EITHERSNEAKER(player) || player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_growshrinktimer] > 0)
turnvalue = FixedMul(turnvalue, (5*FRACUNIT)/4); turnvalue = FixedMul(turnvalue, (5*FRACUNIT)/4);
if (K_PlayerUsesBotMovement(player))
turnvalue = FixedMul(turnvalue, (5*FRACUNIT)/4);
return turnvalue; return turnvalue;
} }

View file

@ -66,6 +66,7 @@ void K_DropItems(player_t *player);
void K_StripItems(player_t *player); void K_StripItems(player_t *player);
void K_StripOther(player_t *player); void K_StripOther(player_t *player);
void K_MomentumToFacing(player_t *player); void K_MomentumToFacing(player_t *player);
boolean K_ApplyOffroad(player_t *player);
fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed); fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed);
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower);
fixed_t K_GetKartAccel(player_t *player); fixed_t K_GetKartAccel(player_t *player);