- transitioned Shadow Warrior to new main loop.

Problem: Does not work yet with cl_syncinput = 0. Something about those angle and horizon settings is not right yet.
This commit is contained in:
Christoph Oelckers 2020-09-02 20:56:09 +02:00
parent 141b5c00cd
commit a222a7d7c9
10 changed files with 111 additions and 299 deletions

View file

@ -866,7 +866,7 @@ int RunGame()
videoInit();
// Duke has transitioned to the new main loop, the other games haven't yet.
if (!(g_gameType & (GAMEFLAG_SW | GAMEFLAG_PSEXHUMED)))
if (!(g_gameType & (GAMEFLAG_PSEXHUMED)))
{
D_CheckNetGame();
MainLoop();

View file

@ -75,6 +75,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
#include "screenjob.h"
#include "inputstate.h"
#include "gamestate.h"
#include "d_net.h"
//#include "crc32.h"
@ -267,7 +268,7 @@ void StartMenu()
//
//---------------------------------------------------------------------------
void DrawMenuLevelScreen(void)
void GameInterface::DrawBackground(void)
{
const int TITLE_PIC = 2324;
twod->ClearScreen();
@ -279,6 +280,13 @@ void DrawMenuLevelScreen(void)
MNU_DrawString(160, 170, "Lo Wang is waiting for other players...", 1, 16, 0);
MNU_DrawString(160, 180, "They are afraid!", 1, 16, 0);
}
// hack alert. This needs to go away.
if (SavegameLoaded || NextLevel)
{
TerminateLevel();
ExitLevel = false;
gamestate = GS_LEVEL;
}
}
//---------------------------------------------------------------------------
@ -462,9 +470,6 @@ void InitPlayerGameSettings(void)
void InitRunLevel(void)
{
//SendVersion(GameVersion);
//waitforeverybody();
Mus_Stop();
DoTheCache();
@ -485,11 +490,6 @@ void InitRunLevel(void)
InitPrediction(&Player[myconnectindex]);
waitforeverybody();
//CheckVersion(GameVersion);
// IMPORTANT - MUST be right before game loop AFTER waitforeverybody
InitTimingVars();
if (snd_ambience)
@ -607,57 +607,10 @@ void TerminateLevel(void)
//
//---------------------------------------------------------------------------
void MoveTicker(void)
{
int pnum;
//getpackets();
if (PredictionOn && CommEnabled)
{
while (predictmovefifoplc < Player[myconnectindex].movefifoend)
{
DoPrediction(ppp);
}
}
//While you have new input packets to process...
if (!CommEnabled)
bufferjitter = 0;
while (Player[myconnectindex].movefifoend - movefifoplc > bufferjitter)
{
//Make sure you have at least 1 packet from everyone else
for (pnum = connecthead; pnum >= 0; pnum = connectpoint2[pnum])
{
if (movefifoplc == Player[pnum].movefifoend)
{
break;
}
}
//Pnum is >= 0 only if last loop was broken, meaning a player wasn't caught up
if (pnum >= 0)
break;
domovethings();
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void EndOfLevel()
{
STAT_Update(false);
// for good measure do this
ready2send = 0;
waitforeverybody();
if (FinishedLevel)
{
//ResetPalette(mpp);
@ -697,7 +650,7 @@ void EndOfLevel()
//
//---------------------------------------------------------------------------
void GameTicker(void)
void GameInterface::Ticker(void)
{
if (!ExitLevel)
{
@ -708,11 +661,6 @@ void GameTicker(void)
// contains what is needed from calls below
if (snd_ambience)
StartAmbientSound();
// crappy little hack to prevent play clock from being overwritten
// for load games
int SavePlayClock = PlayClock;
InitTimingVars();
PlayClock = SavePlayClock;
ExitLevel = false;
}
else if (NextLevel)
@ -721,84 +669,60 @@ void GameTicker(void)
InitRunLevel();
ExitLevel = false;
}
ready2send = 1;
int const currentTic = I_GetTime();
if (paused)
{
smoothratio = MaxSmoothRatio;
}
else
{
gameupdatetime.Reset();
gameupdatetime.Clock();
while (ready2send && currentTic - lastTic >= 1)
{
lastTic = currentTic;
UpdateInputs();
MoveTicker();
}
gameupdatetime.Unclock();
// Get input again to update q16ang/q16horiz.
if (!cl_syncinput)
getinput(&loc, TRUE);
smoothratio = I_GetTimeFrac() * MaxSmoothRatio;
}
drawtime.Reset();
drawtime.Clock();
drawscreen(Player + screenpeek, smoothratio);
drawtime.Unclock();
ready2send = 0;
}
int i;
TRAVERSE_CONNECT(i)
{
auto pp = Player + i;
pp->lastinput = pp->input;
pp->input = playercmds[i].ucmd;
}
domovethings();
r_NoInterpolate = paused;
if (ExitLevel)
{
ExitLevel = false;
EndOfLevel();
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void GameInterface::Render()
{
if (paused)
{
smoothratio = MaxSmoothRatio;
}
else
{
smoothratio = I_GetTimeFrac() * MaxSmoothRatio;
}
drawtime.Reset();
drawtime.Clock();
drawscreen(Player + screenpeek, smoothratio);
drawtime.Unclock();
}
void GameInterface::RunGameFrame()
void GameInterface::Startup()
{
// if the menu initiazed a new game or loaded a savegame, switch to play mode.
if (SavegameLoaded || NextLevel) gamestate = GS_LEVEL;
gi->UpdateSounds();
switch (gamestate)
if (userConfig.CommandMap.IsNotEmpty())
{
default:
case GS_STARTUP:
if (userConfig.CommandMap.IsNotEmpty())
{
}
else
{
if (!userConfig.nologo) Logo([](bool) { StartMenu(); });
else StartMenu();
}
break;
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
DrawMenuLevelScreen();
break;
case GS_LEVEL:
GameTicker();
break;
case GS_INTERMISSION:
case GS_INTRO:
RunScreenJobFrame(); // This handles continuation through its completion callback.
break;
}
else
{
if (!userConfig.nologo) Logo([](bool) { StartMenu(); });
else StartMenu();
}
}

View file

@ -915,13 +915,7 @@ struct PLAYERstruct
//Multiplayer variables
InputPacket input;
//FIFO queue to hold values while faketimerhandler is called from within the drawing routing
#define MOVEFIFOSIZ 256
InputPacket inputfifo[MOVEFIFOSIZ];
int movefifoend;
InputPacket lastinput;
// must start out as 0
int playerreadyflag;
@ -2013,7 +2007,7 @@ extern int x_min_bound, y_min_bound, x_max_bound, y_max_bound;
//extern unsigned char synctics, lastsynctics;
extern short snum;
extern int lockspeed,totalsynctics;
extern int lockspeed;
#define synctics 3
#define ACTORMOVETICS (synctics<<1)
@ -2059,10 +2053,6 @@ extern double smoothratio;
// local copy of variables updated by faketimerhandler
extern int locselectedgun;
//FIFO queue to hold values while faketimerhandler is called from within the drawing routing
extern int movefifoplc, movefifoend[];
extern SWBOOL MoveSkip4, MoveSkip2, MoveSkip8;
#define MASTER_SWITCHING 1
@ -2211,7 +2201,6 @@ struct GameInterface : ::GameInterface
{
const char* Name() override { return "ShadowWarrior"; }
void app_init() override;
void RunGameFrame() override;
void FreeGameData() override;
bool GenerateSavePic() override;
void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) override;
@ -2232,6 +2221,11 @@ struct GameInterface : ::GameInterface
void ResetFollowPos(bool message) override;
void UpdateSounds() override;
void ErrorCleanup() override;
void GetInput(InputPacket* input) override;
void DrawBackground(void) override;
void Ticker(void) override;
void Render() override;
void Startup() override;
GameStats getStats() override;
};

View file

@ -40,6 +40,25 @@ double scaleAdjustmentToInterval(double x) { return x * (120 / synctics) / (1000
void DoPlayerTurn(PLAYERp pp, fixed_t *pq16ang, fixed_t q16angvel);
void DoPlayerHorizon(PLAYERp pp, fixed_t *pq16horiz, fixed_t q16horz);
InputPacket loc;
void
InitNetVars(void)
{
loc = {};
}
void
InitTimingVars(void)
{
PlayClock = 0;
randomseed = 17L;
MoveSkip8 = 2;
MoveSkip2 = 0;
MoveSkip4 = 1; // start slightly offset so these
}
void GameInterface::ResetFollowPos(bool)
{
@ -359,4 +378,17 @@ getinput(InputPacket *loc, SWBOOL tied)
}
}
void GameInterface::GetInput(InputPacket *packet)
{
getinput(&loc, FALSE);
if (packet)
{
PLAYERp pp = &Player[myconnectindex];
loc.q16ang = pp->camq16ang;
loc.q16horiz = pp->camq16horiz;
*packet = loc;
loc = {};
}
}
END_SW_NS

View file

@ -55,7 +55,6 @@ gNET gNet;
//Local multiplayer variables
// should move this to a local scope of faketimerhandler - do it when able to test
InputPacket loc;
//InputPacket oloc;
@ -63,7 +62,6 @@ SWBOOL ready2send = 0;
SWBOOL CommEnabled = FALSE;
uint8_t CommPlayers = 0;
int movefifoplc, movefifosendplc; //, movefifoend[MAX_SW_PLAYERS];
int bufferjitter = 1;
@ -88,82 +86,4 @@ InitNetPlayerOptions(void)
}
}
void
waitforeverybody(void)
{
}
void
InitNetVars(void)
{
short pnum;
PLAYERp pp;
memset(&loc, 0, sizeof(loc));
TRAVERSE_CONNECT(pnum)
{
pp = Player + pnum;
pp->movefifoend = 0;
memset(pp->inputfifo,0,sizeof(pp->inputfifo));
}
movefifoplc = 0;
movefifosendplc = 0;
predictmovefifoplc = 0;
}
void
InitTimingVars(void)
{
PlayClock = 0;
// resettiming();
totalsynctics = 0;
randomseed = 17L;
MoveSkip8 = 2;
MoveSkip2 = 0;
MoveSkip4 = 1; // start slightly offset so these
}
void
UpdateInputs(void)
{
int i, j, k;
PLAYERp pp;
//getpackets();
if (Player[myconnectindex].movefifoend - movefifoplc >= 100)
return;
getinput(&loc, FALSE);
pp = Player + myconnectindex;
loc.q16ang = pp->camq16ang;
loc.q16horiz = pp->camq16horiz;
pp->inputfifo[Player[myconnectindex].movefifoend & (MOVEFIFOSIZ - 1)] = loc;
pp->movefifoend++;
Bmemset(&loc, 0, sizeof(loc));
if (!CommEnabled)
{
TRAVERSE_CONNECT(i)
{
if (i != myconnectindex)
{
memset(&Player[i].inputfifo[Player[i].movefifoend & (MOVEFIFOSIZ - 1)], 0, sizeof(Player[i].inputfifo[0]));
Player[i].movefifoend++;
}
}
return;
}
}
END_SW_NS

View file

@ -32,7 +32,7 @@ BEGIN_SW_NS
extern SWBOOL PredictionOn;
extern PLAYER PredictPlayer;
extern PLAYERp ppp;
extern short predictangpos[MOVEFIFOSIZ];
extern short predictangpos[];
extern int predictmovefifoplc;
extern SWBOOL Prediction;
@ -74,7 +74,6 @@ extern gNET gNet;
void UpdateInputs(void);
void InitNetVars(void);
void InitTimingVars(void);
void waitforeverybody(void);
void InitNetPlayerOptions(void);
inline void SW_SendMessage(short, const char*) {}

View file

@ -1756,18 +1756,12 @@ DoPlayerTurnTurret(PLAYERp pp)
short new_ang;
short diff;
SECTOR_OBJECTp sop = pp->sop;
InputPacket last_input;
int fifo_ndx;
if (!Prediction)
{
// this code looks at the fifo to get the last value for comparison
fifo_ndx = (movefifoplc-2) & (MOVEFIFOSIZ - 1);
last_input = pp->inputfifo[fifo_ndx];
if (pp->input.q16avel && !last_input.q16avel)
if (pp->input.q16avel && !pp->lastinput.q16avel)
PlaySOsound(pp->sop->mid_sector, SO_DRIVE_SOUND);
else if (!pp->input.q16avel && last_input.q16avel)
else if (!pp->input.q16avel && pp->lastinput.q16avel)
PlaySOsound(pp->sop->mid_sector, SO_IDLE_SOUND);
}
@ -2526,11 +2520,6 @@ MoveScrollMode2D(PLAYERp pp)
}
void
DoPlayerMenuKeys(PLAYERp pp)
{
}
void PlayerSectorBound(PLAYERp pp, int amt)
{
if (pp->cursectnum < 9)
@ -2838,21 +2827,14 @@ DoPlayerMoveBoat(PLAYERp pp)
short save_sectnum;
SECTOR_OBJECTp sop = pp->sop;
InputPacket last_input;
int fifo_ndx;
if (Prediction)
return;
if (!Prediction)
{
// this code looks at the fifo to get the last value for comparison
fifo_ndx = (movefifoplc-2) & (MOVEFIFOSIZ - 1);
last_input = pp->inputfifo[fifo_ndx];
if (labs(pp->input.fvel|pp->input.svel) && !labs(last_input.fvel|last_input.svel))
if (labs(pp->input.fvel|pp->input.svel) && !labs(pp->lastinput.fvel| pp->lastinput.svel))
PlaySOsound(pp->sop->mid_sector,SO_DRIVE_SOUND);
else if (!labs(pp->input.fvel|pp->input.svel) && labs(last_input.fvel|last_input.svel))
else if (!labs(pp->input.fvel|pp->input.svel) && labs(pp->lastinput.fvel| pp->lastinput.svel))
PlaySOsound(pp->sop->mid_sector,SO_IDLE_SOUND);
}
@ -3201,8 +3183,6 @@ DoPlayerMoveTank(PLAYERp pp)
int j,k;
short startwall,endwall;
InputPacket last_input;
int fifo_ndx;
SWBOOL RectClip = !!TEST(sop->flags, SOBJ_RECT_CLIP);
if (Prediction)
@ -3210,13 +3190,9 @@ DoPlayerMoveTank(PLAYERp pp)
if (!Prediction)
{
// this code looks at the fifo to get the last value for comparison
fifo_ndx = (movefifoplc-2) & (MOVEFIFOSIZ - 1);
last_input = pp->inputfifo[fifo_ndx];
if (labs(pp->input.fvel|pp->input.svel) && !labs(last_input.fvel|last_input.svel))
if (labs(pp->input.fvel|pp->input.svel) && !labs(pp->lastinput.fvel| pp->lastinput.svel))
PlaySOsound(pp->sop->mid_sector,SO_DRIVE_SOUND);
else if (!labs(pp->input.fvel|pp->input.svel) && labs(last_input.fvel|last_input.svel))
else if (!labs(pp->input.fvel|pp->input.svel) && labs(pp->lastinput.fvel| pp->lastinput.svel))
PlaySOsound(pp->sop->mid_sector,SO_IDLE_SOUND);
}
@ -7596,43 +7572,11 @@ domovethings(void)
extern int FinishTimer;
// grab values stored in the fifo and put them in the players vars
TRAVERSE_CONNECT(i)
{
pp = Player + i;
pp->input = pp->inputfifo[movefifoplc & (MOVEFIFOSIZ - 1)];
}
movefifoplc++;
#if SYNC_TEST
if (/* CTW REMOVED !gTenActivated ||*/ !(movefifoplc & 0x3f))
getsyncstat();
#ifdef DEBUG // in DEBUG mode even TEN does sync all the time
else
getsyncstat();
#endif
#endif
// count the number of times this loop is called and use
// for things like sync testing
totalsynctics += synctics;
updateinterpolations(); // Stick at beginning of domovethings
short_updateinterpolations(); // Stick at beginning of domovethings
so_updateinterpolations(); // Stick at beginning of domovethings
MoveSkipSavePos();
// check for pause of multi-play game
if (CommEnabled)
PauseMultiPlay();
TRAVERSE_CONNECT(pnum)
{
pp = Player + pnum;
DoPlayerMenuKeys(pp);
}
if (paused)
{
if (!ReloadPrompt)
@ -7727,13 +7671,11 @@ domovethings(void)
MultiPlayLimits();
//if (MoveSkip8 == 0) // 8=5x 4=10x, 2=20x, 0=40x per second
gi->UpdateSounds();
thinktime.Unclock();
#if 0
CorrectPrediction(movefifoplc - 1);
#endif
if (FinishTimer)
{
if ((FinishTimer -= synctics) <= 0)

View file

@ -49,7 +49,7 @@ typedef struct
short filler;
} PREDICT, *PREDICTp;
PREDICT Predict[MOVEFIFOSIZ];
PREDICT Predict[/*MOVEFIFOSIZ*/256];
int predictmovefifoplc;
void DoPlayerSectorUpdatePreMove(PLAYERp);
@ -70,6 +70,7 @@ InitPrediction(PLAYERp pp)
void
DoPrediction(PLAYERp ppp)
{
#if 0
USERp u;
SPRITE spr;
int bakrandomseed;
@ -118,11 +119,13 @@ DoPrediction(PLAYERp ppp)
Predict[predictmovefifoplc & (MOVEFIFOSIZ-1)].z = ppp->posz;
Predict[predictmovefifoplc & (MOVEFIFOSIZ-1)].q16horiz = ppp->q16horiz;
predictmovefifoplc++;
#endif
}
void
CorrectPrediction(int actualfifoplc)
{
#if 0
PREDICTp predict = &Predict[actualfifoplc & (MOVEFIFOSIZ-1)];
if (!PredictionOn)
@ -153,6 +156,7 @@ CorrectPrediction(int actualfifoplc)
{
DoPrediction(ppp);
}
#endif
}
END_SW_NS

View file

@ -470,11 +470,8 @@ bool GameInterface::SaveGame(FSaveGameNode *sv)
}
MWRITE(&loc,sizeof(loc),1,fil);
//MWRITE(&oloc,sizeof(oloc),1,fil);
//MWRITE(&fsync,sizeof(fsync),1,fil);
MWRITE(&screenpeek,sizeof(screenpeek),1,fil);
MWRITE(&totalsynctics,sizeof(totalsynctics),1,fil);
MWRITE(&randomseed, sizeof(randomseed), 1, fil);
// do all sector manipulation structures
@ -873,7 +870,7 @@ bool GameInterface::LoadGame(FSaveGameNode* sv)
MREAD(&loc,sizeof(loc),1,fil);
MREAD(&screenpeek,sizeof(screenpeek),1,fil);
MREAD(&totalsynctics,sizeof(totalsynctics),1,fil); // same as kens lockclock
MREAD(&randomseed, sizeof(randomseed), 1, fil);
// do all sector manipulation structures

View file

@ -2182,7 +2182,7 @@ MoveZ(SECTOR_OBJECTp sop)
if (sop->bob_amt)
{
sop->bob_sine_ndx = (totalsynctics << sop->bob_speed) & 2047;
sop->bob_sine_ndx = (PlayClock << sop->bob_speed) & 2047;
sop->bob_diff = ((sop->bob_amt * (int) sintable[sop->bob_sine_ndx]) >> 14);
// for all sectors
@ -2790,7 +2790,7 @@ OperateSectorObjectForTics(SECTOR_OBJECTp sop, short newang, int newx, int newy,
if (sop->bob_amt)
{
sop->bob_sine_ndx = (totalsynctics << sop->bob_speed) & 2047;
sop->bob_sine_ndx = (PlayClock << sop->bob_speed) & 2047;
sop->bob_diff = ((sop->bob_amt * (int) sintable[sop->bob_sine_ndx]) >> 14);
// for all sectors