diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e05b9b44..f131ef0b 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4008,7 +4008,7 @@ FILESTAMP } { // Store the node's latency in tics on the ticcmd right as we receive it. I think this should be sync-stable - UINT8 latency = min(maketic - nettics[node], 12); //@TODO add a cvar to allow setting this max + UINT8 latency = min(maketic - nettics[node], MAXPREDICTTICS-1); //@TODO add a cvar to allow setting this max switch (netbuffer->packettype) { diff --git a/src/d_player.h b/src/d_player.h index 1b1d4d0a..2759058f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -415,6 +415,8 @@ typedef struct player_s // SRB2kart stuff INT32 kartstuff[NUMKARTSTUFF]; angle_t frameangle; // for the player add the ability to have the sprite only face other angles + INT16 lturn_max[MAXPREDICTTICS]; // What's the expected turn value for full-left for a number of frames back (to account for netgame latency)? + INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right // Bit flags. // See pflags_t, above. diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index 6524870d..dab758f8 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -21,6 +21,8 @@ #pragma interface #endif +#define MAXPREDICTTICS 12 + // Button/action code definitions. typedef enum { diff --git a/src/g_game.c b/src/g_game.c index 5b5ceb1a..9b3ba2e8 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1202,7 +1202,7 @@ boolean camspin, camspin2, camspin3, camspin4; static fixed_t forwardmove[2] = {25<>16, 50<>16}; static fixed_t sidemove[2] = {2<>16, 4<>16}; -static fixed_t angleturn[3] = {400, 800, 200}; // + slow turn +static fixed_t angleturn[3] = {KART_FULLTURN/2, KART_FULLTURN, KART_FULLTURN/4}; // + slow turn void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { diff --git a/src/k_kart.h b/src/k_kart.h index fed490db..3f712091 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -9,6 +9,8 @@ #include "doomdef.h" #include "d_player.h" // Need for player_t +#define KART_FULLTURN 800 + UINT8 colortranslations[MAXSKINCOLORS][16]; extern const char *KartColor_Names[MAXSKINCOLORS]; extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2]; diff --git a/src/p_user.c b/src/p_user.c index 853ceaf0..014110b7 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -6633,8 +6633,50 @@ static void P_MovePlayer(player_t *player) P_2dMovement(player); else*/ { - if (!player->climbing && (!P_AnalogMove(player))) - player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */); + INT16 angle_diff, max_left_turn, max_right_turn; + boolean add_delta = true; + + // Kart: store the current turn range for later use + if (((player->mo && player->speed > 0) // Moving + || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn + || (player->kartstuff[k_respawn]) // Respawning + || (player->spectator || objectplacing)) // Not a physical player + && !(player->kartstuff[k_spinouttimer] && player->kartstuff[k_sneakertimer])) // Spinning and boosting cancels out turning + { + player->lturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, KART_FULLTURN)+1; + player->rturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, -KART_FULLTURN)-1; + } else { + player->lturn_max[leveltime%MAXPREDICTTICS] = player->rturn_max[leveltime%MAXPREDICTTICS] = 0; + } + + if (leveltime >= starttime) + { + // KART: Don't directly apply angleturn! It may have been either A) forged by a malicious client, or B) not be a smooth turn due to a player dropping frames. + // Instead, turn the player only up to the amount they're supposed to turn accounting for latency. Allow exactly 1 extra turn unit to try to keep old replays synced. + angle_diff = cmd->angleturn - (player->mo->angle>>16); + max_left_turn = player->lturn_max[(leveltime + MAXPREDICTTICS - cmd->latency) % MAXPREDICTTICS]; + max_right_turn = player->rturn_max[(leveltime + MAXPREDICTTICS - cmd->latency) % MAXPREDICTTICS]; + + //CONS_Printf("----------------\nangle diff: %d - turning options: %d to %d - ", angle_diff, max_left_turn, max_right_turn); + + if (angle_diff > max_left_turn) + angle_diff = max_left_turn; + else if (angle_diff < max_right_turn) + angle_diff = max_right_turn; + else + { + // Try to keep normal turning as accurate to 1.0.1 as possible to reduce replay desyncs. + player->mo->angle = cmd->angleturn<<16; + add_delta = false; + } + //CONS_Printf("applied turn: %d\n", angle_diff); + + if (add_delta) { + player->mo->angle += angle_diff<<16; + player->mo->angle &= ~0xFFFF; // Try to keep the turning somewhat similar to how it was before? + CONS_Printf("leftover turn (%s): %d\n", player_names[player-players], (INT16) (cmd->angleturn - (player->mo->angle>>16))); + } + } ticruned++; if ((cmd->angleturn & TICCMD_RECEIVED) == 0)