- transitioned Exhumed to the new main loop.

Fixed #301
This commit is contained in:
Christoph Oelckers 2020-09-02 22:55:57 +02:00
parent b1a3080671
commit b49e050baf
13 changed files with 191 additions and 179 deletions

View file

@ -863,13 +863,8 @@ int RunGame()
enginePostInit(); // This must not be done earlier!
videoInit();
// Duke has transitioned to the new main loop, the other games haven't yet.
if (!(g_gameType & (GAMEFLAG_PSEXHUMED)))
{
D_CheckNetGame();
MainLoop();
}
else app_loop();
D_CheckNetGame();
MainLoop();
return 0; // this is never reached. app_loop only exits via exception.
}

View file

@ -223,11 +223,5 @@ enum AM_Mode
extern int automapMode;
extern bool automapFollow;
extern bool sendPause;
extern int gameclock;
extern uint64_t gameclockstart;
extern int lastTic;
inline void updateGameClock()
{
gameclock = static_cast<int>((I_GetTimeNS() - gameclockstart) * 120 / 1'000'000'000);
}

View file

@ -194,7 +194,6 @@ static void GameTicker()
case GS_LEVEL:
gameupdatetime.Reset();
gameupdatetime.Clock();
updateGameClock();
gi->Ticker();
gameupdatetime.Unclock();
break;
@ -249,7 +248,6 @@ void Display()
twod->Clear();
twod->SetSize(screen->GetWidth(), screen->GetHeight());
twodpsp.SetSize(screen->GetWidth(), screen->GetHeight());
updateGameClock();
gi->Render();
DrawFullscreenBlends();
}

View file

@ -30,18 +30,12 @@ BEGIN_PS_NS
void resettiming()
{
gameclock = 0;
lastTic = -1;
}
void doTileLoad(int i)
{
tileLoad(i);
#ifdef USE_OPENGL
if (r_precache) PrecacheHardwareTextures(i);
#endif
}
void precache()

View file

@ -373,6 +373,8 @@ double calc_smoothratio()
return I_GetTimeFrac() * MaxSmoothRatio;
}
void CheckProgression();
void GameMove(void)
{
FixPalette();
@ -444,10 +446,133 @@ static int SelectAltWeapon(int weap2)
return 0;
}
void GameInterface::Ticker()
{
if (!paused)
{
nPlayerDAng += localInput.q16avel;
inita &= kAngleMask;
for (int i = 0; i < 4; i++)
{
lPlayerXVel += localInput.fvel * Cos(inita) + localInput.svel * Sin(inita);
lPlayerYVel += localInput.fvel * Sin(inita) - localInput.svel * Cos(inita);
lPlayerXVel -= (lPlayerXVel >> 5) + (lPlayerXVel >> 6);
lPlayerYVel -= (lPlayerYVel >> 5) + (lPlayerYVel >> 6);
}
int weap2 = localInput.getNewWeapon();
if (weap2 == WeaponSel_Next)
{
weap2 = SelectNextWeapon(weap2);
}
else if (weap2 == WeaponSel_Prev)
{
weap2 = SelectPrevWeapon(weap2);
}
else if (weap2 == WeaponSel_Alt)
{
weap2 = SelectAltWeapon(weap2);
}
if (localInput.actions & SB_INVPREV)
{
int nItem = nPlayerItem[nLocalPlayer];
int i;
for (i = 6; i > 0; i--)
{
nItem--;
if (nItem < 0) nItem = 5;
if (PlayerList[nLocalPlayer].items[nItem] != 0)
break;
}
if (i > 0) SetPlayerItem(nLocalPlayer, nItem);
}
if (localInput.actions & SB_INVNEXT)
{
int nItem = nPlayerItem[nLocalPlayer];
int i;
for (i = 6; i > 0; i--)
{
nItem++;
if (nItem == 6) nItem = 0;
if (PlayerList[nLocalPlayer].items[nItem] != 0)
break;
}
if (i > 0) SetPlayerItem(nLocalPlayer, nItem);
}
if (localInput.actions & SB_INVUSE)
{
if (nPlayerItem[nLocalPlayer] != -1)
{
localInput.setItemUsed(nPlayerItem[nLocalPlayer]);
}
}
for (int i = 0; i < 6; i++)
{
if (localInput.isItemUsed(i))
{
localInput.clearItemUsed(i);
if (PlayerList[nLocalPlayer].items[i] > 0)
{
if (nItemMagic[i] <= PlayerList[nLocalPlayer].nMagic)
{
sPlayerInput[nLocalPlayer].nItem = i;
break;
}
}
}
}
if (localInput.actions & SB_CENTERVIEW)
{
bLockPan = false;
bPlayerPan = false;
//PlayerList[nLocalPlayer].q16horiz = IntToFixed(92);
nDestVertPan[nLocalPlayer] = IntToFixed(92);
}
if (localInput.actions & SB_TURNAROUND)
{
// todo
}
sPlayerInput[nLocalPlayer].xVel = lPlayerXVel;
sPlayerInput[nLocalPlayer].yVel = lPlayerYVel;
// make weapon selection persist until it gets used up.
sPlayerInput[nLocalPlayer].buttons = lLocalCodes;
int weap = sPlayerInput[nLocalPlayer].getNewWeapon();
sPlayerInput[nLocalPlayer].actions = localInput.actions;
if (weap2 <= 0 || weap2 > 7) sPlayerInput[nLocalPlayer].SetNewWeapon(weap);
sPlayerInput[nLocalPlayer].nTarget = besttarget;
Ra[nLocalPlayer].nTarget = besttarget;
lLocalCodes = 0;
nPlayerDAng = 0;
sPlayerInput[nLocalPlayer].horizon = PlayerList[nLocalPlayer].q16horiz;
leveltime++;
GameMove();
r_NoInterpolate = false;
}
else r_NoInterpolate = true;
CheckProgression(); // todo: Get rid of this.
}
void GameTicker()
{
int const currentTic = I_GetTime();
gameclock = I_GetBuildTime();
if (paused)
{
@ -461,122 +586,7 @@ void GameTicker()
while (!EndLevel && currentTic - lastTic >= 1)
{
lastTic = currentTic;
PlayerInterruptKeys(false);
nPlayerDAng += localInput.q16avel;
inita &= kAngleMask;
for (int i = 0; i < 4; i++)
{
lPlayerXVel += localInput.fvel * Cos(inita) + localInput.svel * Sin(inita);
lPlayerYVel += localInput.fvel * Sin(inita) - localInput.svel * Cos(inita);
lPlayerXVel -= (lPlayerXVel >> 5) + (lPlayerXVel >> 6);
lPlayerYVel -= (lPlayerYVel >> 5) + (lPlayerYVel >> 6);
}
int weap2 = localInput.getNewWeapon();
if (weap2 == WeaponSel_Next)
{
weap2 = SelectNextWeapon(weap2);
}
else if (weap2 == WeaponSel_Prev)
{
weap2 = SelectPrevWeapon(weap2);
}
else if (weap2 == WeaponSel_Alt)
{
weap2 = SelectAltWeapon(weap2);
}
if (localInput.actions & SB_INVPREV)
{
int nItem = nPlayerItem[nLocalPlayer];
int i;
for (i = 6; i > 0; i--)
{
nItem--;
if (nItem < 0) nItem = 5;
if (PlayerList[nLocalPlayer].items[nItem] != 0)
break;
}
if (i > 0) SetPlayerItem(nLocalPlayer, nItem);
}
if (localInput.actions & SB_INVNEXT)
{
int nItem = nPlayerItem[nLocalPlayer];
int i;
for (i = 6; i > 0; i--)
{
nItem++;
if (nItem == 6) nItem = 0;
if (PlayerList[nLocalPlayer].items[nItem] != 0)
break;
}
if (i > 0) SetPlayerItem(nLocalPlayer, nItem);
}
if (localInput.actions & SB_INVUSE)
{
if (nPlayerItem[nLocalPlayer] != -1)
{
localInput.setItemUsed(nPlayerItem[nLocalPlayer]);
}
}
for (int i = 0; i < 6; i++)
{
if (localInput.isItemUsed(i))
{
localInput.clearItemUsed(i);
if (PlayerList[nLocalPlayer].items[i] > 0)
{
if (nItemMagic[i] <= PlayerList[nLocalPlayer].nMagic)
{
sPlayerInput[nLocalPlayer].nItem = i;
break;
}
}
}
}
if (localInput.actions & SB_CENTERVIEW)
{
bLockPan = false;
bPlayerPan = false;
//PlayerList[nLocalPlayer].q16horiz = IntToFixed(92);
nDestVertPan[nLocalPlayer] = IntToFixed(92);
}
if (localInput.actions & SB_TURNAROUND)
{
// todo
}
sPlayerInput[nLocalPlayer].xVel = lPlayerXVel;
sPlayerInput[nLocalPlayer].yVel = lPlayerYVel;
// make weapon selection persist until it gets used up.
sPlayerInput[nLocalPlayer].buttons = lLocalCodes;
int weap = sPlayerInput[nLocalPlayer].getNewWeapon();
sPlayerInput[nLocalPlayer].actions = localInput.actions;
if (weap2 <= 0 || weap2 > 7) sPlayerInput[nLocalPlayer].SetNewWeapon(weap);
sPlayerInput[nLocalPlayer].nTarget = besttarget;
Ra[nLocalPlayer].nTarget = besttarget;
lLocalCodes = 0;
nPlayerDAng = 0;
sPlayerInput[nLocalPlayer].horizon = PlayerList[nLocalPlayer].q16horiz;
leveltime++;
GameMove();
gi->Ticker();
}
gameupdatetime.Unclock();

View file

@ -197,7 +197,7 @@ public:
void ComputeCinemaText();
void ReadyCinemaText(uint16_t nVal);
void DisplayText();
bool AdvanceCinemaText(int gameclock);
bool AdvanceCinemaText(int clock);
};
@ -250,6 +250,11 @@ struct GameInterface : ::GameInterface
void QuitToTitle() override;
void UpdateSounds() override;
void ErrorCleanup() override;
void Ticker() override;
void DrawBackground() override;
void Render() override;
void GetInput(InputPacket* packet) override;
void Startup() override;
::GameStats getStats() override;
};

View file

@ -50,6 +50,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_PS_NS
void CheckProgression();
short nBestLevel;
static int32_t nonsharedtimer;
@ -114,8 +116,9 @@ static void showmap(short nLevel, short nLevelNew, short nLevelBest, TArray<JobD
}
static void GameDisplay(void)
void GameInterface::Render()
{
CheckKeys2();
drawtime.Reset();
drawtime.Clock();
@ -142,8 +145,9 @@ static void GameDisplay(void)
//
//
//---------------------------------------------------------------------------
void CheckProgression();
void drawmenubackground()
void GameInterface::DrawBackground()
{
auto nLogoTile = EXHUMED ? kExhumedLogo : kPowerslaveLogo;
int dword_9AB5F = (I_GetBuildTime() / 16) & 3;
@ -157,7 +161,7 @@ void drawmenubackground()
// draw the fire urn/lamp thingies
DrawRel(kTile3512 + dword_9AB5F, 50, 150, 32);
DrawRel(kTile3512 + ((dword_9AB5F + 2) & 3), 270, 150, 32);
CheckProgression();
}
//---------------------------------------------------------------------------
@ -251,10 +255,31 @@ void GameLoop()
GameTicker();
PlayerInterruptKeys(true);
gi->UpdateSounds();
CheckKeys2();
}
void GameInterface::Startup()
{
resettiming();
GameAction = -1;
EndLevel = false;
if (userConfig.CommandMap.IsNotEmpty())
{
/*
auto map = FindMapByName(userConfig.CommandMap);
if (map) GameAction = map->levelNumber;
userConfig.CommandMap = "";
goto again;
*/
}
else
{
DoTitle([](bool) { startmainmenu(); });
}
}
void GameInterface::RunGameFrame()
{
again:
@ -263,31 +288,16 @@ void GameInterface::RunGameFrame()
{
default:
case GS_STARTUP:
resettiming();
GameAction = -1;
EndLevel = false;
if (userConfig.CommandMap.IsNotEmpty())
{
auto map = FindMapByName(userConfig.CommandMap);
if (map) GameAction = map->levelNumber;
userConfig.CommandMap = "";
goto again;
}
else
{
DoTitle([](bool) { startmainmenu(); });
}
break;
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
drawmenubackground();
gi->DrawBackground();
break;
case GS_LEVEL:
GameLoop();
GameDisplay();
gi->Render();
break;
case GS_INTERMISSION:

View file

@ -325,4 +325,10 @@ void PlayerInterruptKeys(bool after)
}
void GameInterface::GetInput(InputPacket* packet)
{
PlayerInterruptKeys(packet == nullptr);
if (packet) *packet = localInput;
}
END_PS_NS

View file

@ -434,7 +434,7 @@ static void G_DrawOverheadMap(int32_t cposx, int32_t cposy, int32_t czoom, int16
if (p == screenpeek || GTFLAGS(GAMETYPE_OTHERPLAYERSINMAP))
{
if (pSprite->xvel > 16 && pPlayer->on_ground)
i = APLAYERTOP+(((int32_t) gameclock>>4)&3);
i = APLAYERTOP+(((int32_t) leveltime>>4)&3);
else
i = APLAYERTOP;

View file

@ -1492,7 +1492,7 @@ void DimLights()
void DoFinale()
{
static int dword_96788 = 0;
static int dword_1542FC = 0;
static int nextstage = 0;
if (!lFinaleStart)
return;
@ -1529,20 +1529,20 @@ void DoFinale()
{
StopLocalSound();
PlayLocalSound(StaticSound[kSound76], 0);
dword_1542FC = gameclock + 120;
nextstage = leveltime + 120;
nFinaleStage++;
}
}
else if (nFinaleStage <= 2)
{
if (gameclock >= dword_1542FC)
if (leveltime >= nextstage)
{
PlayLocalSound(StaticSound[kSound77], 0);
nFinaleStage++;
dword_1542FC = gameclock + 360;
nextstage = leveltime + 360;
}
}
else if (nFinaleStage == 3 && gameclock >= dword_1542FC)
else if (nFinaleStage == 3 && leveltime >= nextstage)
{
EndLevel = true;
}
@ -1706,7 +1706,7 @@ void ExplodeEnergyBlock(int nSprite)
else
{
nFinaleSpr = nSprite;
lFinaleStart = gameclock;
lFinaleStart = leveltime;
if (!lFinaleStart) {
lFinaleStart = lFinaleStart + 1;

View file

@ -127,7 +127,7 @@ void InitSpiritHead()
sprite[nSpiritSprite].cstat &= 0x7FFF;
nHeadTimeStart = gameclock;
nHeadTimeStart = leveltime;
memset(Worktile, TRANSPARENT_INDEX, WorktileSize);
TileFiles.InvalidateTile(kTileRamsesWorkTile);
@ -152,8 +152,8 @@ void InitSpiritHead()
StartSwirlies();
sprintf(filename, "LEV%d.PUP", currentLevel->levelNumber);
lNextStateChange = gameclock;
lHeadStartClock = gameclock;
lNextStateChange = leveltime;
lHeadStartClock = leveltime;
auto headfd = fileSystem.OpenFileReader(filename);
if (!headfd.isOpen())
@ -219,7 +219,7 @@ int DoSpiritHead()
if (nHeadStage < 2 || nHeadStage != 5)
{
nPixelsToShow = (gameclock - nHeadTimeStart) * 15;
nPixelsToShow = (leveltime - nHeadTimeStart) * 15;
if (nPixelsToShow > nPixels) {
nPixelsToShow = nPixels;
@ -242,10 +242,10 @@ int DoSpiritHead()
if (!nHeadStage)
{
if ((gameclock - nHeadTimeStart) > 480)
if ((leveltime - nHeadTimeStart) > 480)
{
nHeadStage = 1;
nHeadTimeStart = gameclock + 480;
nHeadTimeStart = leveltime + 480;
}
for (int i = 0; i < nPixelsToShow; i++)
@ -426,7 +426,7 @@ int DoSpiritHead()
Worktile[kSpiritX + ecx] = pixelval[i];
}
if ((gameclock - lHeadStartClock) > 600)
if ((leveltime - lHeadStartClock) > 600)
{
CopyHeadToWorkTile(kTileRamsesGold);
}
@ -467,7 +467,7 @@ int DoSpiritHead()
}
else
{
if (lNextStateChange <= gameclock)
if (lNextStateChange <= leveltime)
{
if (nPupData)
{

View file

@ -450,7 +450,7 @@ void EXSoundEngine::CalcPosVel(int type, const void* source, const float pt[3],
else if (type == SOURCE_Swirly)
{
int which = *(int*)source;
float phase = (gameclock << (4 + which)) * (M_PI / 1024);
float phase = (leveltime << (4 + which)) * (M_PI / 1024);
pos->X = fcampos.X + 256 * cos(phase);
pos->Z = fcampos.Z + 256 * sin(phase);
}

View file

@ -631,7 +631,7 @@ private:
int shade;
if (gameclock / kTimerTicks & 1) {
if (leveltime / kTimerTicks & 1) {
shade = -100;
}
else {
@ -649,14 +649,14 @@ private:
if (word_9AD54[i] == nScore)
{
int v9 = dword_9AD64[i];
if (v9 && v9 <= gameclock) {
if (v9 && v9 <= leveltime) {
dword_9AD64[i] = 0;
}
}
else
{
word_9AD54[i] = nScore;
dword_9AD64[i] = gameclock + 30;
dword_9AD64[i] = leveltime + 30;
}
DrawGraphic(tileGetTexture(nTile), x, 7, DI_ITEM_CENTER, 1, -1, -1, 1, 1);