This commit is contained in:
Christoph Oelckers 2014-10-14 08:54:41 +02:00
commit 57895d69f9
21 changed files with 663 additions and 528 deletions

View File

@ -937,9 +937,6 @@ public:
TObjPtr<AInventory> Inventory; // [RH] This actor's inventory TObjPtr<AInventory> Inventory; // [RH] This actor's inventory
DWORD InventoryID; // A unique ID to keep track of inventory items DWORD InventoryID; // A unique ID to keep track of inventory items
//Added by MC:
SDWORD id; // Player ID (for items, # in list.)
BYTE smokecounter; BYTE smokecounter;
BYTE FloatBobPhase; BYTE FloatBobPhase;
BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc) BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc)

View File

@ -249,7 +249,7 @@ shootmissile:
if (m) if (m)
{ {
if (inc[actor->id]) if (inc[actor->player - players])
actor->player->angle += m; actor->player->angle += m;
else else
actor->player->angle -= m; actor->player->angle -= m;
@ -257,7 +257,7 @@ shootmissile:
if (abs (actor->player->angle - actor->angle) < 4*ANGLE_1) if (abs (actor->player->angle - actor->angle) < 4*ANGLE_1)
{ {
inc[actor->id] = !inc[actor->id]; inc[actor->player - players] = !inc[actor->player - players];
} }
if (Check_LOS (actor, enemy, (SHOOTFOV/2))) if (Check_LOS (actor, enemy, (SHOOTFOV/2)))

View File

@ -17,20 +17,7 @@
#include "gi.h" #include "gi.h"
#include "a_keys.h" #include "a_keys.h"
#include "d_event.h" #include "d_event.h"
#include "p_enemy.h"
enum dirtype_t
{
DI_EAST,
DI_NORTHEAST,
DI_NORTH,
DI_NORTHWEST,
DI_WEST,
DI_SOUTHWEST,
DI_SOUTH,
DI_SOUTHEAST,
DI_NODIR,
NUMDIRS
};
static FRandom pr_botopendoor ("BotOpenDoor"); static FRandom pr_botopendoor ("BotOpenDoor");
static FRandom pr_bottrywalk ("BotTryWalk"); static FRandom pr_bottrywalk ("BotTryWalk");
@ -39,10 +26,6 @@ static FRandom pr_botnewchasedir ("BotNewChaseDir");
// borrow some tables from p_enemy.cpp // borrow some tables from p_enemy.cpp
extern dirtype_t opposite[9]; extern dirtype_t opposite[9];
extern dirtype_t diags[4]; extern dirtype_t diags[4];
extern fixed_t xspeed[8];
extern fixed_t yspeed[8];
extern TArray<line_t *> spechit;
//Called while the bot moves after its player->dest mobj //Called while the bot moves after its player->dest mobj
//which can be a weapon/enemy/item whatever. //which can be a weapon/enemy/item whatever.

View File

@ -273,7 +273,8 @@ void CT_Drawer (void)
if (players[consoleplayer].camera != NULL && if (players[consoleplayer].camera != NULL &&
(Button_ShowScores.bDown || (Button_ShowScores.bDown ||
players[consoleplayer].camera->health <= 0) && players[consoleplayer].camera->health <= 0 ||
SB_ForceActive) &&
// Don't draw during intermission, since it has its own scoreboard in wi_stuff.cpp. // Don't draw during intermission, since it has its own scoreboard in wi_stuff.cpp.
gamestate != GS_INTERMISSION) gamestate != GS_INTERMISSION)
{ {

View File

@ -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)
{ {

View File

@ -60,9 +60,6 @@
static FRandom pr_pickteam ("PickRandomTeam"); static FRandom pr_pickteam ("PickRandomTeam");
extern bool st_firsttime;
EXTERN_CVAR (Bool, teamplay)
CVAR (Float, autoaim, 5000.f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Float, autoaim, 5000.f, CVAR_USERINFO | CVAR_ARCHIVE);
CVAR (String, name, "Player", CVAR_USERINFO | CVAR_ARCHIVE); CVAR (String, name, "Player", CVAR_USERINFO | CVAR_ARCHIVE);
CVAR (Color, color, 0x40cf00, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Color, color, 0x40cf00, CVAR_USERINFO | CVAR_ARCHIVE);

View File

@ -76,8 +76,6 @@ FPlayerColorSet *P_GetPlayerColorSet(FName classname, int setnum);
void P_EnumPlayerColorSets(FName classname, TArray<int> *out); void P_EnumPlayerColorSets(FName classname, TArray<int> *out);
const char *GetPrintableDisplayName(const PClass *cls); const char *GetPrintableDisplayName(const PClass *cls);
class player_t;
class APlayerPawn : public AActor class APlayerPawn : public AActor
{ {
DECLARE_CLASS (APlayerPawn, AActor) DECLARE_CLASS (APlayerPawn, AActor)
@ -176,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;
@ -398,7 +397,6 @@ public:
int inventorytics; int inventorytics;
BYTE CurrentPlayerClass; // class # for this player instance BYTE CurrentPlayerClass; // class # for this player instance
bool backpack;
int frags[MAXPLAYERS]; // kills of other players int frags[MAXPLAYERS]; // kills of other players
int fragcount; // [RH] Cumulative frags for this player int fragcount; // [RH] Cumulative frags for this player

View File

@ -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;

View File

@ -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);

View File

@ -1025,7 +1025,7 @@ void AInventory::Touch (AActor *toucher)
for (int i = 0; i < MAXPLAYERS; i++) for (int i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && this == players[i].dest) if (playeringame[i] && this == players[i].dest)
players[i].dest = NULL; players[i].dest = NULL;
} }
} }

View File

@ -49,6 +49,7 @@
#include "hu_stuff.h" #include "hu_stuff.h"
#include "gstrings.h" #include "gstrings.h"
#include "d_net.h" #include "d_net.h"
#include "c_dispatch.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------
@ -117,6 +118,8 @@ int STACK_ARGS compareteams (const void *arg1, const void *arg2)
return diff; return diff;
} }
bool SB_ForceActive = false;
// PRIVATE DATA DEFINITIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE -------------------------------------------------------------------- // CODE --------------------------------------------------------------------
@ -492,3 +495,8 @@ int HU_GetRowColor(player_t *player, bool highlight)
} }
} }
} }
CCMD (togglescoreboard)
{
SB_ForceActive = !SB_ForceActive;
}

View File

@ -52,6 +52,8 @@ void HU_GetPlayerWidths(int &maxnamewidth, int &maxscorewidth, int &maxiconheigh
void HU_DrawColorBar(int x, int y, int height, int playernum); void HU_DrawColorBar(int x, int y, int height, int playernum);
int HU_GetRowColor(player_t *player, bool hightlight); int HU_GetRowColor(player_t *player, bool hightlight);
extern bool SB_ForceActive;
// Sorting routines // Sorting routines
int STACK_ARGS comparepoints(const void *arg1, const void *arg2); int STACK_ARGS comparepoints(const void *arg1, const void *arg2);

View File

@ -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;
} }

View File

@ -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

View File

@ -252,9 +252,13 @@ void AActor::Serialize (FArchive &arc)
<< MinMissileChance << MinMissileChance
<< SpawnFlags << SpawnFlags
<< Inventory << Inventory
<< InventoryID << InventoryID;
<< id if (SaveVersion < 4513)
<< FloatBobPhase {
SDWORD id;
arc << id;
}
arc << FloatBobPhase
<< Translation << Translation
<< SeeSound << SeeSound
<< AttackSound << AttackSound
@ -4246,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)
@ -4358,9 +4368,6 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
mobj->pitch = mobj->roll = 0; mobj->pitch = mobj->roll = 0;
mobj->health = p->health; mobj->health = p->health;
//Added by MC: Identification (number in the players[MAXPLAYERS] array)
mobj->id = playernum;
// [RH] Set player sprite based on skin // [RH] Set player sprite based on skin
if (!(mobj->flags4 & MF4_NOSKIN)) if (!(mobj->flags4 & MF4_NOSKIN))
{ {

View File

@ -328,7 +328,6 @@ static AActor *SelectTeleDest (int tid, int tag, bool norandom)
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;
@ -341,6 +340,7 @@ bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool
{ // Teleport function called with an invalid actor { // Teleport function called with an invalid actor
return false; return false;
} }
bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING));
if (thing->flags2 & MF2_NOTELEPORT) if (thing->flags2 & MF2_NOTELEPORT)
{ {
return false; return false;

View File

@ -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;
@ -240,7 +261,6 @@ player_t::player_t()
health(0), health(0),
inventorytics(0), inventorytics(0),
CurrentPlayerClass(0), CurrentPlayerClass(0),
backpack(0),
fragcount(0), fragcount(0),
lastkilltime(0), lastkilltime(0),
multicount(0), multicount(0),
@ -341,7 +361,6 @@ player_t &player_t::operator=(const player_t &p)
health = p.health; health = p.health;
inventorytics = p.inventorytics; inventorytics = p.inventorytics;
CurrentPlayerClass = p.CurrentPlayerClass; CurrentPlayerClass = p.CurrentPlayerClass;
backpack = p.backpack;
memcpy(frags, &p.frags, sizeof(frags)); memcpy(frags, &p.frags, sizeof(frags));
fragcount = p.fragcount; fragcount = p.fragcount;
lastkilltime = p.lastkilltime; lastkilltime = p.lastkilltime;
@ -2638,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;
@ -2665,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;
@ -2723,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)
@ -2732,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;
}
}
} }
} }
@ -2744,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
@ -2754,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.
@ -2859,6 +2939,9 @@ void P_UnPredictPlayer ()
} }
block = block->NextBlock; block = block->NextBlock;
} }
act->InvSel = InvSel;
player->inventorytics = inventorytics;
} }
} }
@ -2889,9 +2972,13 @@ void player_t::Serialize (FArchive &arc)
<< vely << vely
<< centering << centering
<< health << health
<< inventorytics << inventorytics;
<< backpack if (SaveVersion < 4513)
<< fragcount {
bool backpack;
arc << backpack;
}
arc << fragcount
<< spreecount << spreecount
<< multicount << multicount
<< lastkilltime << lastkilltime

View File

@ -1768,6 +1768,7 @@ enum SIX_Flags
SIXF_SETTARGET = 1 << 20, SIXF_SETTARGET = 1 << 20,
SIXF_SETTRACER = 1 << 21, SIXF_SETTRACER = 1 << 21,
SIXF_NOPOINTERS = 1 << 22, SIXF_NOPOINTERS = 1 << 22,
SIXF_ORIGINATOR = 1 << 23,
}; };
static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
@ -1803,11 +1804,13 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
{ {
mo->pitch = self->pitch; mo->pitch = self->pitch;
} }
while (originator && originator->isMissile()) if (!(flags & SIXF_ORIGINATOR))
{ {
originator = originator->target; while (originator && originator->isMissile())
{
originator = originator->target;
}
} }
if (flags & SIXF_TELEFRAG) if (flags & SIXF_TELEFRAG)
{ {
P_TeleportMove(mo, mo->x, mo->y, mo->z, true); P_TeleportMove(mo, mo->x, mo->y, mo->z, true);
@ -3278,18 +3281,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
enum JLOS_flags enum JLOS_flags
{ {
JLOSF_PROJECTILE=1, JLOSF_PROJECTILE = 1,
JLOSF_NOSIGHT=2, JLOSF_NOSIGHT = 1 << 1,
JLOSF_CLOSENOFOV=4, JLOSF_CLOSENOFOV = 1 << 2,
JLOSF_CLOSENOSIGHT=8, JLOSF_CLOSENOSIGHT = 1 << 3,
JLOSF_CLOSENOJUMP=16, JLOSF_CLOSENOJUMP = 1 << 4,
JLOSF_DEADNOJUMP=32, JLOSF_DEADNOJUMP = 1 << 5,
JLOSF_CHECKMASTER=64, JLOSF_CHECKMASTER = 1 << 6,
JLOSF_TARGETLOS=128, JLOSF_TARGETLOS = 1 << 7,
JLOSF_FLIPFOV=256, JLOSF_FLIPFOV = 1 << 8,
JLOSF_ALLYNOJUMP=512, JLOSF_ALLYNOJUMP = 1 << 9,
JLOSF_COMBATANTONLY=1024, JLOSF_COMBATANTONLY = 1 << 10,
JLOSF_NOAUTOAIM=2048, JLOSF_NOAUTOAIM = 1 << 11,
JLOSF_CHECKTRACER = 1 << 12,
}; };
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
@ -3314,9 +3318,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
{ {
target = self->master; target = self->master;
} }
else if (self->flags & MF_MISSILE && (flags & JLOSF_PROJECTILE)) else if ((self->flags & MF_MISSILE && (flags & JLOSF_PROJECTILE)) || (flags & JLOSF_CHECKTRACER))
{ {
if (self->flags2 & MF2_SEEKERMISSILE) if ((self->flags2 & MF2_SEEKERMISSILE) || (flags & JLOSF_CHECKTRACER))
target = self->tracer; target = self->tracer;
else else
target = NULL; target = NULL;
@ -5002,7 +5006,7 @@ static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags
//since that's the whole point of it. //since that's the whole point of it.
if ((!(killtarget->flags2 & MF2_INVULNERABLE) || (flags & KILS_FOILINVUL)) && !(killtarget->flags5 & MF5_NODAMAGE)) if ((!(killtarget->flags2 & MF2_INVULNERABLE) || (flags & KILS_FOILINVUL)) && !(killtarget->flags5 & MF5_NODAMAGE))
{ {
P_ExplodeMissile(self->target, NULL, NULL); P_ExplodeMissile(killtarget, NULL, NULL);
} }
} }
if (!(flags & KILS_NOMONSTERS)) if (!(flags & KILS_NOMONSTERS))
@ -5112,9 +5116,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings)
enum RMVF_flags enum RMVF_flags
{ {
RMVF_MISSILES = 1 << 0, RMVF_MISSILES = 1 << 0,
RMVF_NOMONSTERS = 1 << 1, RMVF_NOMONSTERS = 1 << 1,
RMVF_MISC = 1 << 2, RMVF_MISC = 1 << 2,
RMVF_EVERYTHING = 1 << 3, RMVF_EVERYTHING = 1 << 3,
}; };

View File

@ -76,7 +76,7 @@ const char *GetVersionString();
// Use 4500 as the base git save version, since it's higher than the // Use 4500 as the base git save version, since it's higher than the
// SVN revision ever got. // SVN revision ever got.
#define SAVEVER 4512 #define SAVEVER 4513
#define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY2(x) #x
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)

View File

@ -70,6 +70,7 @@ const int SXF_TRANSFERRENDERSTYLE = 1 << 19;
const int SXF_SETTARGET = 1 << 20; const int SXF_SETTARGET = 1 << 20;
const int SXF_SETTRACER = 1 << 21; const int SXF_SETTRACER = 1 << 21;
const int SXF_NOPOINTERS = 1 << 22; const int SXF_NOPOINTERS = 1 << 22;
const int SXF_ORIGINATOR = 1 << 23;
// Flags for A_Chase // Flags for A_Chase
const int CHF_FASTCHASE = 1; const int CHF_FASTCHASE = 1;
@ -92,18 +93,22 @@ const int RSF_KEEPTARGET = 2;
const int RSF_TELEFRAG = 4; const int RSF_TELEFRAG = 4;
// Flags for A_JumpIfTargetInLOS and A_JumpIfInTargetLOS // Flags for A_JumpIfTargetInLOS and A_JumpIfInTargetLOS
const int JLOSF_PROJECTILE = 1; enum
const int JLOSF_NOSIGHT = 2; {
const int JLOSF_CLOSENOFOV = 4; JLOSF_PROJECTILE = 1,
const int JLOSF_CLOSENOSIGHT = 8; JLOSF_NOSIGHT = 1 << 1,
const int JLOSF_CLOSENOJUMP = 16; JLOSF_CLOSENOFOV = 1 << 2,
const int JLOSF_DEADNOJUMP = 32; JLOSF_CLOSENOSIGHT = 1 << 3,
const int JLOSF_CHECKMASTER = 64; JLOSF_CLOSENOJUMP = 1 << 4,
const int JLOSF_TARGETLOS = 128; JLOSF_DEADNOJUMP = 1 << 5,
const int JLOSF_FLIPFOV = 256; JLOSF_CHECKMASTER = 1 << 6,
const int JLOSF_ALLYNOJUMP = 512; JLOSF_TARGETLOS = 1 << 7,
const int JLOSF_COMBATANTONLY = 1024; JLOSF_FLIPFOV = 1 << 8,
const int JLOSF_NOAUTOAIM = 2048; JLOSF_ALLYNOJUMP = 1 << 9,
JLOSF_COMBATANTONLY = 1 << 10,
JLOSF_NOAUTOAIM = 1 << 11,
JLOSF_CHECKTRACER = 1 << 12,
};
// Flags for A_ChangeVelocity // Flags for A_ChangeVelocity
const int CVF_RELATIVE = 1; const int CVF_RELATIVE = 1;
@ -375,7 +380,7 @@ const int KILS_NOMONSTERS = 4;
const int DMSS_FOILINVUL = 1; const int DMSS_FOILINVUL = 1;
const int DMSS_AFFECTARMOR = 2; const int DMSS_AFFECTARMOR = 2;
const int DMSS_KILL = 4; const int DMSS_KILL = 4;
const int DMSS_NOFACTOR = 8; const int DMSS_NOFACTOR = 8;
// Flags for A_AlertMonsters // Flags for A_AlertMonsters
const int AMF_TARGETEMITTER = 1; const int AMF_TARGETEMITTER = 1;
@ -388,7 +393,7 @@ enum
RMVF_MISSILES = 1 << 0, RMVF_MISSILES = 1 << 0,
RMVF_NOMONSTERS = 1 << 1, RMVF_NOMONSTERS = 1 << 1,
RMVF_MISC = 1 << 2, RMVF_MISC = 1 << 2,
RMVF_EVERYTHING = 1 << 3 RMVF_EVERYTHING = 1 << 3,
}; };

View File

@ -458,6 +458,7 @@ OptionMenu "CustomizeControls"
Control "Run", "+speed" Control "Run", "+speed"
Control "Strafe", "+strafe" Control "Strafe", "+strafe"
Control "Show Scoreboard", "+showscores" Control "Show Scoreboard", "+showscores"
Control "Toggle Scoreboard", "togglescoreboard"
StaticText "" StaticText ""
StaticText "Chat", 1 StaticText "Chat", 1
Control "Say", "messagemode" Control "Say", "messagemode"
@ -1612,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"