diff --git a/src/k_bot.c b/src/k_bot.c index 968ec09b2..2e280ffba 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -116,10 +116,12 @@ 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 = (player->speed / FRACUNIT) * TICRATE; + const INT32 futuresight = (3*TICRATE/4); // How far ahead into the future to try and predict + const INT32 distance = (player->speed / FRACUNIT) * futuresight; INT32 distanceleft = distance; botprediction_t *predictcoords = Z_Calloc(sizeof(botprediction_t), PU_LEVEL, NULL); waypoint_t *wp = player->nextwaypoint; + fixed_t smallestradius = wp->mobj->radius; size_t nwp; size_t i; INT32 lp = 0; @@ -128,7 +130,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) { predictcoords->x = wp->mobj->x; predictcoords->y = wp->mobj->y; - predictcoords->radius = wp->mobj->radius; + predictcoords->radius = smallestradius; return predictcoords; } @@ -174,13 +176,19 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) break; } - wp = wp->nextwaypoints[nwp]; distanceleft -= wp->nextwaypointdistances[nwp]; + + if (wp->nextwaypoints[nwp]->mobj->radius < smallestradius) + { + smallestradius = wp->nextwaypoints[nwp]->mobj->radius; + } + + wp = wp->nextwaypoints[nwp]; } predictcoords->x = wp->mobj->x; predictcoords->y = wp->mobj->y; - predictcoords->radius = wp->mobj->radius; + predictcoords->radius = smallestradius; if (distanceleft > 0) { @@ -195,6 +203,9 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) { + boolean ontrack = false; + INT16 turnamt = KART_FULLTURN; + // Can't build a ticcmd if we aren't spawned... if (!player->mo) return; @@ -225,7 +236,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (player->nextwaypoint != NULL && player->nextwaypoint->mobj != NULL && !P_MobjWasRemoved(player->nextwaypoint->mobj)) { botprediction_t *predict = K_CreateBotPrediction(player); - INT16 turnamt = KART_FULLTURN; SINT8 turnsign = 0; angle_t destangle, moveangle, angle; INT16 anglediff; @@ -256,13 +266,18 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) } else { - fixed_t rad = predict->radius - (player->mo->radius*2); + fixed_t rad = predict->radius - (player->mo->radius*4); fixed_t dirdist = K_DistanceOfLineFromPoint( player->mo->x, player->mo->y, player->mo->x + FINECOSINE(moveangle >> ANGLETOFINESHIFT), player->mo->y + FINESINE(moveangle >> ANGLETOFINESHIFT), predict->x, predict->y ); + if (rad < 0) + { + rad = 0; + } + cmd->buttons |= BT_ACCELERATE; // Full speed ahead! @@ -270,7 +285,22 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (dirdist <= rad) { - if (dirdist < 2*rad/3) + fixed_t speedmul = FixedMul(player->speed, K_GetKartSpeed(player, false)); + fixed_t speedrad = rad/4; + + ontrack = true; + + if (speedmul > FRACUNIT) + { + speedmul = FRACUNIT; + } + + // Increase radius with speed + // At low speed, the CPU will try to be more accurate + // At high speed, they're more likely to lawnmower + speedrad += FixedMul(speedmul, rad/2); + + if (dirdist < speedrad) { // Don't need to turn! turnamt = 0; @@ -291,17 +321,36 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (turnamt != 0) { - cmd->driftturn = KART_FULLTURN * turnsign; - cmd->angleturn += KART_FULLTURN * turnsign; + cmd->driftturn = turnamt * turnsign; + cmd->angleturn += turnamt * turnsign; } Z_Free(predict); } - - if (player->kartstuff[k_userings] == 1 && !player->exiting) + else { - if (player->kartstuff[k_rings] > 10) - cmd->buttons |= BT_ATTACK; + turnamt = 0; + } + + (void)ontrack; + + if (player->kartstuff[k_userings] == 1) + { + if (!player->exiting) + { + INT32 saferingsval = 8 + K_GetKartRingPower(player); + + if (player->speed < K_GetKartSpeed(player, false)/2 // Being slowed down too much + || player->kartstuff[k_speedboost] > 0) // Have another type of boost (tethering) + { + saferingsval -= 5; + } + + if (player->kartstuff[k_rings] > saferingsval) + { + cmd->buttons |= BT_ATTACK; + } + } } else { @@ -312,58 +361,63 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) return; } - switch (player->kartstuff[k_itemtype]) + if (player->kartstuff[k_rocketsneakertimer] > 0) { - case KITEM_SNEAKER: - 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) + if (player->kartstuff[k_botitemconfirm] > TICRATE) + { + if (player->kartstuff[k_sneakertimer] <= (TICRATE/3) && !(player->pflags & PF_ATTACKDOWN)) { cmd->buttons |= BT_ATTACK; player->kartstuff[k_botitemconfirm] = 0; } - else - { + } + else + { + player->kartstuff[k_botitemconfirm]++; + } + } + else + { + switch (player->kartstuff[k_itemtype]) + { + case KITEM_SNEAKER: 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 + || player->kartstuff[k_botitemconfirm] > 4*TICRATE) // Held onto it for too long { - cmd->buttons |= BT_ATTACK; - player->kartstuff[k_botitemconfirm] -= TICRATE/2; + if (player->kartstuff[k_sneakertimer] <= (TICRATE/3) && !(player->pflags & PF_ATTACKDOWN)) + { + cmd->buttons |= BT_ATTACK; + player->kartstuff[k_botitemconfirm] -= 2*TICRATE; + } } else { player->kartstuff[k_botitemconfirm]++; } - } - break; - case KITEM_INVINCIBILITY: - case KITEM_SPB: - case KITEM_GROW: - case KITEM_SHRINK: - case KITEM_HYUDORO: - case KITEM_SUPERRING: - cmd->buttons |= BT_ATTACK; - player->kartstuff[k_botitemconfirm] = 0; - break; - default: - player->kartstuff[k_botitemconfirm] = 0; - break; + break; + case KITEM_ROCKETSNEAKER: + if (player->kartstuff[k_rocketsneakertimer] <= 0) + { + cmd->buttons |= BT_ATTACK; + player->kartstuff[k_botitemconfirm] = 0; + } + break; + case KITEM_INVINCIBILITY: + case KITEM_SPB: + case KITEM_GROW: + case KITEM_SHRINK: + 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 071a4fb3e..797843dea 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -16,6 +16,7 @@ typedef struct botprediction_s { fixed_t x, y; fixed_t radius; + angle_t dir; } botprediction_t; void K_AddBots(SINT8 numbots); diff --git a/src/k_kart.c b/src/k_kart.c index 4c5d924c7..83d0354b3 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6455,9 +6455,9 @@ 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)) + if (K_PlayerUsesBotMovement(player) + && K_GetWaypointIsShortcut(waypoint->nextwaypoints[i]) + && !K_BotCanTakeCut(player)) { continue; } @@ -6498,17 +6498,11 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) } } - if ((waypoint->prevwaypoints != NULL) && (waypoint->numprevwaypoints > 0U)) + if ((waypoint->prevwaypoints != NULL) && (waypoint->numprevwaypoints > 0U) + && !(K_PlayerUsesBotMovement(player))) // Bots do not need prev waypoints { 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); @@ -6729,6 +6723,11 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) } } +INT32 K_GetKartRingPower(player_t *player) +{ + return (((9 - player->kartspeed) + (9 - player->kartweight)) / 2); +} + // Returns false if this player being placed here causes them to collide with any other player // Used in g_game.c for match etc. respawning // This does not check along the z because the z is not correctly set for the spawnee at this point diff --git a/src/k_kart.h b/src/k_kart.h index 26d6f6ecc..c9167a283 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -59,6 +59,7 @@ void K_UpdateHnextList(player_t *player, boolean clean); void K_DropHnextList(player_t *player); void K_RepairOrbitChain(mobj_t *orbit); player_t *K_FindJawzTarget(mobj_t *actor, player_t *source); +INT32 K_GetKartRingPower(player_t *player); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); INT32 K_GetKartDriftSparkValue(player_t *player); diff --git a/src/p_enemy.c b/src/p_enemy.c index 8f1fcb1be..c9d23d945 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3570,7 +3570,6 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1) // SRB2Kart { -#define RINGBOOSTPWR (((9 - actor->target->player->kartspeed) + (9 - actor->target->player->kartweight)) / 2) if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player) { P_RemoveMobj(actor); @@ -3588,7 +3587,7 @@ void A_AttractChase(mobj_t *actor) angle_t offset = FixedAngle(18<target->player->kartstuff[k_ringboost] += RINGBOOSTPWR+3; + actor->target->player->kartstuff[k_ringboost] += K_GetKartRingPower(actor->target->player)+3; S_StartSound(actor->target, sfx_s1b5); sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS); @@ -3616,7 +3615,7 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 16) { if (actor->target->player->kartstuff[k_rings] >= 20) - actor->target->player->kartstuff[k_ringboost] += RINGBOOSTPWR+3; + actor->target->player->kartstuff[k_ringboost] += K_GetKartRingPower(actor->target->player)+3; else P_GivePlayerRings(actor->target->player, 1); @@ -3645,7 +3644,6 @@ void A_AttractChase(mobj_t *actor) actor->extravalue1++; } } -#undef RINGBOOSTPWR } else {