diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9e410e75e..35dfca737 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,6 @@ # Core sources set(SRB2_CORE_SOURCES am_map.c - b_bot.c command.c comptime.c console.c @@ -50,7 +49,6 @@ set(SRB2_CORE_SOURCES set(SRB2_CORE_HEADERS am_map.h - b_bot.h byteptr.h command.h console.h diff --git a/src/k_bot.c b/src/k_bot.c index c585c5790..84bc8b4ee 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -231,9 +231,9 @@ void K_UpdateMatchRaceBots(void) { UINT8 buf[2]; - i = 0; + i = MAXPLAYERS; - while (numbots > wantedbots && i < MAXPLAYERS) + while (numbots > wantedbots && i > 0) { if (playeringame[i] && players[i].bot) { @@ -244,7 +244,7 @@ void K_UpdateMatchRaceBots(void) numbots--; } - i++; + i--; } } @@ -400,6 +400,59 @@ fixed_t K_BotRubberband(player_t *player) return rubberband; } +/*-------------------------------------------------- + fixed_t K_BotTopSpeedRubberband(player_t *player) + + See header file for description. +--------------------------------------------------*/ +fixed_t K_BotTopSpeedRubberband(player_t *player) +{ + fixed_t rubberband = K_BotRubberband(player); + + if (rubberband < FRACUNIT) + { + // Never go below your regular top speed + rubberband = FRACUNIT; + } + + // Only allow you to go faster than your regular top speed if you're facing the right direction + if (rubberband > FRACUNIT && player->mo != NULL && player->nextwaypoint != NULL) + { + const INT16 mindiff = 30; + const INT16 maxdiff = 60; + INT16 anglediff = 0; + fixed_t amt = rubberband - FRACUNIT; + angle_t destangle = R_PointToAngle2( + player->mo->x, player->mo->y, + player->nextwaypoint->mobj->x, player->nextwaypoint->mobj->y + ); + angle_t angle = player->mo->angle - destangle; + + if (angle < ANGLE_180) + { + anglediff = AngleFixed(angle) >> FRACBITS; + } + else + { + anglediff = 360 - (AngleFixed(angle) >> FRACBITS); + } + + anglediff = abs(anglediff); + + if (anglediff >= maxdiff) + { + rubberband = FRACUNIT; + } + else if (anglediff > mindiff) + { + amt = (amt * (maxdiff - anglediff)) / mindiff; + rubberband = FRACUNIT + amt; + } + } + + return rubberband; +} + /*-------------------------------------------------- fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy) @@ -449,7 +502,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) const fixed_t radreduce = min(distreduce + FRACUNIT/4, FRACUNIT); const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict - const fixed_t speed = P_AproxDistance(player->mo->momx, player->mo->momy); + const fixed_t speed = max(P_AproxDistance(player->mo->momx, player->mo->momy), K_GetKartSpeed(player, false) / 4); const INT32 distance = (FixedMul(speed, distreduce) / FRACUNIT) * futuresight; botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_LEVEL, NULL); @@ -694,7 +747,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (dirdist <= rad) { - fixed_t speedmul = FixedMul(player->speed, K_GetKartSpeed(player, false)); + fixed_t speedmul = FixedDiv(player->speed, K_GetKartSpeed(player, false)); fixed_t speedrad = rad/4; if (speedmul > FRACUNIT) @@ -705,7 +758,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // 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, (3*rad/4) - speedrad); + speedrad += FixedMul(speedmul, rad - speedrad); if (speedrad < playerwidth) { diff --git a/src/k_bot.h b/src/k_bot.h index 505793ada..87d5fc716 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -66,19 +66,35 @@ boolean K_BotCanTakeCut(player_t *player); /*-------------------------------------------------- fixed_t K_BotRubberband(player_t *player); - Gives a multiplier for a bot's rubberbanding. Meant to be used for top speed, - acceleration, and handling. + Gives a multiplier for a bot's rubberbanding. + Meant to be used for acceleration and handling. Input Arguments:- player - Player to check. Return:- - A multiplier in fixed point scale, between 0.875 and 2.0. + A multiplier in fixed point scale. --------------------------------------------------*/ fixed_t K_BotRubberband(player_t *player); +/*-------------------------------------------------- + fixed_t K_BotTopSpeedRubberband(player_t *player); + + Gives a multiplier for a bot's rubberbanding. + Adjusted from K_BotRubberband to be used for top speed. + + Input Arguments:- + player - Player to check. + + Return:- + A multiplier in fixed point scale. +--------------------------------------------------*/ + +fixed_t K_BotTopSpeedRubberband(player_t *player); + + /*-------------------------------------------------- fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy); diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 2a95da738..28e08f3cf 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -25,6 +25,7 @@ #include "d_ticcmd.h" #include "m_random.h" #include "r_things.h" // numskins +#include "p_slopes.h" // P_GetZAt struct globalsmuggle { @@ -156,64 +157,99 @@ static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec) } /*-------------------------------------------------- - static boolean K_BotHatesThisSector(player_t *player, sector_t *sec) + static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) Tells us if a bot will play more careful around - this sector. + this sector. Checks FOFs in the sector, as well. Input Arguments:- player - Player to check against. sec - Sector to check against. + x - Linedef cross X position, for slopes + y - Linedef cross Y position, for slopes Return:- true if avoiding this sector, false otherwise. --------------------------------------------------*/ -static boolean K_BotHatesThisSector(player_t *player, sector_t *sec) +static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) { const boolean flip = (player->mo->eflags & MFE_VERTICALFLIP); - INT32 flag; + INT32 specialflag = 0; + fixed_t highestfloor = INT32_MAX; + sector_t *bestsector = NULL; ffloor_t *rover; - if (flip) + if (flip == true) { - flag = SF_FLIPSPECIAL_CEILING; + specialflag = SF_FLIPSPECIAL_CEILING; + highestfloor = (sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : sec->ceilingheight); } else { - flag = SF_FLIPSPECIAL_FLOOR; + specialflag = SF_FLIPSPECIAL_FLOOR; + highestfloor = (sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : sec->floorheight); } - if (sec->flags & flag) + if (sec->flags & specialflag) { - if (K_BotHatesThisSectorsSpecial(player, sec)) - { - return true; - } + bestsector = sec; } for (rover = sec->ffloors; rover; rover = rover->next) { + fixed_t top = INT32_MAX; + fixed_t bottom = INT32_MAX; + if (!(rover->flags & FF_EXISTS)) { continue; } - if (!(rover->master->frontsector->flags & flag)) + top = (*rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight); + bottom = (*rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) : *rover->bottomheight); + + if (!(rover->flags & FF_BLOCKPLAYER)) + { + if ((top >= player->mo->z) && (bottom <= player->mo->z + player->mo->height) + && K_BotHatesThisSectorsSpecial(player, rover->master->frontsector)) + { + // Bad intangible sector at our height, so we DEFINITELY want to avoid + return true; + } + } + + if ((rover->flags & FF_BLOCKPLAYER) && !(rover->master->frontsector->flags & specialflag)) { continue; } - if (((*rover->bottomheight >= player->mo->z + player->mo->height) && (flip)) - || ((*rover->topheight <= player->mo->z) && (!flip))) + // Find the highest FOF floor beneath the player, and check it at the end. + if (flip == true) { - if (K_BotHatesThisSectorsSpecial(player, sec)) + if (bottom < highestfloor + && bottom >= player->mo->z + player->mo->height) { - return true; + bestsector = rover->master->frontsector; + highestfloor = bottom; + } + } + else + { + if (top > highestfloor + && top <= player->mo->z) + { + bestsector = rover->master->frontsector; + highestfloor = top; } } } - return false; + if (bestsector == NULL) + { + return false; + } + + return K_BotHatesThisSectorsSpecial(player, bestsector); } /*-------------------------------------------------- @@ -236,6 +272,7 @@ static boolean K_FindBlockingWalls(line_t *line) fixed_t maxstep = maxstepmove; fixed_t linedist = INT32_MAX; INT32 lineside = 0; + vertex_t pos; if (!globalsmuggle.botmo || P_MobjWasRemoved(globalsmuggle.botmo) || !globalsmuggle.botmo->player) { @@ -295,20 +332,18 @@ static boolean K_FindBlockingWalls(line_t *line) goto blocked; } - if (!K_BotHatesThisSector(globalsmuggle.botmo->player, globalsmuggle.botmo->subsector->sector)) - { - // Treat damage sectors like walls + // Treat damage sectors like walls + P_ClosestPointOnLine(globalsmuggle.botmo->x, globalsmuggle.botmo->y, line, &pos); - if (lineside) - { - if (K_BotHatesThisSector(globalsmuggle.botmo->player, line->frontsector)) - goto blocked; - } - else - { - if (K_BotHatesThisSector(globalsmuggle.botmo->player, line->backsector)) - goto blocked; - } + if (lineside) + { + if (K_BotHatesThisSector(globalsmuggle.botmo->player, line->frontsector, pos.x, pos.y)) + goto blocked; + } + else + { + if (K_BotHatesThisSector(globalsmuggle.botmo->player, line->backsector, pos.x, pos.y)) + goto blocked; } // We weren't blocked! diff --git a/src/k_kart.c b/src/k_kart.c index 2aaff27ee..9b1119341 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2367,49 +2367,7 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) { if (K_PlayerUsesBotMovement(player)) { - fixed_t rubberband = K_BotRubberband(player); - - if (rubberband < FRACUNIT) - { - rubberband = FRACUNIT; - } - - // Only allow you to go fast if you're facing the right direction - if (rubberband > FRACUNIT && player->mo != NULL && player->nextwaypoint != NULL) - { - const INT16 mindiff = 30; - const INT16 maxdiff = 60; - INT16 anglediff = 0; - fixed_t amt = rubberband - FRACUNIT; - angle_t destangle = R_PointToAngle2( - player->mo->x, player->mo->y, - player->nextwaypoint->mobj->x, player->nextwaypoint->mobj->y - ); - angle_t angle = player->mo->angle - destangle; - - if (angle < ANGLE_180) - { - anglediff = AngleFixed(angle) >> FRACBITS; - } - else - { - anglediff = 360 - (AngleFixed(angle) >> FRACBITS); - } - - anglediff = abs(anglediff); - - if (anglediff >= maxdiff) - { - rubberband = FRACUNIT; - } - else if (anglediff > mindiff) - { - amt = (amt * (maxdiff - anglediff)) / mindiff; - rubberband = FRACUNIT + amt; - } - } - - finalspeed = FixedMul(finalspeed, rubberband); + finalspeed = FixedMul(finalspeed, K_BotTopSpeedRubberband(player)); } return FixedMul(finalspeed, player->kartstuff[k_boostpower]+player->kartstuff[k_speedboost]); @@ -9471,9 +9429,17 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I if (players[tab[i].num].spectator || !players[tab[i].num].mo) continue; //ignore them. - if (netgame // don't draw it offline - && ( tab[i].num != serverplayer || ! server_lagless )) - HU_drawPing(x + ((i < 8) ? -17 : rightoffset + 11), y-4, playerpingtable[tab[i].num], 0); + if (netgame) // don't draw ping offline + { + if (players[tab[i].num].bot) + { + ; // TODO: Put a graphic here to indicate this player is a bot! + } + else if (tab[i].num != serverplayer || !server_lagless) + { + HU_drawPing(x + ((i < 8) ? -17 : rightoffset + 11), y-4, playerpingtable[tab[i].num], 0); + } + } STRBUFCPY(strtime, tab[i].name); diff --git a/src/k_pwrlv.c b/src/k_pwrlv.c index 20810a7f5..ee7c28849 100644 --- a/src/k_pwrlv.c +++ b/src/k_pwrlv.c @@ -327,9 +327,10 @@ void K_PlayerForfeit(UINT8 playernum, boolean pointloss) if (i == playernum) continue; - theirpower = PWRLVRECORD_DEF; - if (clientpowerlevels[i][powertype] != 0) // No power level acts as 5000 (used for splitscreen guests) - theirpower = clientpowerlevels[i][powertype]; + if (clientpowerlevels[i][powertype] == 0) // No power level (splitscreen guests, bots) + continue; + + theirpower = clientpowerlevels[i][powertype]; diff = yourpower - theirpower; inc -= K_CalculatePowerLevelInc(diff); diff --git a/src/p_user.c b/src/p_user.c index 12050ae11..7ff53aaed 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4177,11 +4177,16 @@ static void P_3dMovement(player_t *player) if (K_PlayerUsesBotMovement(player)) { - fixed_t rubberband = K_BotRubberband(player); + fixed_t baserubberband = K_BotRubberband(player); + fixed_t rubberband = FixedMul(baserubberband, + FixedMul(baserubberband, + FixedMul(baserubberband, + baserubberband + ))); // This looks extremely goofy, but we need this really high, but at the same time, proportional. if (rubberband > FRACUNIT) { - div = FixedMul(div, 4*rubberband); + div = FixedMul(div, rubberband); } } diff --git a/src/y_inter.c b/src/y_inter.c index aafb2383c..7121bf404 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -983,9 +983,11 @@ static void K_UpdatePowerLevels(void) continue; } - theirpower = PWRLVRECORD_DEF; - if (clientpowerlevels[jpnum][powertype] != 0) // No power level acts as 5000 (used for splitscreen guests) - theirpower = clientpowerlevels[jpnum][powertype]; + if (clientpowerlevels[jpnum][powertype] == 0) // No power level (splitscreen guests, bots) + continue; + + theirpower = clientpowerlevels[jpnum][powertype]; + CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", jpnum, theirpower); if (G_RaceGametype()) @@ -1025,9 +1027,11 @@ static void K_UpdatePowerLevels(void) CONS_Debug(DBG_GAMELOGIC, "Player %d VS Player %d (griefer):\n", ipnum, jpnum); - theirpower = PWRLVRECORD_DEF; - if (nospectategrief[jpnum] != 0) // No power level acts as 5000 (used for splitscreen guests) - theirpower = nospectategrief[jpnum]; + if (nospectategrief[jpnum] == 0) // No power level (splitscreen guests, bots) + continue; + + theirpower = nospectategrief[jpnum]; + CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", jpnum, theirpower); diff = theirpower - yourpower;