mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-28 15:02:39 +00:00
Merge pull request #1 from rheit/master
Merge rheit: master into MajorCooke: master
This commit is contained in:
commit
c5db63fbbb
20 changed files with 567 additions and 65 deletions
|
@ -756,9 +756,9 @@ void D_Display ()
|
||||||
}
|
}
|
||||||
screen->SetBlendingRect(viewwindowx, viewwindowy,
|
screen->SetBlendingRect(viewwindowx, viewwindowy,
|
||||||
viewwindowx + viewwidth, viewwindowy + viewheight);
|
viewwindowx + viewwidth, viewwindowy + viewheight);
|
||||||
P_PredictPlayer(&players[consoleplayer]);
|
|
||||||
Renderer->RenderView(&players[consoleplayer]);
|
Renderer->RenderView(&players[consoleplayer]);
|
||||||
P_UnPredictPlayer();
|
|
||||||
if ((hw2d = screen->Begin2D(viewactive)))
|
if ((hw2d = screen->Begin2D(viewactive)))
|
||||||
{
|
{
|
||||||
// Redraw everything every frame when using 2D accel
|
// Redraw everything every frame when using 2D accel
|
||||||
|
|
196
src/d_net.cpp
196
src/d_net.cpp
|
@ -110,13 +110,15 @@ unsigned int lastrecvtime[MAXPLAYERS]; // [RH] Used for pings
|
||||||
unsigned int currrecvtime[MAXPLAYERS];
|
unsigned int currrecvtime[MAXPLAYERS];
|
||||||
unsigned int lastglobalrecvtime; // Identify the last time a packet was recieved.
|
unsigned int lastglobalrecvtime; // Identify the last time a packet was recieved.
|
||||||
bool hadlate;
|
bool hadlate;
|
||||||
|
int netdelay[MAXNETNODES][BACKUPTICS]; // Used for storing network delay times.
|
||||||
|
int lastaverage;
|
||||||
|
|
||||||
int nodeforplayer[MAXPLAYERS];
|
int nodeforplayer[MAXPLAYERS];
|
||||||
int playerfornode[MAXNETNODES];
|
int playerfornode[MAXNETNODES];
|
||||||
|
|
||||||
int maketic;
|
int maketic;
|
||||||
int skiptics;
|
int skiptics;
|
||||||
int ticdup;
|
int ticdup;
|
||||||
|
|
||||||
void D_ProcessEvents (void);
|
void D_ProcessEvents (void);
|
||||||
void G_BuildTiccmd (ticcmd_t *cmd);
|
void G_BuildTiccmd (ticcmd_t *cmd);
|
||||||
|
@ -151,6 +153,32 @@ CUSTOM_CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CVAR(Bool, net_ticbalance, false, CVAR_SERVERINFO | CVAR_NOSAVE)
|
||||||
|
CUSTOM_CVAR(Int, net_extratic, 0, CVAR_SERVERINFO | CVAR_NOSAVE)
|
||||||
|
{
|
||||||
|
if (self < 0)
|
||||||
|
{
|
||||||
|
self = 0;
|
||||||
|
}
|
||||||
|
else if (self > 2)
|
||||||
|
{
|
||||||
|
self = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
CVAR(Int, net_fakelatency, 0, 0);
|
||||||
|
|
||||||
|
struct PacketStore
|
||||||
|
{
|
||||||
|
int timer;
|
||||||
|
doomcom_t message;
|
||||||
|
};
|
||||||
|
|
||||||
|
static TArray<PacketStore> InBuffer;
|
||||||
|
static TArray<PacketStore> OutBuffer;
|
||||||
|
#endif
|
||||||
|
|
||||||
// [RH] Special "ticcmds" get stored in here
|
// [RH] Special "ticcmds" get stored in here
|
||||||
static struct TicSpecial
|
static struct TicSpecial
|
||||||
{
|
{
|
||||||
|
@ -347,6 +375,9 @@ int NetbufferSize ()
|
||||||
k += netbuffer[k] + 1;
|
k += netbuffer[k] + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Network delay byte
|
||||||
|
k++;
|
||||||
|
|
||||||
if (netbuffer[0] & NCMD_MULTI)
|
if (netbuffer[0] & NCMD_MULTI)
|
||||||
{
|
{
|
||||||
count = netbuffer[k];
|
count = netbuffer[k];
|
||||||
|
@ -487,7 +518,30 @@ void HSendPacket (int node, int len)
|
||||||
doomcom.remotenode = node;
|
doomcom.remotenode = node;
|
||||||
doomcom.datalength = len;
|
doomcom.datalength = len;
|
||||||
|
|
||||||
I_NetCmd ();
|
#ifdef _DEBUG
|
||||||
|
if (net_fakelatency / 2 > 0)
|
||||||
|
{
|
||||||
|
PacketStore store;
|
||||||
|
store.message = doomcom;
|
||||||
|
store.timer = I_GetTime(false) + ((net_fakelatency / 2) / (1000 / TICRATE));
|
||||||
|
OutBuffer.Push(store);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
I_NetCmd();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < OutBuffer.Size(); i++)
|
||||||
|
{
|
||||||
|
if (OutBuffer[i].timer <= I_GetTime(false))
|
||||||
|
{
|
||||||
|
doomcom = OutBuffer[i].message;
|
||||||
|
I_NetCmd();
|
||||||
|
OutBuffer.Delete(i);
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
I_NetCmd();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -509,12 +563,42 @@ bool HGetPacket (void)
|
||||||
|
|
||||||
if (demoplayback)
|
if (demoplayback)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
doomcom.command = CMD_GET;
|
doomcom.command = CMD_GET;
|
||||||
I_NetCmd ();
|
I_NetCmd ();
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
if (net_fakelatency / 2 > 0 && doomcom.remotenode != -1)
|
||||||
|
{
|
||||||
|
PacketStore store;
|
||||||
|
store.message = doomcom;
|
||||||
|
store.timer = I_GetTime(false) + ((net_fakelatency / 2) / (1000 / TICRATE));
|
||||||
|
InBuffer.Push(store);
|
||||||
|
doomcom.remotenode = -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (doomcom.remotenode == -1)
|
if (doomcom.remotenode == -1)
|
||||||
|
{
|
||||||
|
bool gotmessage = false;
|
||||||
|
for (unsigned int i = 0; i < InBuffer.Size(); i++)
|
||||||
|
{
|
||||||
|
if (InBuffer[i].timer <= I_GetTime(false))
|
||||||
|
{
|
||||||
|
doomcom = InBuffer[i].message;
|
||||||
|
InBuffer.Delete(i);
|
||||||
|
gotmessage = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!gotmessage)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (doomcom.remotenode == -1)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (debugfile)
|
if (debugfile)
|
||||||
{
|
{
|
||||||
|
@ -570,6 +654,9 @@ bool HGetPacket (void)
|
||||||
|
|
||||||
if (doomcom.datalength != NetbufferSize ())
|
if (doomcom.datalength != NetbufferSize ())
|
||||||
{
|
{
|
||||||
|
Printf("Bad packet length %i (calculated %i)\n",
|
||||||
|
doomcom.datalength, NetbufferSize());
|
||||||
|
|
||||||
if (debugfile)
|
if (debugfile)
|
||||||
fprintf (debugfile,"---bad packet length %i (calculated %i)\n",
|
fprintf (debugfile,"---bad packet length %i (calculated %i)\n",
|
||||||
doomcom.datalength, NetbufferSize());
|
doomcom.datalength, NetbufferSize());
|
||||||
|
@ -782,6 +869,9 @@ void GetPackets (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pull current network delay from node
|
||||||
|
netdelay[netnode][(nettics[netnode]+1) % BACKUPTICS] = netbuffer[k++];
|
||||||
|
|
||||||
playerbytes[0] = netconsole;
|
playerbytes[0] = netconsole;
|
||||||
if (netbuffer[0] & NCMD_MULTI)
|
if (netbuffer[0] & NCMD_MULTI)
|
||||||
{
|
{
|
||||||
|
@ -1150,11 +1240,18 @@ void NetUpdate (void)
|
||||||
netbuffer[k++] = lowtic;
|
netbuffer[k++] = lowtic;
|
||||||
}
|
}
|
||||||
|
|
||||||
numtics = lowtic - realstart;
|
numtics = MAX(0, lowtic - realstart);
|
||||||
if (numtics > BACKUPTICS)
|
if (numtics > BACKUPTICS)
|
||||||
I_Error ("NetUpdate: Node %d missed too many tics", i);
|
I_Error ("NetUpdate: Node %d missed too many tics", i);
|
||||||
|
|
||||||
resendto[i] = MAX (0, lowtic - doomcom.extratics);
|
switch (net_extratic)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
resendto[i] = lowtic; break;
|
||||||
|
case 1: resendto[i] = MAX(0, lowtic - 1); break;
|
||||||
|
case 2: resendto[i] = nettics[i]; break;
|
||||||
|
}
|
||||||
|
|
||||||
if (numtics == 0 && resendOnly && !remoteresend[i] && nettics[i])
|
if (numtics == 0 && resendOnly && !remoteresend[i] && nettics[i])
|
||||||
{
|
{
|
||||||
|
@ -1190,6 +1287,10 @@ void NetUpdate (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send current network delay
|
||||||
|
// The number of tics we just made should be removed from the count.
|
||||||
|
netbuffer[k++] = ((maketic - newtics - gametic) / ticdup);
|
||||||
|
|
||||||
if (numtics > 0)
|
if (numtics > 0)
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
|
@ -1299,9 +1400,37 @@ void NetUpdate (void)
|
||||||
// that it won't adapt. Fortunately, player prediction helps
|
// that it won't adapt. Fortunately, player prediction helps
|
||||||
// alleviate the lag somewhat.
|
// alleviate the lag somewhat.
|
||||||
|
|
||||||
if (NetMode != NET_PacketServer)
|
if (NetMode == NET_PeerToPeer)
|
||||||
{
|
{
|
||||||
mastertics = nettics[nodeforplayer[Net_Arbitrator]];
|
int totalavg = 0;
|
||||||
|
if (net_ticbalance)
|
||||||
|
{
|
||||||
|
// Try to guess ahead the time it takes to send responses to the slowest node
|
||||||
|
int nodeavg = 0, arbavg = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < BACKUPTICS; j++)
|
||||||
|
{
|
||||||
|
arbavg += netdelay[nodeforplayer[Net_Arbitrator]][j];
|
||||||
|
nodeavg += netdelay[0][j];
|
||||||
|
}
|
||||||
|
arbavg /= BACKUPTICS;
|
||||||
|
nodeavg /= BACKUPTICS;
|
||||||
|
|
||||||
|
// We shouldn't adapt if we are already the arbitrator isn't what we are waiting for, otherwise it just adds more latency
|
||||||
|
if (arbavg > nodeavg)
|
||||||
|
{
|
||||||
|
lastaverage = totalavg = ((arbavg + nodeavg) / 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Allow room to guess two tics ahead
|
||||||
|
if (nodeavg > (arbavg + 2) && lastaverage > 0)
|
||||||
|
lastaverage--;
|
||||||
|
totalavg = lastaverage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mastertics = nettics[nodeforplayer[Net_Arbitrator]] + totalavg;
|
||||||
}
|
}
|
||||||
if (nettics[0] <= mastertics)
|
if (nettics[0] <= mastertics)
|
||||||
{
|
{
|
||||||
|
@ -1346,9 +1475,8 @@ void NetUpdate (void)
|
||||||
//
|
//
|
||||||
// 0 One byte set to NCMD_SETUP+2
|
// 0 One byte set to NCMD_SETUP+2
|
||||||
// 1 One byte for ticdup setting
|
// 1 One byte for ticdup setting
|
||||||
// 2 One byte for extratics setting
|
// 2 One byte for NetMode setting
|
||||||
// 3 One byte for NetMode setting
|
// 3 String with starting map's name
|
||||||
// 4 String with starting map's name
|
|
||||||
// . Four bytes for the RNG seed
|
// . Four bytes for the RNG seed
|
||||||
// . Stream containing remaining game info
|
// . Stream containing remaining game info
|
||||||
//
|
//
|
||||||
|
@ -1429,10 +1557,9 @@ bool DoArbitrate (void *userdata)
|
||||||
data->gotsetup[0] = 0x80;
|
data->gotsetup[0] = 0x80;
|
||||||
|
|
||||||
ticdup = doomcom.ticdup = netbuffer[1];
|
ticdup = doomcom.ticdup = netbuffer[1];
|
||||||
doomcom.extratics = netbuffer[2];
|
NetMode = netbuffer[2];
|
||||||
NetMode = netbuffer[3];
|
|
||||||
|
|
||||||
stream = &netbuffer[4];
|
stream = &netbuffer[3];
|
||||||
s = ReadString (&stream);
|
s = ReadString (&stream);
|
||||||
startmap = s;
|
startmap = s;
|
||||||
delete[] s;
|
delete[] s;
|
||||||
|
@ -1497,9 +1624,8 @@ bool DoArbitrate (void *userdata)
|
||||||
{
|
{
|
||||||
netbuffer[0] = NCMD_SETUP+2;
|
netbuffer[0] = NCMD_SETUP+2;
|
||||||
netbuffer[1] = (BYTE)doomcom.ticdup;
|
netbuffer[1] = (BYTE)doomcom.ticdup;
|
||||||
netbuffer[2] = (BYTE)doomcom.extratics;
|
netbuffer[2] = NetMode;
|
||||||
netbuffer[3] = NetMode;
|
stream = &netbuffer[3];
|
||||||
stream = &netbuffer[4];
|
|
||||||
WriteString (startmap, &stream);
|
WriteString (startmap, &stream);
|
||||||
WriteLong (rngseed, &stream);
|
WriteLong (rngseed, &stream);
|
||||||
C_WriteCVars (&stream, CVAR_SERVERINFO, true);
|
C_WriteCVars (&stream, CVAR_SERVERINFO, true);
|
||||||
|
@ -1647,15 +1773,23 @@ void D_CheckNetGame (void)
|
||||||
|
|
||||||
consoleplayer = doomcom.consoleplayer;
|
consoleplayer = doomcom.consoleplayer;
|
||||||
|
|
||||||
v = Args->CheckValue ("-netmode");
|
if (consoleplayer == Net_Arbitrator)
|
||||||
if (v != NULL)
|
|
||||||
{
|
{
|
||||||
NetMode = atoi (v) != 0 ? NET_PacketServer : NET_PeerToPeer;
|
v = Args->CheckValue("-netmode");
|
||||||
}
|
if (v != NULL)
|
||||||
if (doomcom.numnodes > 1)
|
{
|
||||||
{
|
NetMode = atoi(v) != 0 ? NET_PacketServer : NET_PeerToPeer;
|
||||||
Printf ("Selected " TEXTCOLOR_BLUE "%s" TEXTCOLOR_NORMAL " networking mode. (%s)\n", NetMode == NET_PeerToPeer ? "peer to peer" : "packet server",
|
}
|
||||||
v != NULL ? "forced" : "auto");
|
if (doomcom.numnodes > 1)
|
||||||
|
{
|
||||||
|
Printf("Selected " TEXTCOLOR_BLUE "%s" TEXTCOLOR_NORMAL " networking mode. (%s)\n", NetMode == NET_PeerToPeer ? "peer to peer" : "packet server",
|
||||||
|
v != NULL ? "forced" : "auto");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Args->CheckParm("-extratic"))
|
||||||
|
{
|
||||||
|
net_extratic = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] Setup user info
|
// [RH] Setup user info
|
||||||
|
@ -1683,6 +1817,11 @@ void D_CheckNetGame (void)
|
||||||
for (i = 0; i < doomcom.numnodes; i++)
|
for (i = 0; i < doomcom.numnodes; i++)
|
||||||
nodeingame[i] = true;
|
nodeingame[i] = true;
|
||||||
|
|
||||||
|
if (consoleplayer != Net_Arbitrator && doomcom.numnodes > 1)
|
||||||
|
{
|
||||||
|
Printf("Arbitrator selected " TEXTCOLOR_BLUE "%s" TEXTCOLOR_NORMAL " networking mode.\n", NetMode == NET_PeerToPeer ? "peer to peer" : "packet server");
|
||||||
|
}
|
||||||
|
|
||||||
Printf ("player %i of %i (%i nodes)\n",
|
Printf ("player %i of %i (%i nodes)\n",
|
||||||
consoleplayer+1, doomcom.numplayers, doomcom.numnodes);
|
consoleplayer+1, doomcom.numplayers, doomcom.numnodes);
|
||||||
}
|
}
|
||||||
|
@ -1809,6 +1948,9 @@ void TryRunTics (void)
|
||||||
{
|
{
|
||||||
C_Ticker();
|
C_Ticker();
|
||||||
M_Ticker();
|
M_Ticker();
|
||||||
|
// Repredict the player for new buffered movement
|
||||||
|
P_UnPredictPlayer();
|
||||||
|
P_PredictPlayer(&players[consoleplayer]);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1844,6 +1986,9 @@ void TryRunTics (void)
|
||||||
{
|
{
|
||||||
C_Ticker ();
|
C_Ticker ();
|
||||||
M_Ticker ();
|
M_Ticker ();
|
||||||
|
// Repredict the player for new buffered movement
|
||||||
|
P_UnPredictPlayer();
|
||||||
|
P_PredictPlayer(&players[consoleplayer]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1857,6 +2002,7 @@ void TryRunTics (void)
|
||||||
// run the count tics
|
// run the count tics
|
||||||
if (counts > 0)
|
if (counts > 0)
|
||||||
{
|
{
|
||||||
|
P_UnPredictPlayer();
|
||||||
while (counts--)
|
while (counts--)
|
||||||
{
|
{
|
||||||
if (gametic > lowtic)
|
if (gametic > lowtic)
|
||||||
|
@ -1876,6 +2022,7 @@ void TryRunTics (void)
|
||||||
|
|
||||||
NetUpdate (); // check for new console commands
|
NetUpdate (); // check for new console commands
|
||||||
}
|
}
|
||||||
|
P_PredictPlayer(&players[consoleplayer]);
|
||||||
S_UpdateSounds (players[consoleplayer].camera); // move positional sounds
|
S_UpdateSounds (players[consoleplayer].camera); // move positional sounds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2713,7 +2860,6 @@ void Net_SkipCommand (int type, BYTE **stream)
|
||||||
CCMD (pings)
|
CCMD (pings)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
if (playeringame[i])
|
if (playeringame[i])
|
||||||
Printf ("% 4d %s\n", currrecvtime[i] - lastrecvtime[i],
|
Printf ("% 4d %s\n", currrecvtime[i] - lastrecvtime[i],
|
||||||
|
|
|
@ -70,7 +70,6 @@ struct doomcom_t
|
||||||
// info common to all nodes
|
// info common to all nodes
|
||||||
SWORD numnodes; // console is always node 0.
|
SWORD numnodes; // console is always node 0.
|
||||||
SWORD ticdup; // 1 = no duplication, 2-5 = dup for slow nets
|
SWORD ticdup; // 1 = no duplication, 2-5 = dup for slow nets
|
||||||
SWORD extratics; // 1 = send a backup tic in every packet
|
|
||||||
#ifdef DJGPP
|
#ifdef DJGPP
|
||||||
SWORD pad[5]; // keep things aligned for DOS drivers
|
SWORD pad[5]; // keep things aligned for DOS drivers
|
||||||
#endif
|
#endif
|
||||||
|
@ -143,6 +142,8 @@ extern struct ticcmd_t localcmds[LOCALCMDTICS];
|
||||||
|
|
||||||
extern int maketic;
|
extern int maketic;
|
||||||
extern int nettics[MAXNETNODES];
|
extern int nettics[MAXNETNODES];
|
||||||
|
extern int netdelay[MAXNETNODES][BACKUPTICS];
|
||||||
|
extern int nodeforplayer[MAXPLAYERS];
|
||||||
|
|
||||||
extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
||||||
extern int ticdup;
|
extern int ticdup;
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
// copy would be.
|
// copy would be.
|
||||||
|
|
||||||
#include "doomtype.h"
|
#include "doomtype.h"
|
||||||
|
#include "doomdef.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
#include "g_level.h"
|
#include "g_level.h"
|
||||||
|
#include "d_net.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
@ -73,6 +75,7 @@ CVAR (Bool, hud_showscore, false, CVAR_ARCHIVE); // for user maintained score
|
||||||
CVAR (Bool, hud_showweapons, true, CVAR_ARCHIVE); // Show weapons collected
|
CVAR (Bool, hud_showweapons, true, CVAR_ARCHIVE); // Show weapons collected
|
||||||
CVAR (Int , hud_showtime, 0, CVAR_ARCHIVE); // Show time on HUD
|
CVAR (Int , hud_showtime, 0, CVAR_ARCHIVE); // Show time on HUD
|
||||||
CVAR (Int , hud_timecolor, CR_GOLD,CVAR_ARCHIVE); // Color of in-game time on HUD
|
CVAR (Int , hud_timecolor, CR_GOLD,CVAR_ARCHIVE); // Color of in-game time on HUD
|
||||||
|
CVAR (Int , hud_showlag, 0, CVAR_ARCHIVE); // Show input latency (maketic - gametic difference)
|
||||||
|
|
||||||
CVAR (Int, hud_ammo_red, 25, CVAR_ARCHIVE) // ammo percent less than which status is red
|
CVAR (Int, hud_ammo_red, 25, CVAR_ARCHIVE) // ammo percent less than which status is red
|
||||||
CVAR (Int, hud_ammo_yellow, 50, CVAR_ARCHIVE) // ammo percent less is yellow more green
|
CVAR (Int, hud_ammo_yellow, 50, CVAR_ARCHIVE) // ammo percent less is yellow more green
|
||||||
|
@ -917,6 +920,51 @@ static void DrawTime()
|
||||||
DrawHudText(SmallFont, hud_timecolor, timeString, hudwidth - width, height, FRACUNIT);
|
DrawHudText(SmallFont, hud_timecolor, timeString, hudwidth - width, height, FRACUNIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Draw in-game latency
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static void DrawLatency()
|
||||||
|
{
|
||||||
|
if (hud_showlag <= 0 ||
|
||||||
|
(hud_showlag == 1 && !netgame) ||
|
||||||
|
hud_showlag > 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int i, localdelay = 0, arbitratordelay = 0;
|
||||||
|
for (i = 0; i < BACKUPTICS; i++) localdelay += netdelay[0][i];
|
||||||
|
for (i = 0; i < BACKUPTICS; i++) arbitratordelay += netdelay[nodeforplayer[Net_Arbitrator]][i];
|
||||||
|
localdelay = ((localdelay / BACKUPTICS) * ticdup) * (1000 / TICRATE);
|
||||||
|
arbitratordelay = ((arbitratordelay / BACKUPTICS) * ticdup) * (1000 / TICRATE);
|
||||||
|
int color = CR_GREEN;
|
||||||
|
if (MAX(localdelay, arbitratordelay) > 200)
|
||||||
|
{
|
||||||
|
color = CR_YELLOW;
|
||||||
|
}
|
||||||
|
if (MAX(localdelay, arbitratordelay) > 400)
|
||||||
|
{
|
||||||
|
color = CR_ORANGE;
|
||||||
|
}
|
||||||
|
if (MAX(localdelay, arbitratordelay) >= ((BACKUPTICS / 2 - 1) * ticdup) * (1000 / TICRATE))
|
||||||
|
{
|
||||||
|
color = CR_RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
char tempstr[32];
|
||||||
|
|
||||||
|
const int millis = (level.time % TICRATE) * (1000 / TICRATE);
|
||||||
|
mysnprintf(tempstr, sizeof(tempstr), "a:%dms - l:%dms", arbitratordelay, localdelay);
|
||||||
|
|
||||||
|
const int characterCount = strlen(tempstr);
|
||||||
|
const int width = SmallFont->GetCharWidth('0') * characterCount + 2; // small offset from screen's border
|
||||||
|
const int height = SmallFont->GetHeight() * 2;
|
||||||
|
|
||||||
|
DrawHudText(SmallFont, color, tempstr, hudwidth - width, height, FRACUNIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -982,6 +1030,7 @@ void DrawHUD()
|
||||||
if (idmypos) DrawCoordinates(CPlayer);
|
if (idmypos) DrawCoordinates(CPlayer);
|
||||||
|
|
||||||
DrawTime();
|
DrawTime();
|
||||||
|
DrawLatency();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
#include "hu_stuff.h"
|
#include "hu_stuff.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
|
#include "d_net.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@
|
||||||
|
|
||||||
static void HU_DoDrawScores (player_t *, player_t *[MAXPLAYERS]);
|
static void HU_DoDrawScores (player_t *, player_t *[MAXPLAYERS]);
|
||||||
static void HU_DrawTimeRemaining (int y);
|
static void HU_DrawTimeRemaining (int y);
|
||||||
static void HU_DrawPlayer (player_t *, bool, int, int, int, int, int, int, int, int);
|
static void HU_DrawPlayer(player_t *, bool, int, int, int, int, int, int, int, int, int);
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
|
@ -228,7 +229,7 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
|
||||||
int maxnamewidth, maxscorewidth, maxiconheight;
|
int maxnamewidth, maxscorewidth, maxiconheight;
|
||||||
int numTeams = 0;
|
int numTeams = 0;
|
||||||
int x, y, ypadding, bottom;
|
int x, y, ypadding, bottom;
|
||||||
int col2, col3, col4;
|
int col2, col3, col4, col5;
|
||||||
|
|
||||||
if (deathmatch)
|
if (deathmatch)
|
||||||
{
|
{
|
||||||
|
@ -309,12 +310,14 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
|
||||||
|
|
||||||
const char *text_color = GStrings("SCORE_COLOR"),
|
const char *text_color = GStrings("SCORE_COLOR"),
|
||||||
*text_frags = GStrings(deathmatch ? "SCORE_FRAGS" : "SCORE_KILLS"),
|
*text_frags = GStrings(deathmatch ? "SCORE_FRAGS" : "SCORE_KILLS"),
|
||||||
*text_name = GStrings("SCORE_NAME");
|
*text_name = GStrings("SCORE_NAME"),
|
||||||
|
*text_delay = GStrings("SCORE_DELAY");
|
||||||
|
|
||||||
col2 = (SmallFont->StringWidth(text_color) + 8) * CleanXfac;
|
col2 = (SmallFont->StringWidth(text_color) + 8) * CleanXfac;
|
||||||
col3 = col2 + (SmallFont->StringWidth(text_frags) + 8) * CleanXfac;
|
col3 = col2 + (SmallFont->StringWidth(text_frags) + 8) * CleanXfac;
|
||||||
col4 = col3 + maxscorewidth * CleanXfac;
|
col4 = col3 + maxscorewidth * CleanXfac;
|
||||||
x = (SCREENWIDTH >> 1) - ((maxnamewidth * CleanXfac + col4) >> 1);
|
col5 = col4 + (maxnamewidth + 8) * CleanXfac;
|
||||||
|
x = (SCREENWIDTH >> 1) - (((SmallFont->StringWidth(text_delay) * CleanXfac) + col5) >> 1);
|
||||||
|
|
||||||
screen->DrawText (SmallFont, color, x, y, text_color,
|
screen->DrawText (SmallFont, color, x, y, text_color,
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
DTA_CleanNoMove, true, TAG_DONE);
|
||||||
|
@ -325,6 +328,9 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
|
||||||
screen->DrawText (SmallFont, color, x + col4, y, text_name,
|
screen->DrawText (SmallFont, color, x + col4, y, text_name,
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
DTA_CleanNoMove, true, TAG_DONE);
|
||||||
|
|
||||||
|
screen->DrawText(SmallFont, color, x + col5, y, text_delay,
|
||||||
|
DTA_CleanNoMove, true, TAG_DONE);
|
||||||
|
|
||||||
y += height + 6 * CleanYfac;
|
y += height + 6 * CleanYfac;
|
||||||
bottom -= height;
|
bottom -= height;
|
||||||
|
|
||||||
|
@ -332,7 +338,7 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
|
||||||
{
|
{
|
||||||
if (playeringame[sortedplayers[i] - players])
|
if (playeringame[sortedplayers[i] - players])
|
||||||
{
|
{
|
||||||
HU_DrawPlayer (sortedplayers[i], player==sortedplayers[i], x, col2, col3, col4, maxnamewidth, y, ypadding, lineheight);
|
HU_DrawPlayer(sortedplayers[i], player == sortedplayers[i], x, col2, col3, col4, col5, maxnamewidth, y, ypadding, lineheight);
|
||||||
y += lineheight + CleanYfac;
|
y += lineheight + CleanYfac;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,7 +383,7 @@ static void HU_DrawTimeRemaining (int y)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2, int col3, int col4, int maxnamewidth, int y, int ypadding, int height)
|
static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2, int col3, int col4, int col5, int maxnamewidth, int y, int ypadding, int height)
|
||||||
{
|
{
|
||||||
int color;
|
int color;
|
||||||
char str[80];
|
char str[80];
|
||||||
|
@ -387,12 +393,13 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2,
|
||||||
// The teamplay mode uses colors to show teams, so we need some
|
// The teamplay mode uses colors to show teams, so we need some
|
||||||
// other way to do highlighting. And it may as well be used for
|
// other way to do highlighting. And it may as well be used for
|
||||||
// all modes for the sake of consistancy.
|
// all modes for the sake of consistancy.
|
||||||
screen->Dim(MAKERGB(200,245,255), 0.125f, col1 - 12*CleanXfac, y - 1, col4 + (maxnamewidth + 24)*CleanXfac, height + 2);
|
screen->Dim(MAKERGB(200,245,255), 0.125f, col1 - 12*CleanXfac, y - 1, col5 + (maxnamewidth + 24)*CleanXfac, height + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
col2 += col1;
|
col2 += col1;
|
||||||
col3 += col1;
|
col3 += col1;
|
||||||
col4 += col1;
|
col4 += col1;
|
||||||
|
col5 += col1;
|
||||||
|
|
||||||
color = HU_GetRowColor(player, highlight);
|
color = HU_GetRowColor(player, highlight);
|
||||||
HU_DrawColorBar(col1, y, height, (int)(player - players));
|
HU_DrawColorBar(col1, y, height, (int)(player - players));
|
||||||
|
@ -412,6 +419,18 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2,
|
||||||
screen->DrawText (SmallFont, color, col4, y + ypadding, player->userinfo.GetName(),
|
screen->DrawText (SmallFont, color, col4, y + ypadding, player->userinfo.GetName(),
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
DTA_CleanNoMove, true, TAG_DONE);
|
||||||
|
|
||||||
|
int avgdelay = 0;
|
||||||
|
for (int i = 0; i < BACKUPTICS; i++)
|
||||||
|
{
|
||||||
|
avgdelay += netdelay[nodeforplayer[(int)(player - players)]][i];
|
||||||
|
}
|
||||||
|
avgdelay /= BACKUPTICS;
|
||||||
|
|
||||||
|
mysnprintf(str, countof(str), "%d", (avgdelay * ticdup) * (1000 / TICRATE));
|
||||||
|
|
||||||
|
screen->DrawText(SmallFont, color, col5, y + ypadding, str,
|
||||||
|
DTA_CleanNoMove, true, TAG_DONE);
|
||||||
|
|
||||||
if (teamplay && Teams[player->userinfo.GetTeam()].GetLogo().IsNotEmpty ())
|
if (teamplay && Teams[player->userinfo.GetTeam()].GetLogo().IsNotEmpty ())
|
||||||
{
|
{
|
||||||
FTexture *pic = TexMan[Teams[player->userinfo.GetTeam()].GetLogo().GetChars ()];
|
FTexture *pic = TexMan[Teams[player->userinfo.GetTeam()].GetLogo().GetChars ()];
|
||||||
|
|
|
@ -208,11 +208,11 @@ void PacketSend (void)
|
||||||
{
|
{
|
||||||
I_FatalError("Netbuffer overflow!");
|
I_FatalError("Netbuffer overflow!");
|
||||||
}
|
}
|
||||||
|
assert(!(doomcom.data[0] & NCMD_COMPRESSED));
|
||||||
|
|
||||||
uLong size = TRANSMIT_SIZE - 1;
|
uLong size = TRANSMIT_SIZE - 1;
|
||||||
if (doomcom.datalength >= 10)
|
if (doomcom.datalength >= 10)
|
||||||
{
|
{
|
||||||
assert(!(doomcom.data[0] & NCMD_COMPRESSED));
|
|
||||||
TransmitBuffer[0] = doomcom.data[0] | NCMD_COMPRESSED;
|
TransmitBuffer[0] = doomcom.data[0] | NCMD_COMPRESSED;
|
||||||
c = compress2(TransmitBuffer + 1, &size, doomcom.data + 1, doomcom.datalength - 1, 9);
|
c = compress2(TransmitBuffer + 1, &size, doomcom.data + 1, doomcom.datalength - 1, 9);
|
||||||
size += 1;
|
size += 1;
|
||||||
|
@ -938,11 +938,6 @@ bool I_InitNetwork (void)
|
||||||
doomcom.ticdup = 1;
|
doomcom.ticdup = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Args->CheckParm ("-extratic"))
|
|
||||||
doomcom.extratics = 1;
|
|
||||||
else
|
|
||||||
doomcom.extratics = 0;
|
|
||||||
|
|
||||||
v = Args->CheckValue ("-port");
|
v = Args->CheckValue ("-port");
|
||||||
if (v)
|
if (v)
|
||||||
{
|
{
|
||||||
|
|
|
@ -298,6 +298,7 @@ xx(Abs)
|
||||||
xx(ACS_NamedExecuteWithResult)
|
xx(ACS_NamedExecuteWithResult)
|
||||||
xx(CallACS)
|
xx(CallACS)
|
||||||
xx(Sqrt)
|
xx(Sqrt)
|
||||||
|
xx(CheckClass)
|
||||||
|
|
||||||
// Various actor names which are used internally
|
// Various actor names which are used internally
|
||||||
xx(MapSpot)
|
xx(MapSpot)
|
||||||
|
|
|
@ -380,7 +380,9 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra
|
||||||
// ... and some items can never be telefragged while others will be telefragged by everything that teleports upon them.
|
// ... and some items can never be telefragged while others will be telefragged by everything that teleports upon them.
|
||||||
if ((StompAlwaysFrags && !(th->flags6 & MF6_NOTELEFRAG)) || (th->flags7 & MF7_ALWAYSTELEFRAG))
|
if ((StompAlwaysFrags && !(th->flags6 & MF6_NOTELEFRAG)) || (th->flags7 & MF7_ALWAYSTELEFRAG))
|
||||||
{
|
{
|
||||||
P_DamageMobj(th, thing, thing, TELEFRAG_DAMAGE, NAME_Telefrag, DMG_THRUSTLESS);
|
// Don't actually damage if predicting a teleport
|
||||||
|
if (thing->player == NULL || !(thing->player->cheats & CF_PREDICTING))
|
||||||
|
P_DamageMobj(th, thing, thing, TELEFRAG_DAMAGE, NAME_Telefrag, DMG_THRUSTLESS);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1981,13 +1983,6 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
||||||
thing->AdjustFloorClip();
|
thing->AdjustFloorClip();
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] Don't activate anything if just predicting
|
|
||||||
if (thing->player && (thing->player->cheats & CF_PREDICTING))
|
|
||||||
{
|
|
||||||
thing->flags6 &= ~MF6_INTRYMOVE;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if any special lines were hit, do the effect
|
// if any special lines were hit, do the effect
|
||||||
if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP)))
|
if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP)))
|
||||||
{
|
{
|
||||||
|
@ -1998,7 +1993,11 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
||||||
oldside = P_PointOnLineSide(oldx, oldy, ld);
|
oldside = P_PointOnLineSide(oldx, oldy, ld);
|
||||||
if (side != oldside && ld->special && !(thing->flags6 & MF6_NOTRIGGER))
|
if (side != oldside && ld->special && !(thing->flags6 & MF6_NOTRIGGER))
|
||||||
{
|
{
|
||||||
if (thing->player)
|
if (thing->player && (thing->player->cheats & CF_PREDICTING))
|
||||||
|
{
|
||||||
|
P_PredictLine(ld, thing, oldside, SPAC_Cross);
|
||||||
|
}
|
||||||
|
else if (thing->player)
|
||||||
{
|
{
|
||||||
P_ActivateLine(ld, thing, oldside, SPAC_Cross);
|
P_ActivateLine(ld, thing, oldside, SPAC_Cross);
|
||||||
}
|
}
|
||||||
|
@ -2024,6 +2023,13 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [RH] Don't activate anything if just predicting
|
||||||
|
if (thing->player && (thing->player->cheats & CF_PREDICTING))
|
||||||
|
{
|
||||||
|
thing->flags6 &= ~MF6_INTRYMOVE;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// [RH] Check for crossing fake floor/ceiling
|
// [RH] Check for crossing fake floor/ceiling
|
||||||
newsec = thing->Sector;
|
newsec = thing->Sector;
|
||||||
if (newsec->heightsec && oldsec->heightsec && newsec->SecActTarget)
|
if (newsec->heightsec && oldsec->heightsec && newsec->SecActTarget)
|
||||||
|
|
|
@ -73,6 +73,7 @@
|
||||||
static FRandom pr_playerinspecialsector ("PlayerInSpecialSector");
|
static FRandom pr_playerinspecialsector ("PlayerInSpecialSector");
|
||||||
void P_SetupPortals();
|
void P_SetupPortals();
|
||||||
|
|
||||||
|
EXTERN_CVAR(Bool, cl_predict_specials)
|
||||||
|
|
||||||
IMPLEMENT_POINTY_CLASS (DScroller)
|
IMPLEMENT_POINTY_CLASS (DScroller)
|
||||||
DECLARE_POINTER (m_Interpolations[0])
|
DECLARE_POINTER (m_Interpolations[0])
|
||||||
|
@ -408,6 +409,48 @@ bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// P_PredictLine
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
bool P_PredictLine(line_t *line, AActor *mo, int side, int activationType)
|
||||||
|
{
|
||||||
|
int lineActivation;
|
||||||
|
INTBOOL buttonSuccess;
|
||||||
|
BYTE special;
|
||||||
|
|
||||||
|
// Only predict a very specifc section of specials
|
||||||
|
if (line->special != Teleport_Line &&
|
||||||
|
line->special != Teleport)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!P_TestActivateLine(line, mo, side, activationType) || !cl_predict_specials)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line->locknumber > 0) return false;
|
||||||
|
lineActivation = line->activation;
|
||||||
|
buttonSuccess = false;
|
||||||
|
buttonSuccess = P_ExecuteSpecial(line->special,
|
||||||
|
line, mo, side == 1, line->args[0],
|
||||||
|
line->args[1], line->args[2],
|
||||||
|
line->args[3], line->args[4]);
|
||||||
|
|
||||||
|
special = line->special;
|
||||||
|
|
||||||
|
// end of changed code
|
||||||
|
if (developer && buttonSuccess)
|
||||||
|
{
|
||||||
|
Printf("Line special %d predicted on line %i\n", special, int(line - lines));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// P_PlayerInSpecialSector
|
// P_PlayerInSpecialSector
|
||||||
// Called every tic frame
|
// Called every tic frame
|
||||||
|
|
|
@ -166,6 +166,7 @@ void P_UpdateSpecials (void);
|
||||||
// when needed
|
// when needed
|
||||||
bool P_ActivateLine (line_t *ld, AActor *mo, int side, int activationType);
|
bool P_ActivateLine (line_t *ld, AActor *mo, int side, int activationType);
|
||||||
bool P_TestActivateLine (line_t *ld, AActor *mo, int side, int activationType);
|
bool P_TestActivateLine (line_t *ld, AActor *mo, int side, int activationType);
|
||||||
|
bool P_PredictLine (line_t *ld, AActor *mo, int side, int activationType);
|
||||||
|
|
||||||
void P_PlayerInSpecialSector (player_t *player, sector_t * sector=NULL);
|
void P_PlayerInSpecialSector (player_t *player, sector_t * sector=NULL);
|
||||||
void P_PlayerOnSpecialFlat (player_t *player, int floorType);
|
void P_PlayerOnSpecialFlat (player_t *player, int floorType);
|
||||||
|
|
|
@ -96,6 +96,8 @@ void P_SpawnTeleportFog(fixed_t x, fixed_t y, fixed_t z, int spawnid)
|
||||||
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
||||||
bool useFog, bool sourceFog, bool keepOrientation, bool bHaltVelocity, bool keepHeight)
|
bool useFog, bool sourceFog, bool keepOrientation, bool bHaltVelocity, bool keepHeight)
|
||||||
{
|
{
|
||||||
|
bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING));
|
||||||
|
|
||||||
fixed_t oldx;
|
fixed_t oldx;
|
||||||
fixed_t oldy;
|
fixed_t oldy;
|
||||||
fixed_t oldz;
|
fixed_t oldz;
|
||||||
|
@ -181,7 +183,7 @@ bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
||||||
angle = thing->angle;
|
angle = thing->angle;
|
||||||
}
|
}
|
||||||
// Spawn teleport fog at source and destination
|
// Spawn teleport fog at source and destination
|
||||||
if (sourceFog)
|
if (sourceFog && !predicting)
|
||||||
{
|
{
|
||||||
fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
|
fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
|
||||||
AActor *fog = Spawn<ATeleportFog> (oldx, oldy, oldz + fogDelta, ALLOW_REPLACE);
|
AActor *fog = Spawn<ATeleportFog> (oldx, oldy, oldz + fogDelta, ALLOW_REPLACE);
|
||||||
|
@ -189,11 +191,14 @@ bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
||||||
}
|
}
|
||||||
if (useFog)
|
if (useFog)
|
||||||
{
|
{
|
||||||
fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
|
if (!predicting)
|
||||||
an = angle >> ANGLETOFINESHIFT;
|
{
|
||||||
AActor *fog = Spawn<ATeleportFog> (x + 20*finecosine[an],
|
fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
|
||||||
y + 20*finesine[an], thing->z + fogDelta, ALLOW_REPLACE);
|
an = angle >> ANGLETOFINESHIFT;
|
||||||
fog->target = thing;
|
AActor *fog = Spawn<ATeleportFog>(x + 20 * finecosine[an],
|
||||||
|
y + 20 * finesine[an], thing->z + fogDelta, ALLOW_REPLACE);
|
||||||
|
fog->target = thing;
|
||||||
|
}
|
||||||
if (thing->player)
|
if (thing->player)
|
||||||
{
|
{
|
||||||
// [RH] Zoom player's field of vision
|
// [RH] Zoom player's field of vision
|
||||||
|
@ -226,7 +231,7 @@ bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static AActor *SelectTeleDest (int tid, int tag)
|
static AActor *SelectTeleDest (int tid, int tag, bool norandom)
|
||||||
{
|
{
|
||||||
AActor *searcher;
|
AActor *searcher;
|
||||||
|
|
||||||
|
@ -276,7 +281,7 @@ static AActor *SelectTeleDest (int tid, int tag)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (count != 1)
|
if (count != 1 && !norandom)
|
||||||
{
|
{
|
||||||
count = 1 + (pr_teleport() % count);
|
count = 1 + (pr_teleport() % count);
|
||||||
}
|
}
|
||||||
|
@ -323,6 +328,8 @@ static AActor *SelectTeleDest (int tid, int tag)
|
||||||
bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool fog,
|
bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool fog,
|
||||||
bool sourceFog, bool keepOrientation, bool haltVelocity, bool keepHeight)
|
bool sourceFog, bool keepOrientation, bool haltVelocity, bool keepHeight)
|
||||||
{
|
{
|
||||||
|
bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING));
|
||||||
|
|
||||||
AActor *searcher;
|
AActor *searcher;
|
||||||
fixed_t z;
|
fixed_t z;
|
||||||
angle_t angle = 0;
|
angle_t angle = 0;
|
||||||
|
@ -342,7 +349,7 @@ bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool
|
||||||
{ // Don't teleport if hit back of line, so you can get out of teleporter.
|
{ // Don't teleport if hit back of line, so you can get out of teleporter.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
searcher = SelectTeleDest (tid, tag);
|
searcher = SelectTeleDest(tid, tag, predicting);
|
||||||
if (searcher == NULL)
|
if (searcher == NULL)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -390,7 +397,7 @@ bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool
|
||||||
thing->velx = FixedMul(velx, c) - FixedMul(vely, s);
|
thing->velx = FixedMul(velx, c) - FixedMul(vely, s);
|
||||||
thing->vely = FixedMul(vely, c) + FixedMul(velx, s);
|
thing->vely = FixedMul(vely, c) + FixedMul(velx, s);
|
||||||
}
|
}
|
||||||
if ((velx | vely) == 0 && thing->player != NULL && thing->player->mo == thing)
|
if ((velx | vely) == 0 && thing->player != NULL && thing->player->mo == thing && !predicting)
|
||||||
{
|
{
|
||||||
thing->player->mo->PlayIdle ();
|
thing->player->mo->PlayIdle ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ 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)
|
||||||
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;
|
||||||
|
@ -2722,8 +2723,12 @@ void P_PredictPlayer (player_t *player)
|
||||||
}
|
}
|
||||||
act->BlockNode = NULL;
|
act->BlockNode = NULL;
|
||||||
|
|
||||||
|
bool NoInterpolateOld = R_GetViewInterpolationStatus();
|
||||||
for (int i = gametic; i < maxtic; ++i)
|
for (int i = gametic; i < maxtic; ++i)
|
||||||
{
|
{
|
||||||
|
if (!NoInterpolateOld)
|
||||||
|
R_RebuildViewInterpolation(player);
|
||||||
|
|
||||||
player->cmd = localcmds[i % LOCALCMDTICS];
|
player->cmd = localcmds[i % LOCALCMDTICS];
|
||||||
P_PlayerThink (player);
|
P_PlayerThink (player);
|
||||||
player->mo->Tick ();
|
player->mo->Tick ();
|
||||||
|
|
|
@ -729,6 +729,42 @@ void R_ClearPastViewer (AActor *actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// R_RebuildViewInterpolation
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void R_RebuildViewInterpolation(player_t *player)
|
||||||
|
{
|
||||||
|
if (player == NULL || player->camera == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!NoInterpolateView)
|
||||||
|
return;
|
||||||
|
NoInterpolateView = false;
|
||||||
|
|
||||||
|
InterpolationViewer *iview = FindPastViewer(player->camera);
|
||||||
|
|
||||||
|
iview->oviewx = iview->nviewx;
|
||||||
|
iview->oviewy = iview->nviewy;
|
||||||
|
iview->oviewz = iview->nviewz;
|
||||||
|
iview->oviewpitch = iview->nviewpitch;
|
||||||
|
iview->oviewangle = iview->nviewangle;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// R_GetViewInterpolationStatus
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool R_GetViewInterpolationStatus()
|
||||||
|
{
|
||||||
|
return NoInterpolateView;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// R_SetupFrame
|
// R_SetupFrame
|
||||||
|
|
|
@ -61,6 +61,8 @@ inline angle_t R_PointToAngle (fixed_t x, fixed_t y) { return R_PointToAngle2 (v
|
||||||
subsector_t *R_PointInSubsector (fixed_t x, fixed_t y);
|
subsector_t *R_PointInSubsector (fixed_t x, fixed_t y);
|
||||||
fixed_t R_PointToDist2 (fixed_t dx, fixed_t dy);
|
fixed_t R_PointToDist2 (fixed_t dx, fixed_t dy);
|
||||||
void R_ResetViewInterpolation ();
|
void R_ResetViewInterpolation ();
|
||||||
|
void R_RebuildViewInterpolation(player_t *player);
|
||||||
|
bool R_GetViewInterpolationStatus();
|
||||||
void R_SetViewSize (int blocks);
|
void R_SetViewSize (int blocks);
|
||||||
void R_SetFOV (float fov);
|
void R_SetFOV (float fov);
|
||||||
float R_GetFOV ();
|
float R_GetFOV ();
|
||||||
|
|
|
@ -3532,7 +3532,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// A_DamageMaster (int amount)
|
// A_DamageMaster (int amount, str damagetype)
|
||||||
// Damages the master of this child by the specified amount. Negative values heal.
|
// Damages the master of this child by the specified amount. Negative values heal.
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -3558,7 +3558,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// A_DamageChildren (amount)
|
// A_DamageChildren (amount, str damagetype)
|
||||||
// Damages the children of this master by the specified amount. Negative values heal.
|
// Damages the children of this master by the specified amount. Negative values heal.
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -3592,7 +3592,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// A_DamageSiblings (amount)
|
// A_DamageSiblings (int amount, str damagetype)
|
||||||
// Damages the siblings of this master by the specified amount. Negative values heal.
|
// Damages the siblings of this master by the specified amount. Negative values heal.
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -4993,4 +4993,81 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed)
|
||||||
ACTION_PARAM_FIXED(speed, 0);
|
ACTION_PARAM_FIXED(speed, 0);
|
||||||
|
|
||||||
self->Speed = speed;
|
self->Speed = speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// A_DamageSelf (int amount, str damagetype)
|
||||||
|
// Damages the calling actor by the specified amount. Negative values heal.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf)
|
||||||
|
{
|
||||||
|
ACTION_PARAM_START(2);
|
||||||
|
ACTION_PARAM_INT(amount, 0);
|
||||||
|
ACTION_PARAM_NAME(DamageType, 1);
|
||||||
|
|
||||||
|
if (amount > 0)
|
||||||
|
{
|
||||||
|
P_DamageMobj(self, self, self, amount, DamageType, DMG_NO_ARMOR);
|
||||||
|
}
|
||||||
|
else if (amount < 0)
|
||||||
|
{
|
||||||
|
amount = -amount;
|
||||||
|
P_GiveBody(self, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// A_DamageTarget (int amount, str damagetype)
|
||||||
|
// Damages the target of the actor by the specified amount. Negative values heal.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget)
|
||||||
|
{
|
||||||
|
ACTION_PARAM_START(2);
|
||||||
|
ACTION_PARAM_INT(amount, 0);
|
||||||
|
ACTION_PARAM_NAME(DamageType, 1);
|
||||||
|
|
||||||
|
if (self->target != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (amount > 0)
|
||||||
|
{
|
||||||
|
P_DamageMobj(self->target, self, self, amount, DamageType, DMG_NO_ARMOR);
|
||||||
|
}
|
||||||
|
else if (amount < 0)
|
||||||
|
{
|
||||||
|
amount = -amount;
|
||||||
|
P_GiveBody(self->target, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// A_DamageTracer (int amount, str damagetype)
|
||||||
|
// Damages the tracer of the actor by the specified amount. Negative values heal.
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer)
|
||||||
|
{
|
||||||
|
ACTION_PARAM_START(2);
|
||||||
|
ACTION_PARAM_INT(amount, 0);
|
||||||
|
ACTION_PARAM_NAME(DamageType, 1);
|
||||||
|
|
||||||
|
if (self->target != NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (amount > 0)
|
||||||
|
{
|
||||||
|
P_DamageMobj(self->tracer, self, self, amount, DamageType, DMG_NO_ARMOR);
|
||||||
|
}
|
||||||
|
else if (amount < 0)
|
||||||
|
{
|
||||||
|
amount = -amount;
|
||||||
|
P_GiveBody(self->tracer, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,6 +43,8 @@
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef.h"
|
||||||
#include "thingdef_exp.h"
|
#include "thingdef_exp.h"
|
||||||
|
#include "actor.h"
|
||||||
|
#include "actorptrselect.h"
|
||||||
|
|
||||||
static TMap<FName, FxGlobalFunctionCall::Creator> CreatorMap;
|
static TMap<FName, FxGlobalFunctionCall::Creator> CreatorMap;
|
||||||
|
|
||||||
|
@ -185,3 +187,77 @@ public:
|
||||||
|
|
||||||
GLOBALFUNCTION_ADDER(Sqrt);
|
GLOBALFUNCTION_ADDER(Sqrt);
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Function: checkclass
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxGlobalFunctionCall_CheckClass : public FxGlobalFunctionCall
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GLOBALFUNCTION_DEFINE(CheckClass);
|
||||||
|
|
||||||
|
FxExpression *Resolve(FCompileContext& ctx)
|
||||||
|
{
|
||||||
|
CHECKRESOLVED();
|
||||||
|
|
||||||
|
if (!ResolveArgs(ctx, 1, 3, false))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (int i = ArgList->Size(); i > 1;)
|
||||||
|
{
|
||||||
|
if (!(*ArgList)[--i]->ValueType.isNumeric())
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter");
|
||||||
|
delete this;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((*ArgList)[0]->ValueType.Type)
|
||||||
|
{
|
||||||
|
case VAL_Class: case VAL_Name:break;
|
||||||
|
default:
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "actor class expected for parameter");
|
||||||
|
delete this;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType = VAL_Float;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpVal EvalExpression(AActor *self)
|
||||||
|
{
|
||||||
|
ExpVal ret;
|
||||||
|
ret.Type = VAL_Int;
|
||||||
|
|
||||||
|
const PClass * checkclass;
|
||||||
|
{
|
||||||
|
ExpVal v = (*ArgList)[0]->EvalExpression(self);
|
||||||
|
checkclass = v.GetClass();
|
||||||
|
if (!checkclass)
|
||||||
|
{
|
||||||
|
checkclass = PClass::FindClass(v.GetName());
|
||||||
|
if (!checkclass) { ret.Int = 0; return ret; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool match_superclass = false;
|
||||||
|
int pick_pointer = AAPTR_DEFAULT;
|
||||||
|
|
||||||
|
switch (ArgList->Size())
|
||||||
|
{
|
||||||
|
case 3: match_superclass = (*ArgList)[2]->EvalExpression(self).GetBool();
|
||||||
|
case 2: pick_pointer = (*ArgList)[1]->EvalExpression(self).GetInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
self = COPY_AAPTR(self, pick_pointer);
|
||||||
|
if (!self){ ret.Int = 0; return ret; }
|
||||||
|
ret.Int = match_superclass ? checkclass->IsAncestorOf(self->GetClass()) : checkclass == self->GetClass();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GLOBALFUNCTION_ADDER(CheckClass);
|
|
@ -51,7 +51,7 @@ const char *GetVersionString();
|
||||||
// Version identifier for network games.
|
// Version identifier for network games.
|
||||||
// Bump it every time you do a release unless you're certain you
|
// Bump it every time you do a release unless you're certain you
|
||||||
// didn't change anything that will affect sync.
|
// didn't change anything that will affect sync.
|
||||||
#define NETGAMEVERSION 230
|
#define NETGAMEVERSION 231
|
||||||
|
|
||||||
// Version stored in the ini's [LastRun] section.
|
// Version stored in the ini's [LastRun] section.
|
||||||
// Bump it if you made some configuration change that you want to
|
// Bump it if you made some configuration change that you want to
|
||||||
|
|
|
@ -304,6 +304,9 @@ ACTOR Actor native //: Thinker
|
||||||
action native A_SetDamageType(name damagetype);
|
action native A_SetDamageType(name damagetype);
|
||||||
action native A_DropItem(class<Actor> item, int dropamount = -1, int chance = 256);
|
action native A_DropItem(class<Actor> item, int dropamount = -1, int chance = 256);
|
||||||
action native A_SetSpeed(float speed);
|
action native A_SetSpeed(float speed);
|
||||||
|
action native A_DamageSelf(int amount, name damagetype = "none");
|
||||||
|
action native A_DamageTarget(int amount, name damagetype = "none");
|
||||||
|
action native A_DamageTracer(int amount, name damagetype = "none");
|
||||||
|
|
||||||
action native A_CheckSightOrRange(float distance, state label);
|
action native A_CheckSightOrRange(float distance, state label);
|
||||||
action native A_CheckRange(float distance, state label);
|
action native A_CheckRange(float distance, state label);
|
||||||
|
|
|
@ -836,6 +836,7 @@ SCORE_BONUS = "BONUS";
|
||||||
SCORE_COLOR = "COLOR";
|
SCORE_COLOR = "COLOR";
|
||||||
SCORE_SECRET = "SECRET";
|
SCORE_SECRET = "SECRET";
|
||||||
SCORE_NAME = "NAME";
|
SCORE_NAME = "NAME";
|
||||||
|
SCORE_DELAY = "DELAY(ms)";
|
||||||
SCORE_KILLS = "KILLS";
|
SCORE_KILLS = "KILLS";
|
||||||
SCORE_FRAGS = "FRAGS";
|
SCORE_FRAGS = "FRAGS";
|
||||||
SCORE_DEATHS = "DEATHS";
|
SCORE_DEATHS = "DEATHS";
|
||||||
|
|
|
@ -341,6 +341,7 @@ OptionMenu "OptionsMenu"
|
||||||
Submenu "Automap Options", "AutomapOptions"
|
Submenu "Automap Options", "AutomapOptions"
|
||||||
Submenu "HUD Options", "HUDOptions"
|
Submenu "HUD Options", "HUDOptions"
|
||||||
Submenu "Miscellaneous Options", "MiscOptions"
|
Submenu "Miscellaneous Options", "MiscOptions"
|
||||||
|
Submenu "Network Options", "NetworkOptions"
|
||||||
Submenu "Sound Options", "SoundOptions"
|
Submenu "Sound Options", "SoundOptions"
|
||||||
Submenu "Display Options", "VideoOptions"
|
Submenu "Display Options", "VideoOptions"
|
||||||
Submenu "Set video mode", "VideoModeMenu"
|
Submenu "Set video mode", "VideoModeMenu"
|
||||||
|
@ -805,6 +806,13 @@ OptionValue "AltHUDTime"
|
||||||
9, "System"
|
9, "System"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OptionValue "AltHUDLag"
|
||||||
|
{
|
||||||
|
0, "Off"
|
||||||
|
1, "Netgames only"
|
||||||
|
2, "Always"
|
||||||
|
}
|
||||||
|
|
||||||
OptionMenu "AltHUDOptions"
|
OptionMenu "AltHUDOptions"
|
||||||
{
|
{
|
||||||
Title "Alternative HUD"
|
Title "Alternative HUD"
|
||||||
|
@ -819,6 +827,7 @@ OptionMenu "AltHUDOptions"
|
||||||
Option "Show weapons", "hud_showweapons", "OnOff"
|
Option "Show weapons", "hud_showweapons", "OnOff"
|
||||||
Option "Show time", "hud_showtime", "AltHUDTime"
|
Option "Show time", "hud_showtime", "AltHUDTime"
|
||||||
Option "Time color", "hud_timecolor", "TextColors"
|
Option "Time color", "hud_timecolor", "TextColors"
|
||||||
|
Option "Show network latency", "hud_showlag", "AltHUDLag"
|
||||||
Slider "Red ammo display below %", "hud_ammo_red", 0, 100, 1, 0
|
Slider "Red ammo display below %", "hud_ammo_red", 0, 100, 1, 0
|
||||||
Slider "Yellow ammo display below %", "hud_ammo_yellow", 0, 100, 1, 0
|
Slider "Yellow ammo display below %", "hud_ammo_yellow", 0, 100, 1, 0
|
||||||
Slider "Red health display below", "hud_health_red", 0, 100, 1, 0
|
Slider "Red health display below", "hud_health_red", 0, 100, 1, 0
|
||||||
|
@ -1591,3 +1600,28 @@ OptionMenu VideoModeMenu
|
||||||
class VideoModeMenu
|
class VideoModeMenu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*=======================================
|
||||||
|
*
|
||||||
|
* Network options menu
|
||||||
|
*
|
||||||
|
*=======================================*/
|
||||||
|
|
||||||
|
OptionMenu NetworkOptions
|
||||||
|
{
|
||||||
|
Title "NETWORK OPTIONS"
|
||||||
|
StaticText "Local options", 1
|
||||||
|
Option "Movement prediction", "cl_noprediction", "OffOn"
|
||||||
|
Option "Predict line actions", "cl_predict_specials", "OnOff"
|
||||||
|
StaticText " "
|
||||||
|
StaticText "Host options", 1
|
||||||
|
Option "Extra Tics", "net_extratic", "ExtraTicMode"
|
||||||
|
Option "Latency balancing", "net_ticbalance", "OnOff"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionValue ExtraTicMode
|
||||||
|
{
|
||||||
|
0, "None"
|
||||||
|
1, "1"
|
||||||
|
2, "All unacknowledged"
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue