raze/source/games/duke/src/gameloop.cpp

431 lines
8.5 KiB
C++
Raw Normal View History

//-------------------------------------------------------------------------
/*
Copyright (C) 1996, 2003 - 3D Realms Entertainment
Copyright (C) 2020 - Christoph Oelckers
This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
Duke Nukem 3D is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
aint with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Original Source: 1996 - Todd Replogle
Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
*/
//-------------------------------------------------------------------------
#include "ns.h" // Must come before everything else!
#include "gamestate.h"
#include "duke3d.h"
2020-07-06 01:00:52 +00:00
#include "sbar.h"
#include "m_argv.h"
#include "mapinfo.h"
#include "texturemanager.h"
#include "glbackend/glbackend.h"
BEGIN_DUKE_NS
//---------------------------------------------------------------------------
//
// abstract the queue's implementation
// All access to the input queues should go through this function interface.
//
//---------------------------------------------------------------------------
static InputPacket inputfifo[MOVEFIFOSIZ][MAXPLAYERS];
static int movefifoend[MAXPLAYERS];
static int movefifoplc;
static int bufferjitter;
void clearfifo(void)
{
memset(&inputfifo, 0, sizeof(inputfifo));
memset(sync, 0, sizeof(sync));
}
static inline void GetNextInput()
{
for (int i = connecthead; i >= 0; i = connectpoint2[i])
memcpy(&sync[i], &inputfifo[movefifoplc & (MOVEFIFOSIZ - 1)][i], sizeof(InputPacket));
movefifoplc++;
}
2020-07-18 09:56:49 +00:00
static void advancequeue(int myconnectindex)
{
movefifoend[myconnectindex]++;
}
static InputPacket& nextinput(int myconnectindex)
{
return inputfifo[movefifoend[myconnectindex] & (MOVEFIFOSIZ - 1)][myconnectindex];
}
bool shouldprocessinput(int myconnectindex)
{
if (movefifoend[myconnectindex] - movefifoplc > bufferjitter)
{
int i;
for (i = connecthead; i >= 0; i = connectpoint2[i])
if (movefifoplc == movefifoend[i]) return false;
if (i >= 0) return false;
return true;
}
return false;
}
static void fakedomovethings()
{
// prediction
}
static void fakedomovethingscorrect()
{
// unprediction
}
void prediction()
{
#if 0
// We currently have no net code driving this.
if (numplayers > 1)
while (fakemovefifoplc < movefifoend[myconnectindex]) fakedomovethings();
getpackets();
#endif
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-07-06 01:00:52 +00:00
/*
void mploadsave()
{
2020-07-06 01:00:52 +00:00
for(int i=connecthead;i>=0;i=connectpoint2[i])
if( sync[i].bits&(1<<17) )
{
multiflag = 2;
multiwhat = (sync[i].bits>>18)&1;
multipos = (unsigned) (sync[i].bits>>19)&15;
multiwho = i;
if( multiwhat )
{
saveplayer( multipos );
multiflag = 0;
if(multiwho != myconnectindex)
{
strcpy(&fta_quotes[122],&ud.user_name[multiwho][0]);
strcat(&fta_quotes[122]," SAVED A MULTIPLAYER GAME");
FTA(122,&ps[myconnectindex]);
}
else
{
strcpy(&fta_quotes[122],"MULTIPLAYER GAME SAVED");
FTA(122,&ps[myconnectindex]);
}
break;
}
else
{
// waitforeverybody();
j = loadplayer( multipos );
multiflag = 0;
2020-07-06 11:26:26 +00:00
if(j == 0 && !isRR())
2020-07-06 01:00:52 +00:00
{
if(multiwho != myconnectindex)
{
strcpy(&fta_quotes[122],&ud.user_name[multiwho][0]);
strcat(&fta_quotes[122]," LOADED A MULTIPLAYER GAME");
FTA(122,&ps[myconnectindex]);
}
else
{
strcpy(&fta_quotes[122],"MULTIPLAYER GAME LOADED");
FTA(122,&ps[myconnectindex]);
}
return 1;
}
}
}
}
2020-07-06 01:00:52 +00:00
*/
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int domovethings()
{
int i;
// mplpadsave();
2020-07-06 01:00:52 +00:00
ud.camerasprite = -1;
if (earthquaketime > 0) earthquaketime--;
if (rtsplaying > 0) rtsplaying--;
if (show_shareware > 0)
{
show_shareware--;
}
everyothertime++;
GetNextInput();
updateinterpolations();
#if 0
2020-07-06 01:00:52 +00:00
j = -1;
for (i = connecthead; i >= 0; i = connectpoint2[i])
{
2020-07-06 11:26:26 +00:00
if (PlayerInput(i, SKB_GAMEQUIT))
2020-07-06 01:00:52 +00:00
{
if (i == myconnectindex) gameexitfrommenu();
if (screenpeek == i)
{
screenpeek = connectpoint2[i];
if (screenpeek < 0) screenpeek = connecthead;
}
if (i == connecthead) connecthead = connectpoint2[connecthead];
else connectpoint2[j] = connectpoint2[i];
numplayers--;
ud.multimode--;
//closedemowrite();
if (numplayers < 2 && !isRR())
S_PlaySound(GENERIC_AMBIENCE17, CHAN_AUTO, CHANF_UI);
2020-07-15 16:10:31 +00:00
Printf(PRINT_NOTIFY, "%s is history!", ud.user_name[i]);
2020-07-06 01:00:52 +00:00
quickkill(&ps[i]);
deletesprite(ps[i].i);
}
else j = i;
}
#endif
2020-07-06 01:00:52 +00:00
//if(ud.recstat == 1) record();
if (playrunning())
2020-07-06 01:00:52 +00:00
{
global_random = krand();
movedummyplayers();//ST 13
}
for (i = connecthead; i >= 0; i = connectpoint2[i])
{
if (playrunning())
2020-07-06 01:00:52 +00:00
{
auto p = &ps[i];
2020-07-06 19:57:38 +00:00
if (p->pals.a > 0)
p->pals.a--;
2020-07-06 01:00:52 +00:00
hud_input(i);
2020-07-06 01:00:52 +00:00
fi.processinput(i);
fi.checksectors(i);
}
}
if (playrunning())
2020-07-06 01:00:52 +00:00
{
if (levelTextTime > 0)
levelTextTime--;
fi.think();
2020-07-06 01:00:52 +00:00
}
2020-07-06 01:00:52 +00:00
fakedomovethingscorrect();
2020-07-06 01:00:52 +00:00
if ((everyothertime & 1) == 0)
{
fi.animatewalls();
movecyclers();
}
2020-07-06 01:00:52 +00:00
if (isRR() && ud.recstat == 0 && ud.multimode < 2)
dotorch();
2020-07-06 01:00:52 +00:00
return 0;
}
2020-07-06 01:00:52 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void GameTicker()
2020-07-18 09:56:49 +00:00
{
if (ps[myconnectindex].gm == MODE_DEMO)
{
M_ClearMenus();
gamestate = GS_STARTUP;
return;
2020-07-18 09:56:49 +00:00
}
//Net_GetPackets();
2020-07-18 09:56:49 +00:00
gameupdatetime.Reset();
gameupdatetime.Clock();
int const currentTic = I_GetTime();
gameclock = I_GetBuildTime() - gameclockstart;
while (playrunning() && currentTic - lastTic >= 1)
2020-07-18 09:56:49 +00:00
{
lastTic = currentTic;
2020-07-18 09:56:49 +00:00
auto& input = nextinput(myconnectindex);
gi->GetInput(&input);
2020-07-18 09:56:49 +00:00
advancequeue(myconnectindex);
if (playrunning())
2020-07-18 09:56:49 +00:00
{
prediction();
if (numplayers < 2) bufferjitter = 0;
while (shouldprocessinput(myconnectindex))
{
if (domovethings()) break;
}
2020-07-18 09:56:49 +00:00
}
}
2020-07-18 09:56:49 +00:00
gameupdatetime.Unclock();
if (ps[myconnectindex].gm & (MODE_EOL | MODE_RESTART))
{
exitlevel();
2020-07-18 09:56:49 +00:00
}
if (!cl_syncinput)
{
gi->GetInput(nullptr);
}
2020-07-18 09:56:49 +00:00
nonsharedkeys();
gi->UpdateSounds();
2020-07-18 09:56:49 +00:00
drawtime.Reset();
drawtime.Clock();
videoSetBrightness(thunder_brightness);
double const smoothRatio = playrunning() ? I_GetTimeFrac() * MaxSmoothRatio : MaxSmoothRatio;
2020-07-18 09:56:49 +00:00
displayrooms(screenpeek, smoothRatio);
drawoverlays(smoothRatio);
2020-07-18 09:56:49 +00:00
drawtime.Unclock();
if (ps[myconnectindex].gm == MODE_DEMO)
{
gamestate = GS_STARTUP;
}
2020-07-18 09:56:49 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void startmainmenu()
{
gamestate = GS_MENUSCREEN;
M_StartControlPanel(false);
M_SetMenu(NAME_Mainmenu);
FX_StopAllSounds();
}
void resetGameClock()
{
I_SetFrameTime();
gameclockstart = I_GetBuildTime();
gameclock = 0;
cloudclock = 0;
}
static void Startup()
2020-07-18 09:56:49 +00:00
{
resetGameClock();
ps[myconnectindex].ftq = 0;
if (userConfig.CommandMap.IsNotEmpty())
{
auto maprecord = FindMapByName(userConfig.CommandMap);
userConfig.CommandMap = "";
if (maprecord)
{
ud.m_respawn_monsters = ud.m_player_skill == 4;
2020-07-18 09:56:49 +00:00
for (int i = 0; i != -1; i = connectpoint2[i])
2020-07-18 09:56:49 +00:00
{
resetweapons(i);
resetinventory(i);
2020-07-18 09:56:49 +00:00
}
startnewgame(maprecord, /*userConfig.skill*/2);
}
}
else
{
fi.ShowLogo([](bool) { startmainmenu(); });
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void GameInterface::RunGameFrame()
{
switch (gamestate)
{
default:
case GS_STARTUP:
Startup();
break;
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
drawbackground();
break;
case GS_LEVEL:
GameTicker();
break;
case GS_INTERMISSION:
case GS_INTRO:
RunScreenJobFrame();
break;
2020-07-18 09:56:49 +00:00
}
}
END_DUKE_NS