mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +00:00
Merge branch 'multi' of https://github.com/Edward850/zdoom
This commit is contained in:
commit
952d03da7c
9 changed files with 203 additions and 66 deletions
|
@ -39,7 +39,6 @@
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
#include "m_cheat.h"
|
#include "m_cheat.h"
|
||||||
#include "p_effect.h"
|
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
#include "sbar.h"
|
#include "sbar.h"
|
||||||
|
@ -670,6 +669,9 @@ void PlayerIsGone (int netnode, int netconsole)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!nodeingame[netnode])
|
||||||
|
return;
|
||||||
|
|
||||||
for (i = netnode + 1; i < doomcom.numnodes; ++i)
|
for (i = netnode + 1; i < doomcom.numnodes; ++i)
|
||||||
{
|
{
|
||||||
if (nodeingame[i])
|
if (nodeingame[i])
|
||||||
|
@ -680,77 +682,40 @@ void PlayerIsGone (int netnode, int netconsole)
|
||||||
doomcom.numnodes = netnode;
|
doomcom.numnodes = netnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (playeringame[netconsole])
|
||||||
|
{
|
||||||
|
players[netconsole].playerstate = PST_GONE;
|
||||||
|
}
|
||||||
nodeingame[netnode] = false;
|
nodeingame[netnode] = false;
|
||||||
playeringame[netconsole] = false;
|
|
||||||
nodejustleft[netnode] = false;
|
nodejustleft[netnode] = false;
|
||||||
|
|
||||||
if (deathmatch)
|
|
||||||
{
|
|
||||||
Printf ("%s left the game with %d frags\n",
|
|
||||||
players[netconsole].userinfo.GetName(),
|
|
||||||
players[netconsole].fragcount);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Printf ("%s left the game\n", players[netconsole].userinfo.GetName());
|
|
||||||
}
|
|
||||||
|
|
||||||
// [RH] Revert each player to their own view if spying through the player who left
|
|
||||||
for (int ii = 0; ii < MAXPLAYERS; ++ii)
|
|
||||||
{
|
|
||||||
if (playeringame[ii] && players[ii].camera == players[netconsole].mo)
|
|
||||||
{
|
|
||||||
players[ii].camera = players[ii].mo;
|
|
||||||
if (ii == consoleplayer && StatusBar != NULL)
|
|
||||||
{
|
|
||||||
StatusBar->AttachToPlayer (&players[ii]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// [RH] Make the player disappear
|
|
||||||
FBehavior::StaticStopMyScripts (players[netconsole].mo);
|
|
||||||
if (players[netconsole].mo != NULL)
|
|
||||||
{
|
|
||||||
P_DisconnectEffect (players[netconsole].mo);
|
|
||||||
players[netconsole].mo->player = NULL;
|
|
||||||
players[netconsole].mo->Destroy ();
|
|
||||||
if (!(players[netconsole].mo->ObjectFlags & OF_EuthanizeMe))
|
|
||||||
{ // We just destroyed a morphed player, so now the original player
|
|
||||||
// has taken their place. Destroy that one too.
|
|
||||||
players[netconsole].mo->Destroy();
|
|
||||||
}
|
|
||||||
players[netconsole].mo = NULL;
|
|
||||||
players[netconsole].camera = NULL;
|
|
||||||
}
|
|
||||||
// [RH] Let the scripts know the player left
|
|
||||||
FBehavior::StaticStartTypedScripts (SCRIPT_Disconnect, NULL, true, netconsole);
|
|
||||||
if (netconsole == Net_Arbitrator)
|
if (netconsole == Net_Arbitrator)
|
||||||
{
|
{
|
||||||
bglobal.RemoveAllBots (true);
|
bglobal.RemoveAllBots(true);
|
||||||
Printf ("Removed all bots\n");
|
Printf("Removed all bots\n");
|
||||||
|
|
||||||
// Pick a new network arbitrator
|
// Pick a new network arbitrator
|
||||||
for (int i = 0; i < MAXPLAYERS; i++)
|
for (int i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && !players[i].isbot)
|
if (i != netconsole && playeringame[i] && !players[i].isbot)
|
||||||
{
|
{
|
||||||
Net_Arbitrator = i;
|
Net_Arbitrator = i;
|
||||||
players[i].settings_controller = true;
|
players[i].settings_controller = true;
|
||||||
Printf ("%s is the new arbitrator\n", players[i].userinfo.GetName());
|
Printf("%s is the new arbitrator\n", players[i].userinfo.GetName());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (debugfile && NetMode == NET_PacketServer)
|
}
|
||||||
|
|
||||||
|
if (debugfile && NetMode == NET_PacketServer)
|
||||||
|
{
|
||||||
|
if (Net_Arbitrator == consoleplayer)
|
||||||
{
|
{
|
||||||
if (Net_Arbitrator == consoleplayer)
|
fprintf(debugfile, "I am the new master!\n");
|
||||||
{
|
}
|
||||||
fprintf (debugfile, "I am the new master!\n");
|
else
|
||||||
}
|
{
|
||||||
else
|
fprintf(debugfile, "Node %d is the new master!\n", nodeforplayer[Net_Arbitrator]);
|
||||||
{
|
|
||||||
fprintf (debugfile, "Node %d is the new master!\n", nodeforplayer[Net_Arbitrator]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1760,10 +1725,19 @@ void D_CheckNetGame (void)
|
||||||
resendto[i] = 0; // which tic to start sending
|
resendto[i] = 0; // which tic to start sending
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Packet server has proven to be rather slow over the internet. Print a warning about it.
|
||||||
|
v = Args->CheckValue("-netmode");
|
||||||
|
if (v != NULL && (atoi(v) != 0))
|
||||||
|
{
|
||||||
|
Printf(TEXTCOLOR_YELLOW "Notice: Using PacketServer (netmode 1) over the internet is prone to running too slow on some internet configurations."
|
||||||
|
"\nIf the game is running well below excpected speeds, use netmode 0 (P2P) instead.\n");
|
||||||
|
}
|
||||||
|
|
||||||
// I_InitNetwork sets doomcom and netgame
|
// I_InitNetwork sets doomcom and netgame
|
||||||
if (I_InitNetwork ())
|
if (I_InitNetwork ())
|
||||||
{
|
{
|
||||||
NetMode = NET_PacketServer;
|
// For now, stop auto selecting PacketServer, as it's more likely to cause confusion.
|
||||||
|
//NetMode = NET_PacketServer;
|
||||||
}
|
}
|
||||||
if (doomcom.id != DOOMCOM_ID)
|
if (doomcom.id != DOOMCOM_ID)
|
||||||
{
|
{
|
||||||
|
|
|
@ -174,7 +174,8 @@ typedef enum
|
||||||
PST_LIVE, // Playing or camping.
|
PST_LIVE, // Playing or camping.
|
||||||
PST_DEAD, // Dead on the ground, view follows killer.
|
PST_DEAD, // Dead on the ground, view follows killer.
|
||||||
PST_REBORN, // Ready to restart/respawn???
|
PST_REBORN, // Ready to restart/respawn???
|
||||||
PST_ENTER // [BC] Entered the game
|
PST_ENTER, // [BC] Entered the game
|
||||||
|
PST_GONE // Player has left the game
|
||||||
} playerstate_t;
|
} playerstate_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
#include "d_net.h"
|
#include "d_net.h"
|
||||||
#include "d_event.h"
|
#include "d_event.h"
|
||||||
#include "p_acs.h"
|
#include "p_acs.h"
|
||||||
|
#include "p_effect.h"
|
||||||
#include "m_joy.h"
|
#include "m_joy.h"
|
||||||
#include "farchive.h"
|
#include "farchive.h"
|
||||||
#include "r_renderer.h"
|
#include "r_renderer.h"
|
||||||
|
@ -1013,10 +1014,16 @@ void G_Ticker ()
|
||||||
// do player reborns if needed
|
// do player reborns if needed
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] &&
|
if (playeringame[i])
|
||||||
(players[i].playerstate == PST_REBORN || players[i].playerstate == PST_ENTER))
|
|
||||||
{
|
{
|
||||||
G_DoReborn (i, false);
|
if ((players[i].playerstate == PST_GONE))
|
||||||
|
{
|
||||||
|
G_DoPlayerPop(i);
|
||||||
|
}
|
||||||
|
if ((players[i].playerstate == PST_REBORN || players[i].playerstate == PST_ENTER))
|
||||||
|
{
|
||||||
|
G_DoReborn(i, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1658,6 +1665,56 @@ void G_DoReborn (int playernum, bool freshbot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// G_DoReborn
|
||||||
|
//
|
||||||
|
void G_DoPlayerPop(int playernum)
|
||||||
|
{
|
||||||
|
playeringame[playernum] = false;
|
||||||
|
|
||||||
|
if (deathmatch)
|
||||||
|
{
|
||||||
|
Printf("%s left the game with %d frags\n",
|
||||||
|
players[playernum].userinfo.GetName(),
|
||||||
|
players[playernum].fragcount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printf("%s left the game\n", players[playernum].userinfo.GetName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// [RH] Revert each player to their own view if spying through the player who left
|
||||||
|
for (int ii = 0; ii < MAXPLAYERS; ++ii)
|
||||||
|
{
|
||||||
|
if (playeringame[ii] && players[ii].camera == players[playernum].mo)
|
||||||
|
{
|
||||||
|
players[ii].camera = players[ii].mo;
|
||||||
|
if (ii == consoleplayer && StatusBar != NULL)
|
||||||
|
{
|
||||||
|
StatusBar->AttachToPlayer(&players[ii]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// [RH] Make the player disappear
|
||||||
|
FBehavior::StaticStopMyScripts(players[playernum].mo);
|
||||||
|
if (players[playernum].mo != NULL)
|
||||||
|
{
|
||||||
|
P_DisconnectEffect(players[playernum].mo);
|
||||||
|
players[playernum].mo->player = NULL;
|
||||||
|
players[playernum].mo->Destroy();
|
||||||
|
if (!(players[playernum].mo->ObjectFlags & OF_EuthanizeMe))
|
||||||
|
{ // We just destroyed a morphed player, so now the original player
|
||||||
|
// has taken their place. Destroy that one too.
|
||||||
|
players[playernum].mo->Destroy();
|
||||||
|
}
|
||||||
|
players[playernum].mo = NULL;
|
||||||
|
players[playernum].camera = NULL;
|
||||||
|
}
|
||||||
|
// [RH] Let the scripts know the player left
|
||||||
|
FBehavior::StaticStartTypedScripts(SCRIPT_Disconnect, NULL, true, playernum);
|
||||||
|
}
|
||||||
|
|
||||||
void G_ScreenShot (char *filename)
|
void G_ScreenShot (char *filename)
|
||||||
{
|
{
|
||||||
shotfile = filename;
|
shotfile = filename;
|
||||||
|
|
|
@ -81,6 +81,7 @@ enum EFinishLevelType
|
||||||
void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags);
|
void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags);
|
||||||
|
|
||||||
void G_DoReborn (int playernum, bool freshbot);
|
void G_DoReborn (int playernum, bool freshbot);
|
||||||
|
void G_DoPlayerPop(int playernum);
|
||||||
|
|
||||||
// Adds pitch to consoleplayer's viewpitch and clamps it
|
// Adds pitch to consoleplayer's viewpitch and clamps it
|
||||||
void G_AddViewPitch (int look);
|
void G_AddViewPitch (int look);
|
||||||
|
|
|
@ -110,6 +110,7 @@ const char *neterror (void);
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PRE_CONNECT, // Sent from guest to host for initial connection
|
PRE_CONNECT, // Sent from guest to host for initial connection
|
||||||
|
PRE_KEEPALIVE,
|
||||||
PRE_DISCONNECT, // Sent from guest that aborts the game
|
PRE_DISCONNECT, // Sent from guest that aborts the game
|
||||||
PRE_ALLHERE, // Sent from host to guest when everybody has connected
|
PRE_ALLHERE, // Sent from host to guest when everybody has connected
|
||||||
PRE_CONACK, // Sent from host to guest to acknowledge PRE_CONNECT receipt
|
PRE_CONACK, // Sent from host to guest to acknowledge PRE_CONNECT receipt
|
||||||
|
@ -548,10 +549,15 @@ bool Host_CheckForConnects (void *userdata)
|
||||||
SendConAck (doomcom.numnodes, numplayers);
|
SendConAck (doomcom.numnodes, numplayers);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PRE_KEEPALIVE:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (doomcom.numnodes < numplayers)
|
if (doomcom.numnodes < numplayers)
|
||||||
{
|
{
|
||||||
|
// Send message to everyone as a keepalive
|
||||||
|
SendConAck(doomcom.numnodes, numplayers);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,6 +828,10 @@ bool Guest_WaitForOthers (void *userdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packet.Fake = PRE_FAKE;
|
||||||
|
packet.Message = PRE_KEEPALIVE;
|
||||||
|
PreSend(&packet, 2, &sendaddress[1]);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,7 @@ void P_FallingDamage (AActor *ent);
|
||||||
void P_PlayerThink (player_t *player);
|
void P_PlayerThink (player_t *player);
|
||||||
void P_PredictPlayer (player_t *player);
|
void P_PredictPlayer (player_t *player);
|
||||||
void P_UnPredictPlayer ();
|
void P_UnPredictPlayer ();
|
||||||
|
void P_PredictionLerpReset();
|
||||||
|
|
||||||
//
|
//
|
||||||
// P_MOBJ
|
// P_MOBJ
|
||||||
|
|
|
@ -4250,6 +4250,12 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
|
||||||
if ((unsigned)playernum >= (unsigned)MAXPLAYERS || !playeringame[playernum])
|
if ((unsigned)playernum >= (unsigned)MAXPLAYERS || !playeringame[playernum])
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
// Old lerp data needs to go
|
||||||
|
if (playernum == consoleplayer)
|
||||||
|
{
|
||||||
|
P_PredictionLerpReset();
|
||||||
|
}
|
||||||
|
|
||||||
p = &players[playernum];
|
p = &players[playernum];
|
||||||
|
|
||||||
if (p->cls == NULL)
|
if (p->cls == NULL)
|
||||||
|
|
|
@ -63,6 +63,27 @@ static FRandom pr_skullpop ("SkullPop");
|
||||||
// Variables for prediction
|
// Variables for prediction
|
||||||
CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR(Bool, cl_predict_specials, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CVAR(Bool, cl_predict_specials, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Float, cl_predict_lerpscale, 0.05f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
{
|
||||||
|
P_PredictionLerpReset();
|
||||||
|
}
|
||||||
|
CUSTOM_CVAR(Float, cl_predict_lerpthreshold, 2.00f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
{
|
||||||
|
if (self < 0.1f)
|
||||||
|
self = 0.1f;
|
||||||
|
P_PredictionLerpReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PredictPos
|
||||||
|
{
|
||||||
|
int gametic;
|
||||||
|
FVector3 point;
|
||||||
|
fixed_t pitch;
|
||||||
|
fixed_t yaw;
|
||||||
|
} static PredictionLerpFrom, PredictionLerpResult, PredictionLast;
|
||||||
|
static int PredictionLerptics;
|
||||||
|
|
||||||
static player_t PredictionPlayerBackup;
|
static player_t PredictionPlayerBackup;
|
||||||
static BYTE PredictionActorBackup[sizeof(AActor)];
|
static BYTE PredictionActorBackup[sizeof(AActor)];
|
||||||
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
||||||
|
@ -2636,6 +2657,22 @@ void P_PlayerThink (player_t *player)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void P_PredictionLerpReset()
|
||||||
|
{
|
||||||
|
PredictionLerptics = PredictionLast.gametic = PredictionLerpFrom.gametic = PredictionLerpResult.gametic = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool P_LerpCalculate(FVector3 from, FVector3 to, FVector3 &result, float scale)
|
||||||
|
{
|
||||||
|
result = to - from;
|
||||||
|
result *= scale;
|
||||||
|
result = result + from;
|
||||||
|
FVector3 delta = result - to;
|
||||||
|
|
||||||
|
// As a fail safe, assume extrapolation is the threshold.
|
||||||
|
return (delta.LengthSquared() > cl_predict_lerpthreshold && scale <= 1.00f);
|
||||||
|
}
|
||||||
|
|
||||||
void P_PredictPlayer (player_t *player)
|
void P_PredictPlayer (player_t *player)
|
||||||
{
|
{
|
||||||
int maxtic;
|
int maxtic;
|
||||||
|
@ -2663,8 +2700,8 @@ void P_PredictPlayer (player_t *player)
|
||||||
// Save original values for restoration later
|
// Save original values for restoration later
|
||||||
PredictionPlayerBackup = *player;
|
PredictionPlayerBackup = *player;
|
||||||
|
|
||||||
AActor *act = player->mo;
|
APlayerPawn *act = player->mo;
|
||||||
memcpy (PredictionActorBackup, &act->x, sizeof(AActor)-((BYTE *)&act->x-(BYTE *)act));
|
memcpy(PredictionActorBackup, &act->x, sizeof(APlayerPawn) - ((BYTE *)&act->x - (BYTE *)act));
|
||||||
|
|
||||||
act->flags &= ~MF_PICKUP;
|
act->flags &= ~MF_PICKUP;
|
||||||
act->flags2 &= ~MF2_PUSHWALL;
|
act->flags2 &= ~MF2_PUSHWALL;
|
||||||
|
@ -2721,7 +2758,8 @@ void P_PredictPlayer (player_t *player)
|
||||||
}
|
}
|
||||||
act->BlockNode = NULL;
|
act->BlockNode = NULL;
|
||||||
|
|
||||||
bool NoInterpolateOld = R_GetViewInterpolationStatus();
|
// Values too small to be usable for lerping can be considered "off".
|
||||||
|
bool CanLerp = (!(cl_predict_lerpscale < 0.01f) && (ticdup == 1)), DoLerp = false, NoInterpolateOld = R_GetViewInterpolationStatus();
|
||||||
for (int i = gametic; i < maxtic; ++i)
|
for (int i = gametic; i < maxtic; ++i)
|
||||||
{
|
{
|
||||||
if (!NoInterpolateOld)
|
if (!NoInterpolateOld)
|
||||||
|
@ -2730,6 +2768,47 @@ void P_PredictPlayer (player_t *player)
|
||||||
player->cmd = localcmds[i % LOCALCMDTICS];
|
player->cmd = localcmds[i % LOCALCMDTICS];
|
||||||
P_PlayerThink (player);
|
P_PlayerThink (player);
|
||||||
player->mo->Tick ();
|
player->mo->Tick ();
|
||||||
|
|
||||||
|
if (CanLerp && PredictionLast.gametic > 0 && i == PredictionLast.gametic && !NoInterpolateOld)
|
||||||
|
{
|
||||||
|
// Z is not compared as lifts will alter this with no apparent change
|
||||||
|
DoLerp = (PredictionLast.point.X != FIXED2FLOAT(player->mo->x) ||
|
||||||
|
PredictionLast.point.Y != FIXED2FLOAT(player->mo->y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CanLerp)
|
||||||
|
{
|
||||||
|
if (NoInterpolateOld)
|
||||||
|
P_PredictionLerpReset();
|
||||||
|
|
||||||
|
else if (DoLerp)
|
||||||
|
{
|
||||||
|
// If lerping is already in effect, use the previous camera postion so the view doesn't suddenly snap
|
||||||
|
PredictionLerpFrom = (PredictionLerptics == 0) ? PredictionLast : PredictionLerpResult;
|
||||||
|
PredictionLerptics = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PredictionLast.gametic = maxtic - 1;
|
||||||
|
PredictionLast.point.X = FIXED2FLOAT(player->mo->x);
|
||||||
|
PredictionLast.point.Y = FIXED2FLOAT(player->mo->y);
|
||||||
|
PredictionLast.point.Z = FIXED2FLOAT(player->mo->z);
|
||||||
|
|
||||||
|
if (PredictionLerptics > 0)
|
||||||
|
{
|
||||||
|
if (PredictionLerpFrom.gametic > 0 &&
|
||||||
|
P_LerpCalculate(PredictionLerpFrom.point, PredictionLast.point, PredictionLerpResult.point, (float)PredictionLerptics * cl_predict_lerpscale))
|
||||||
|
{
|
||||||
|
PredictionLerptics++;
|
||||||
|
player->mo->x = FLOAT2FIXED(PredictionLerpResult.point.X);
|
||||||
|
player->mo->y = FLOAT2FIXED(PredictionLerpResult.point.Y);
|
||||||
|
player->mo->z = FLOAT2FIXED(PredictionLerpResult.point.Z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PredictionLerptics = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2742,9 +2821,12 @@ void P_UnPredictPlayer ()
|
||||||
if (player->cheats & CF_PREDICTING)
|
if (player->cheats & CF_PREDICTING)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
AActor *act = player->mo;
|
APlayerPawn *act = player->mo;
|
||||||
AActor *savedcamera = player->camera;
|
AActor *savedcamera = player->camera;
|
||||||
|
|
||||||
|
TObjPtr<AInventory> InvSel = act->InvSel;
|
||||||
|
int inventorytics = player->inventorytics;
|
||||||
|
|
||||||
*player = PredictionPlayerBackup;
|
*player = PredictionPlayerBackup;
|
||||||
|
|
||||||
// Restore the camera instead of using the backup's copy, because spynext/prev
|
// Restore the camera instead of using the backup's copy, because spynext/prev
|
||||||
|
@ -2752,7 +2834,7 @@ void P_UnPredictPlayer ()
|
||||||
player->camera = savedcamera;
|
player->camera = savedcamera;
|
||||||
|
|
||||||
act->UnlinkFromWorld();
|
act->UnlinkFromWorld();
|
||||||
memcpy(&act->x, PredictionActorBackup, sizeof(AActor)-((BYTE *)&act->x - (BYTE *)act));
|
memcpy(&act->x, PredictionActorBackup, sizeof(APlayerPawn) - ((BYTE *)&act->x - (BYTE *)act));
|
||||||
|
|
||||||
// The blockmap ordering needs to remain unchanged, too.
|
// The blockmap ordering needs to remain unchanged, too.
|
||||||
// Restore sector links and refrences.
|
// Restore sector links and refrences.
|
||||||
|
@ -2857,6 +2939,9 @@ void P_UnPredictPlayer ()
|
||||||
}
|
}
|
||||||
block = block->NextBlock;
|
block = block->NextBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
act->InvSel = InvSel;
|
||||||
|
player->inventorytics = inventorytics;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1613,6 +1613,8 @@ OptionMenu NetworkOptions
|
||||||
StaticText "Local options", 1
|
StaticText "Local options", 1
|
||||||
Option "Movement prediction", "cl_noprediction", "OffOn"
|
Option "Movement prediction", "cl_noprediction", "OffOn"
|
||||||
Option "Predict line actions", "cl_predict_specials", "OnOff"
|
Option "Predict line actions", "cl_predict_specials", "OnOff"
|
||||||
|
Slider "Prediction Lerp Scale", "cl_predict_lerpscale", 0.0, 0.5, 0.05
|
||||||
|
Slider "Lerp Threshold", "cl_predict_lerpthreshold", 0.1, 16.0, 0.1
|
||||||
StaticText " "
|
StaticText " "
|
||||||
StaticText "Host options", 1
|
StaticText "Host options", 1
|
||||||
Option "Extra Tics", "net_extratic", "ExtraTicMode"
|
Option "Extra Tics", "net_extratic", "ExtraTicMode"
|
||||||
|
|
Loading…
Reference in a new issue