From a8ef3d0204290795e404e62b1af32bffe4f1403f Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sat, 21 Jun 2025 04:08:29 -0400 Subject: [PATCH 1/4] Slow down bots on straightaways (reinventing the accel wheel) --- src/d_player.h | 1 + src/k_bot.cpp | 9 +++++++++ src/k_bot.h | 4 ++++ src/k_hud.cpp | 1 + src/p_saveg.cpp | 4 +++- 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/d_player.h b/src/d_player.h index 5cb2f7afc..5e2dddb0b 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -430,6 +430,7 @@ struct botvars_t tic_t rouletteTimeout; // If it takes too long to decide, try lowering priority until we find something valid. angle_t predictionError; // How bad is our momentum angle relative to where we're trying to go? + INT16 straightawayTime; // How long have we been going straight? (See k_bot.h) }; // player_t struct for round-specific condition tracking diff --git a/src/k_bot.cpp b/src/k_bot.cpp index 3918a2e6b..ce321c43f 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -823,6 +823,7 @@ fixed_t K_BotRubberband(const player_t *player) fixed_t K_UpdateRubberband(player_t *player) { fixed_t dest = K_BotRubberband(player); + dest = (player->botvars.straightawayTime > 0) ? FixedMul(BOTSTRAIGHTSTRENGTH, dest) : dest; fixed_t ret = player->botvars.rubberband; UINT8 ease_soften = 8; @@ -2123,6 +2124,14 @@ void K_UpdateBotGameplayVars(player_t *player) } } + if (player->botvars.predictionError <= BOTSTRAIGHTANGLE) + player->botvars.straightawayTime++; + else + player->botvars.straightawayTime -= 5; + + player->botvars.straightawayTime = std::min(player->botvars.straightawayTime, BOTSTRAIGHTTIME); + player->botvars.straightawayTime = std::max(player->botvars.straightawayTime, -1 * BOTSTRAIGHTTIME); + const botcontroller_t *botController = K_GetBotController(player->mo); if (K_TryRingShooter(player, botController) == true) { diff --git a/src/k_bot.h b/src/k_bot.h index 6044bbd92..ac3092c8b 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -46,6 +46,10 @@ extern "C" { // How long it takes for a Lv.1 bot to decide to pick an item. #define BOT_ITEM_DECISION_TIME (2*TICRATE) +#define BOTSTRAIGHTTIME (TICRATE/2) +#define BOTSTRAIGHTSTRENGTH (85*FRACUNIT/100) +#define BOTSTRAIGHTANGLE (ANG10) + // Point for bots to aim for struct botprediction_t { diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 1bf954bec..1a39d56b2 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -7096,6 +7096,7 @@ static void K_DrawBotDebugger(void) V_DrawSmallString(8, 70, 0, va("Bot modifier: %.2f", FixedToFloat(K_BotMapModifier()))); V_DrawSmallString(8, 76, 0, va("Prediction error: %d", bot->botvars.predictionError)); + V_DrawSmallString(8, 80, 0, va("Straight: %d", bot->botvars.straightawayTime)); } static void K_DrawGPRankDebugger(void) diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 8e6bcc6e8..e0c2d88b9 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -756,7 +756,8 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT32(save->p, players[i].botvars.spindashconfirm); WRITEUINT32(save->p, players[i].botvars.respawnconfirm); WRITEUINT8(save->p, players[i].botvars.roulettePriority); - WRITEUINT32(save->p, players[i].botvars.rouletteTimeout); + WRITEINT32(save->p, players[i].botvars.rouletteTimeout); + WRITEINT16(save->p, players[i].botvars.straightawayTime); // itemroulette_t WRITEUINT8(save->p, players[i].itemRoulette.active); @@ -1409,6 +1410,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].botvars.respawnconfirm = READUINT32(save->p); players[i].botvars.roulettePriority = READUINT8(save->p); players[i].botvars.rouletteTimeout = READUINT32(save->p); + players[i].botvars.straightawayTime = READINT16(save->p); // itemroulette_t players[i].itemRoulette.active = (boolean)READUINT8(save->p); From d4c8fac82d9f75099f6dc16a7c336a578f660ef1 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sat, 21 Jun 2025 19:23:39 -0400 Subject: [PATCH 2/4] Straight slowdown attempt 2: use momentum angle --- src/d_player.h | 3 ++- src/k_bot.cpp | 35 ++++++++++++++++++++++++++--------- src/k_bot.h | 9 +++++---- src/k_hud.cpp | 4 ++-- src/p_saveg.cpp | 8 ++++++-- src/p_slopes.c | 8 ++++++-- 6 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 5e2dddb0b..16339b32a 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -430,7 +430,8 @@ struct botvars_t tic_t rouletteTimeout; // If it takes too long to decide, try lowering priority until we find something valid. angle_t predictionError; // How bad is our momentum angle relative to where we're trying to go? - INT16 straightawayTime; // How long have we been going straight? (See k_bot.h) + angle_t recentDeflection; // How long have we been going straight? (See k_bot.h) + angle_t lastAngle; }; // player_t struct for round-specific condition tracking diff --git a/src/k_bot.cpp b/src/k_bot.cpp index ce321c43f..d1f64f150 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -586,7 +586,7 @@ const botcontroller_t *K_GetBotController(const mobj_t *mobj) fixed_t K_BotMapModifier(void) { // fuck it we ball - // return 10*FRACUNIT/10; + return 5*FRACUNIT/10; constexpr INT32 complexity_scale = 10000; fixed_t modifier_max = (10 * FRACUNIT / 10) - FRACUNIT; @@ -690,9 +690,9 @@ fixed_t K_BotRubberband(const player_t *player) // Allow the status quo to assert itself a bit. Bots get most of their speed from their // mechanics adjustments, not from items, so kill some bot speed if they've got bad EXP. - if (player->gradingfactor < FRACUNIT && !(player->botvars.rival)) + if (player->gradingfactor < FRACUNIT && !(player->botvars.rival) && player->botvars.difficulty > 1) { - UINT8 levelreduce = 3; // How much to drop the "effective level" of bots that are consistently behind + UINT8 levelreduce = std::min(3, player->botvars.difficulty); // How much to drop the "effective level" of bots that are consistently behind expreduce = Easing_Linear((K_EffectiveGradingFactor(player) - MINGRADINGFACTOR) * 2, levelreduce*FRACUNIT, 0); } @@ -823,7 +823,17 @@ fixed_t K_BotRubberband(const player_t *player) fixed_t K_UpdateRubberband(player_t *player) { fixed_t dest = K_BotRubberband(player); - dest = (player->botvars.straightawayTime > 0) ? FixedMul(BOTSTRAIGHTSTRENGTH, dest) : dest; + + fixed_t deflect = player->botvars.recentDeflection; + if (deflect > BOTMAXDEFLECTION) + deflect = BOTMAXDEFLECTION; + + dest = FixedMul(dest, Easing_Linear( + FixedDiv(deflect, BOTMAXDEFLECTION), + BOTSTRAIGHTSPEED, + BOTTURNSPEED + )); + fixed_t ret = player->botvars.rubberband; UINT8 ease_soften = 8; @@ -2124,13 +2134,20 @@ void K_UpdateBotGameplayVars(player_t *player) } } - if (player->botvars.predictionError <= BOTSTRAIGHTANGLE) - player->botvars.straightawayTime++; + angle_t mangle = K_MomentumAngleEx(player->mo, 5*mapobjectscale); // magic threshold + angle_t langle = player->botvars.lastAngle; + angle_t dangle = 0; + if (mangle >= langle) + dangle = mangle - langle; else - player->botvars.straightawayTime -= 5; + dangle = langle - mangle; + // Writing this made me move my tongue around in my mouth - player->botvars.straightawayTime = std::min(player->botvars.straightawayTime, BOTSTRAIGHTTIME); - player->botvars.straightawayTime = std::max(player->botvars.straightawayTime, -1 * BOTSTRAIGHTTIME); + UINT32 smo = BOTANGLESAMPLES - 1; + + player->botvars.recentDeflection = (smo * player->botvars.recentDeflection / BOTANGLESAMPLES) + (dangle / BOTANGLESAMPLES); + + player->botvars.lastAngle = mangle; const botcontroller_t *botController = K_GetBotController(player->mo); if (K_TryRingShooter(player, botController) == true) diff --git a/src/k_bot.h b/src/k_bot.h index ac3092c8b..e58e4e8be 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -35,7 +35,7 @@ extern "C" { // 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 4 +#define BOTTURNCONFIRM 1 // How many tics with only one spindash-viable condition before we'll let you spindash. #define BOTSPINDASHCONFIRM (4*TICRATE) @@ -46,9 +46,10 @@ extern "C" { // How long it takes for a Lv.1 bot to decide to pick an item. #define BOT_ITEM_DECISION_TIME (2*TICRATE) -#define BOTSTRAIGHTTIME (TICRATE/2) -#define BOTSTRAIGHTSTRENGTH (85*FRACUNIT/100) -#define BOTSTRAIGHTANGLE (ANG10) +#define BOTSTRAIGHTSPEED (80*FRACUNIT/100) // How fast we move when at 0 deflection. +#define BOTTURNSPEED (100*FRACUNIT/100) // How fast we move when at MAXDEFLECTION deflection. +#define BOTANGLESAMPLES (TICRATE) // Time period to average over. Higher values produce lower peaks that last longer. +#define BOTMAXDEFLECTION (ANG1*3) // Measured in "degrees per tic" here, use debugbots. // Point for bots to aim for struct botprediction_t diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 1a39d56b2..de8e97208 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -7095,8 +7095,8 @@ static void K_DrawBotDebugger(void) V_DrawSmallString(8, 66, 0, va("Complexity: %d", K_GetTrackComplexity())); V_DrawSmallString(8, 70, 0, va("Bot modifier: %.2f", FixedToFloat(K_BotMapModifier()))); - V_DrawSmallString(8, 76, 0, va("Prediction error: %d", bot->botvars.predictionError)); - V_DrawSmallString(8, 80, 0, va("Straight: %d", bot->botvars.straightawayTime)); + V_DrawSmallString(8, 76, 0, va("Prediction error: %.2fdeg", FIXED_TO_FLOAT(FixedDiv(bot->botvars.predictionError, ANG1)))); + V_DrawSmallString(8, 80, 0, va("Recent deflection: %.2fdeg", FIXED_TO_FLOAT(FixedDiv(bot->botvars.recentDeflection, ANG1)))); } static void K_DrawGPRankDebugger(void) diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index e0c2d88b9..98e544cd4 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -757,7 +757,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT32(save->p, players[i].botvars.respawnconfirm); WRITEUINT8(save->p, players[i].botvars.roulettePriority); WRITEINT32(save->p, players[i].botvars.rouletteTimeout); - WRITEINT16(save->p, players[i].botvars.straightawayTime); + WRITEUINT32(save->p, players[i].botvars.predictionError); + WRITEUINT32(save->p, players[i].botvars.recentDeflection); + WRITEUINT32(save->p, players[i].botvars.lastAngle); // itemroulette_t WRITEUINT8(save->p, players[i].itemRoulette.active); @@ -1410,7 +1412,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].botvars.respawnconfirm = READUINT32(save->p); players[i].botvars.roulettePriority = READUINT8(save->p); players[i].botvars.rouletteTimeout = READUINT32(save->p); - players[i].botvars.straightawayTime = READINT16(save->p); + players[i].botvars.predictionError = READUINT32(save->p); + players[i].botvars.recentDeflection = READUINT32(save->p); + players[i].botvars.lastAngle = READUINT32(save->p); // itemroulette_t players[i].itemRoulette.active = (boolean)READUINT8(save->p); diff --git a/src/p_slopes.c b/src/p_slopes.c index 7ae2567bd..aca454f3a 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1206,11 +1206,15 @@ void P_ButteredSlope(mobj_t *mo) // Let's get the gravity strength for the object... thrust = FixedMul(thrust, abs(P_GetMobjGravity(mo))); - if (mo->friction != ORIG_FRICTION) + fixed_t basefriction = ORIG_FRICTION; + if (mo->player && false) + basefriction = K_PlayerBaseFriction(mo->player, ORIG_FRICTION); + + if (mo->friction != basefriction && basefriction != 0) { // ... and its friction against the ground for good measure. // (divided by original friction to keep behaviour for normal slopes the same) - thrust = FixedMul(thrust, FixedDiv(mo->friction, ORIG_FRICTION)); + thrust = FixedMul(thrust, FixedDiv(mo->friction, basefriction)); // Sal: Also consider movefactor of players. // We want ice to make slopes *really* funnel you in a specific direction. From 63b55c0abd794db5b14b5182f896307401354574 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sat, 21 Jun 2025 23:55:28 -0400 Subject: [PATCH 3/4] oni fuckup vol69 --- src/k_bot.cpp | 6 +++--- src/p_slopes.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_bot.cpp b/src/k_bot.cpp index d1f64f150..3caab89e7 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -836,10 +836,10 @@ fixed_t K_UpdateRubberband(player_t *player) fixed_t ret = player->botvars.rubberband; - UINT8 ease_soften = 8; + UINT8 ease_soften = (ret > dest) ? 3 : 8; if (player->botvars.bumpslow && dest > ret) - ease_soften *= 10; + ease_soften = 80; // Ease into the new value. ret += (dest - player->botvars.rubberband) / ease_soften; @@ -2146,7 +2146,7 @@ void K_UpdateBotGameplayVars(player_t *player) UINT32 smo = BOTANGLESAMPLES - 1; player->botvars.recentDeflection = (smo * player->botvars.recentDeflection / BOTANGLESAMPLES) + (dangle / BOTANGLESAMPLES); - + player->botvars.lastAngle = mangle; const botcontroller_t *botController = K_GetBotController(player->mo); diff --git a/src/p_slopes.c b/src/p_slopes.c index aca454f3a..a64ebfaa0 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1207,7 +1207,7 @@ void P_ButteredSlope(mobj_t *mo) thrust = FixedMul(thrust, abs(P_GetMobjGravity(mo))); fixed_t basefriction = ORIG_FRICTION; - if (mo->player && false) + if (mo->player) basefriction = K_PlayerBaseFriction(mo->player, ORIG_FRICTION); if (mo->friction != basefriction && basefriction != 0) From 96d78eeb0ffc39955c07657159db614d523e9f22 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Sun, 22 Jun 2025 00:15:25 -0400 Subject: [PATCH 4/4] Slow down bots tethering to other bots --- src/k_kart.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 9caf07617..856db5f9d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1607,13 +1607,16 @@ static boolean K_TryDraft(player_t *player, mobj_t *dest, fixed_t minDist, fixed // How much this increments every tic biases toward acceleration! (min speed gets 1.5% per tic, max speed gets 0.5% per tic) if (player->draftpower < FRACUNIT) { - fixed_t add = (FRACUNIT/200) + ((9 - player->kartspeed) * ((3*FRACUNIT)/1600));; + fixed_t add = (FRACUNIT/200) + ((9 - player->kartspeed) * ((3*FRACUNIT)/1600)); player->draftpower += add; - if (player->bot && (player->botvars.rival || cv_levelskull.value)) + if (player->bot) { // Double speed for the rival! - player->draftpower += add; + if (player->botvars.rival || cv_levelskull.value) + player->draftpower += add; + else if (dest->player->bot) // Reduce bot gluts. + player->draftpower -= 3*add/4; } if (gametyperules & GTR_CLOSERPLAYERS)