diff --git a/src/d_player.h b/src/d_player.h index 57cbca3cc..24c692862 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -348,6 +348,7 @@ typedef enum k_wrongway, // Display WRONG WAY on screen k_botitemdelay, + k_botitemconfirm, NUMKARTSTUFF } kartstufftype_t; diff --git a/src/dehacked.c b/src/dehacked.c index 2bbe6797a..8b957c0bb 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8607,7 +8607,8 @@ static const char *const KARTSTUFF_LIST[] = { "KILLFIELD", "WRONGWAY", - "BOTITEMDELAY" + "BOTITEMDELAY", + "BOTITEMCONFIRM" }; #endif diff --git a/src/k_bot.c b/src/k_bot.c index 2c9956d46..968ec09b2 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -68,7 +68,7 @@ void K_AddBots(SINT8 numbots) else if (numbots == 2) WRITEUINT8(buf_p, 5); else if (numbots == 1) - WRITEUINT8(buf_p, 7); + WRITEUINT8(buf_p, 9); else WRITEUINT8(buf_p, 10); @@ -88,6 +88,17 @@ boolean K_PlayerUsesBotMovement(player_t *player) 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) { 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) { - const INT32 distance = ((256 * player->mo->scale) + (player->speed * 16)) / FRACUNIT; + const INT32 distance = (player->speed / FRACUNIT) * TICRATE; INT32 distanceleft = distance; botprediction_t *predictcoords = Z_Calloc(sizeof(botprediction_t), PU_LEVEL, NULL); waypoint_t *wp = player->nextwaypoint; @@ -113,6 +124,14 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) size_t i; 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) { lp++; @@ -132,6 +151,11 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) for (i = 0; i < wp->numnextwaypoints; i++) { + if (K_GetWaypointIsShortcut(wp->nextwaypoints[i]) && !K_BotCanTakeCut(player)) + { + continue; + } + dist = P_AproxDistance( player->mo->x - wp->nextwaypoints[i]->mobj->x, 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/2) + if (dirdist < 2*rad/3) { // Don't need to turn! turnamt = 0; @@ -257,12 +281,12 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) turnamt /= 4; } } - /*else + else if (anglediff > 45) { // Actually, don't go too fast... cmd->forwardmove /= 2; cmd->buttons |= BT_BRAKE; - }*/ + } } if (turnamt != 0) @@ -282,13 +306,51 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) else { if (player->kartstuff[k_botitemdelay]) + { + player->kartstuff[k_botitemdelay]--; + player->kartstuff[k_botitemconfirm] = 0; return; + } switch (player->kartstuff[k_itemtype]) { 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; + 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; case KITEM_INVINCIBILITY: case KITEM_SPB: @@ -297,8 +359,10 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) case KITEM_HYUDORO: case KITEM_SUPERRING: cmd->buttons |= BT_ATTACK; + player->kartstuff[k_botitemconfirm] = 0; break; default: + player->kartstuff[k_botitemconfirm] = 0; break; } } diff --git a/src/k_bot.h b/src/k_bot.h index c8098b86e..071a4fb3e 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -20,4 +20,5 @@ typedef struct botprediction_s { void K_AddBots(SINT8 numbots); boolean K_PlayerUsesBotMovement(player_t *player); +boolean K_BotCanTakeCut(player_t *player); void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd); diff --git a/src/k_kart.c b/src/k_kart.c index f87afe65e..4ea7dab2f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -763,6 +763,7 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem) hyubgone = 5*TICRATE; player->kartstuff[k_botitemdelay] = TICRATE; + player->kartstuff[k_botitemconfirm] = 0; switch (getitem) { @@ -907,12 +908,14 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp switch (item) { case KITEM_SNEAKER: + case KITEM_ROCKETSNEAKER: case KITEM_INVINCIBILITY: case KITEM_SPB: case KITEM_GROW: case KITEM_SHRINK: case KITEM_HYUDORO: case KITEM_SUPERRING: + case KRITEM_TRIPLESNEAKER: break; default: 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; } -static boolean K_ApplyOffroad(player_t *player) +boolean K_ApplyOffroad(player_t *player) { if (player->kartstuff[k_invincibilitytimer] || player->kartstuff[k_hyudorotimer] || EITHERSNEAKER(player)) return false; @@ -6023,9 +6026,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->powers[pw_flashing]--; } - if (player->kartstuff[k_botitemdelay]) - player->kartstuff[k_botitemdelay]--; - if (player->kartstuff[k_spinouttimer]) { if ((P_IsObjectOnGround(player->mo) @@ -6411,6 +6411,13 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) { for (i = 0U; i < waypoint->numnextwaypoints; i++) { + if (K_GetWaypointIsShortcut(waypoint->nextwaypoints[i]) + && K_PlayerUsesBotMovement(player) + && !K_BotCanTakeCut(player)) + { + continue; + } + angletowaypoint = R_PointToAngle2( player->mo->x, player->mo->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++) { + if (K_GetWaypointIsShortcut(waypoint->prevwaypoints[i]) + && K_PlayerUsesBotMovement(player) + && !K_BotCanTakeCut(player)) + { + continue; + } + angletowaypoint = R_PointToAngle2( player->mo->x, player->mo->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) turnvalue = FixedMul(turnvalue, (5*FRACUNIT)/4); + if (K_PlayerUsesBotMovement(player)) + turnvalue = FixedMul(turnvalue, (5*FRACUNIT)/4); + return turnvalue; } diff --git a/src/k_kart.h b/src/k_kart.h index edec02685..1c945e8c2 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -66,6 +66,7 @@ void K_DropItems(player_t *player); void K_StripItems(player_t *player); void K_StripOther(player_t *player); void K_MomentumToFacing(player_t *player); +boolean K_ApplyOffroad(player_t *player); fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); fixed_t K_GetKartAccel(player_t *player);