Don't turn players more than they're allowed to

This should account for latency properly.
This commit is contained in:
fickleheart 2019-01-04 23:08:33 -06:00
parent 12b0e7d5da
commit bd36a0f0a1
6 changed files with 52 additions and 4 deletions

View file

@ -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 { // 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) switch (netbuffer->packettype)
{ {

View file

@ -415,6 +415,8 @@ typedef struct player_s
// SRB2kart stuff // SRB2kart stuff
INT32 kartstuff[NUMKARTSTUFF]; INT32 kartstuff[NUMKARTSTUFF];
angle_t frameangle; // for the player add the ability to have the sprite only face other angles 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. // Bit flags.
// See pflags_t, above. // See pflags_t, above.

View file

@ -21,6 +21,8 @@
#pragma interface #pragma interface
#endif #endif
#define MAXPREDICTTICS 12
// Button/action code definitions. // Button/action code definitions.
typedef enum typedef enum
{ {

View file

@ -1202,7 +1202,7 @@ boolean camspin, camspin2, camspin3, camspin4;
static fixed_t forwardmove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16}; static fixed_t forwardmove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16};
static fixed_t sidemove[2] = {2<<FRACBITS>>16, 4<<FRACBITS>>16}; static fixed_t sidemove[2] = {2<<FRACBITS>>16, 4<<FRACBITS>>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) void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
{ {

View file

@ -9,6 +9,8 @@
#include "doomdef.h" #include "doomdef.h"
#include "d_player.h" // Need for player_t #include "d_player.h" // Need for player_t
#define KART_FULLTURN 800
UINT8 colortranslations[MAXSKINCOLORS][16]; UINT8 colortranslations[MAXSKINCOLORS][16];
extern const char *KartColor_Names[MAXSKINCOLORS]; extern const char *KartColor_Names[MAXSKINCOLORS];
extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2]; extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2];

View file

@ -6633,8 +6633,50 @@ static void P_MovePlayer(player_t *player)
P_2dMovement(player); P_2dMovement(player);
else*/ else*/
{ {
if (!player->climbing && (!P_AnalogMove(player))) INT16 angle_diff, max_left_turn, max_right_turn;
player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */); 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++; ticruned++;
if ((cmd->angleturn & TICCMD_RECEIVED) == 0) if ((cmd->angleturn & TICCMD_RECEIVED) == 0)