mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-16 17:32:13 +00:00
694 lines
19 KiB
C++
694 lines
19 KiB
C++
//-------------------------------------------------------------------------
|
|
/*
|
|
Copyright (C) 1996, 2003 - 3D Realms Entertainment
|
|
Copyright (C) 2017-2019 Nuke.YKT
|
|
|
|
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
|
|
along 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
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
|
|
// this file collects all 2D content of the game that was scattered across multiple sources originally.
|
|
// All this should transition to a more modern, preferably localization friendly, approach later.
|
|
|
|
#include "ns.h"
|
|
#include "duke3d.h"
|
|
#include "names_r.h"
|
|
#include "animtexture.h"
|
|
#include "animlib.h"
|
|
#include "raze_music.h"
|
|
#include "mapinfo.h"
|
|
#include "screenjob.h"
|
|
#include "texturemanager.h"
|
|
#include "c_dispatch.h"
|
|
#include "gamestate.h"
|
|
|
|
BEGIN_DUKE_NS
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
// Sets up the game fonts.
|
|
// This is a duplicate of the _d function but needed since the tile numbers differ.
|
|
//
|
|
//==========================================================================
|
|
|
|
void InitFonts_r()
|
|
{
|
|
GlyphSet fontdata;
|
|
|
|
// Small font
|
|
for (int i = 0; i < 95; i++)
|
|
{
|
|
auto tile = tileGetTexture(STARTALPHANUM + i);
|
|
if (tile && tile->isValid() && tile->GetTexelWidth() > 0 && tile->GetTexelHeight() > 0)
|
|
{
|
|
fontdata.Insert('!' + i, tile);
|
|
tile->SetOffsetsNotForFont();
|
|
}
|
|
}
|
|
SmallFont = new ::FFont("SmallFont", nullptr, "defsmallfont", 0, 0, 0, -1, 10, false, false, false, &fontdata);
|
|
SmallFont->SetKerning(2);
|
|
fontdata.Clear();
|
|
|
|
// Big font
|
|
|
|
// This font is VERY messy...
|
|
fontdata.Insert('_', tileGetTexture(BIGALPHANUM - 11));
|
|
fontdata.Insert('-', tileGetTexture(BIGALPHANUM - 11));
|
|
for (int i = 0; i < 10; i++) fontdata.Insert('0' + i, tileGetTexture(BIGALPHANUM - 10 + i));
|
|
for (int i = 0; i < 26; i++) fontdata.Insert('A' + i, tileGetTexture(BIGALPHANUM + i));
|
|
fontdata.Insert('.', tileGetTexture(BIGPERIOD));
|
|
fontdata.Insert(',', tileGetTexture(BIGCOMMA));
|
|
fontdata.Insert('!', tileGetTexture(BIGX));
|
|
fontdata.Insert('?', tileGetTexture(BIGQ));
|
|
fontdata.Insert(';', tileGetTexture(BIGSEMI));
|
|
fontdata.Insert(':', tileGetTexture(BIGCOLIN));
|
|
fontdata.Insert('\\', tileGetTexture(BIGALPHANUM + 68));
|
|
fontdata.Insert('/', tileGetTexture(BIGALPHANUM + 68));
|
|
fontdata.Insert('%', tileGetTexture(BIGALPHANUM + 69));
|
|
fontdata.Insert('`', tileGetTexture(BIGAPPOS));
|
|
fontdata.Insert('"', tileGetTexture(BIGAPPOS));
|
|
fontdata.Insert('\'', tileGetTexture(BIGAPPOS));
|
|
GlyphSet::Iterator it(fontdata);
|
|
GlyphSet::Pair* pair;
|
|
while (it.NextPair(pair)) pair->Value->SetOffsetsNotForFont();
|
|
BigFont = new ::FFont("BigFont", nullptr, "defbigfont", 0, 0, 0, -1, 10, false, false, false, &fontdata);
|
|
BigFont->SetKerning(6);
|
|
fontdata.Clear();
|
|
|
|
// Tiny font
|
|
for (int i = 0; i < 95; i++)
|
|
{
|
|
auto tile = tileGetTexture(MINIFONT + i);
|
|
if (tile && tile->isValid() && tile->GetTexelWidth() > 0 && tile->GetTexelHeight() > 0)
|
|
fontdata.Insert('!' + i, tile);
|
|
}
|
|
fontdata.Insert(1, TexMan.FindGameTexture("TINYBLAK")); // this is only here to widen the color range of the font to produce a better translation.
|
|
SmallFont2 = new ::FFont("SmallFont2", nullptr, "defsmallfont2", 0, 0, 0, -1, 6, false, false, false, &fontdata);
|
|
SmallFont2->SetKerning(2);
|
|
fontdata.Clear();
|
|
|
|
// SBAR index font
|
|
for (int i = 0; i < 10; i++) fontdata.Insert('0' + i, tileGetTexture(THREEBYFIVE + i));
|
|
fontdata.Insert(':', tileGetTexture(THREEBYFIVE + 10));
|
|
fontdata.Insert('/', tileGetTexture(THREEBYFIVE + 11));
|
|
fontdata.Insert('%', tileGetTexture(MINIFONT + '%' - '!'));
|
|
fontdata.Insert(1, TexMan.FindGameTexture("TINYBLAK")); // this is only here to widen the color range of the font to produce a better translation.
|
|
IndexFont = new ::FFont("IndexFont", nullptr, nullptr, 0, 0, 0, -1, -1, false, false, false, &fontdata);
|
|
|
|
fontdata.Clear();
|
|
|
|
// digital font
|
|
for (int i = 0; i < 10; i++) fontdata.Insert('0' + i, tileGetTexture(DIGITALNUM + i));
|
|
fontdata.Insert(1, TexMan.FindGameTexture("TINYBLAK")); // this is only here to widen the color range of the font to produce a better translation.
|
|
DigiFont = new ::FFont("DigiFont", nullptr, nullptr, 0, 0, 0, -1, -1, false, false, false, &fontdata);
|
|
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// wrappers around DrawText to allow easier reuse of the old code.
|
|
// The vertical displacements are to have the same positioning as with the original code.
|
|
//
|
|
//==========================================================================
|
|
|
|
static void BigText(double x, double y, const char* text, int align, double alpha = 1.)
|
|
{
|
|
//x *= 2.2; y *= 2.64;
|
|
if (align != -1)
|
|
x -= BigFont->StringWidth(text) * (align == 0 ? 0.2 : 0.4);
|
|
auto width = BigFont->StringWidth(text);
|
|
DrawText(twod, BigFont, CR_UNTRANSLATED, x, y - 12, text, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_ScaleX, 0.4, DTA_ScaleY, 0.4, DTA_Alpha, alpha, TAG_DONE);
|
|
}
|
|
|
|
static void GameText(double x, double y, const char* t, int shade, int align = -1, int trans = 0)
|
|
{
|
|
x *= 2; y *= 2;
|
|
if (align != -1)
|
|
x -= SmallFont->StringWidth(t) * (align == 0 ? 0.5 : 1);
|
|
int light = Scale(numshades - shade, 255, numshades);
|
|
PalEntry pe(255, light, light, light);
|
|
DrawText(twod, SmallFont, CR_UNDEFINED, x, y + 2, t, DTA_FullscreenScale, 3, DTA_VirtualWidth, 640, DTA_VirtualHeight, 400, DTA_TranslationIndex, TRANSLATION(Translation_Remap, trans), DTA_Color, pe, TAG_DONE);
|
|
}
|
|
|
|
static void MiniText(double x, double y, const char* t, int shade, int align = -1, int trans = 0)
|
|
{
|
|
x *= 2; y *= 2;
|
|
if (align != -1)
|
|
x -= SmallFont2->StringWidth(t) * (align == 0 ? 0.5 : 1);
|
|
int light = Scale(numshades - shade, 255, numshades);
|
|
PalEntry pe(255, light, light, light);
|
|
DrawText(twod, SmallFont2, CR_UNDEFINED, x, y, t, DTA_FullscreenScale, 3, DTA_VirtualWidth, 640, DTA_VirtualHeight, 400, DTA_TranslationIndex, TRANSLATION(Translation_Remap, trans), DTA_Color, pe, TAG_DONE);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void Logo_r(const CompletionFunc& completion)
|
|
{
|
|
Mus_Stop();
|
|
FX_StopAllSounds(); // JBF 20031228
|
|
|
|
static const AnimSound introsound[] =
|
|
{
|
|
{ 1, 29+1 },
|
|
{ -1, -1 }
|
|
};
|
|
|
|
static const AnimSound rednecksound[] =
|
|
{
|
|
{ 1, 478+1 },
|
|
{ -1, -1 }
|
|
};
|
|
|
|
static const AnimSound xatrixsound[] =
|
|
{
|
|
{ 1, 479+1 },
|
|
{ -1, -1 }
|
|
};
|
|
|
|
static const int framespeed[] = { 9, 9, 9 }; // same for all 3 anims
|
|
|
|
JobDesc jobs[3];
|
|
int job = 0;
|
|
|
|
if (!isRRRA())
|
|
{
|
|
jobs[job++] = { PlayVideo("rr_intro.anm", introsound, framespeed), nullptr };
|
|
jobs[job++] = { PlayVideo("redneck.anm", rednecksound, framespeed), nullptr };
|
|
jobs[job++] = { PlayVideo("xatlogo.anm", xatrixsound, framespeed), nullptr };
|
|
}
|
|
else
|
|
{
|
|
jobs[job++] = { PlayVideo("redint.mve"), nullptr };
|
|
}
|
|
RunScreenJob(jobs, job, completion, true, true);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
static void bonussequence_r(int num, JobDesc* jobs, int& job)
|
|
{
|
|
static const AnimSound turdmov[] =
|
|
{
|
|
{ 1, 82 + 1 },
|
|
{ -1, -1 }
|
|
};
|
|
|
|
static const AnimSound rr_outro[] =
|
|
{
|
|
{ 1, 35 + 1 },
|
|
{ -1, -1 }
|
|
};
|
|
|
|
static const int framespeed[] = { 9, 9, 9 }; // same for all 3 anims
|
|
|
|
Mus_Stop();
|
|
FX_StopAllSounds();
|
|
|
|
switch (num)
|
|
{
|
|
case 0:
|
|
jobs[job++] = { PlayVideo("turdmov.anm", turdmov, framespeed), nullptr };
|
|
jobs[job++] = { Create<DImageScreen>(TENSCREEN), nullptr };
|
|
break;
|
|
|
|
case 1:
|
|
jobs[job++] = { PlayVideo("rr_outro.anm", rr_outro, framespeed), nullptr };
|
|
jobs[job++] = { Create<DImageScreen>(TENSCREEN), nullptr };
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
class DRRMultiplayerBonusScreen : public DScreenJob
|
|
{
|
|
int playerswhenstarted;
|
|
|
|
public:
|
|
DRRMultiplayerBonusScreen(int pws) : DScreenJob(fadein | fadeout)
|
|
{
|
|
playerswhenstarted = pws;
|
|
S_PlayBonusMusic();
|
|
}
|
|
|
|
int Frame(uint64_t clock, bool skiprequest)
|
|
{
|
|
char tempbuf[32];
|
|
twod->ClearScreen();
|
|
DrawTexture(twod, tileGetTexture(MENUSCREEN), 0, 0, DTA_FullscreenEx, 3, DTA_Color, 0xff808080, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
|
|
double scale = 0.36;
|
|
DrawTexture(twod, tileGetTexture(INGAMEDUKETHREEDEE, true), 160, 34, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200,
|
|
DTA_CenterOffsetRel, true, DTA_ScaleX, scale, DTA_ScaleY, 0.36, TAG_DONE);
|
|
|
|
GameText(160, 58, GStrings("Multiplayer Totals"), 0, 0);
|
|
GameText(160, 58 + 10, currentLevel->DisplayName(), 0, 0);
|
|
GameText(160, 165, GStrings("Presskey"), 0, 0);
|
|
|
|
int t = 0;
|
|
|
|
MiniText(38, 80, GStrings("Name"), 0);
|
|
MiniText(269 + 20, 80, GStrings("Kills"), 0, 1);
|
|
|
|
for (int i = 0; i < playerswhenstarted; i++)
|
|
{
|
|
mysnprintf(tempbuf, 32, "%-4d", i + 1);
|
|
MiniText(92 + (i * 23), 80, tempbuf, 0);
|
|
}
|
|
|
|
for (int i = 0; i < playerswhenstarted; i++)
|
|
{
|
|
int xfragtotal = 0;
|
|
mysnprintf(tempbuf, 32, "%d", i + 1);
|
|
|
|
MiniText(30, 90 + t, tempbuf, 0);
|
|
MiniText(38, 90 + t, ud.user_name[i], 0, -1, ps[i].palookup);
|
|
|
|
for (int y = 0; y < playerswhenstarted; y++)
|
|
{
|
|
int frag = frags[i][y];
|
|
if (i == y)
|
|
{
|
|
mysnprintf(tempbuf, 32, "%-4d", ps[y].fraggedself);
|
|
MiniText(92 + (y * 23), 90 + t, tempbuf, 0);
|
|
xfragtotal -= ps[y].fraggedself;
|
|
}
|
|
else
|
|
{
|
|
mysnprintf(tempbuf, 32, "%-4d", frag);
|
|
MiniText(92 + (y * 23), 90 + t, tempbuf, 0);
|
|
xfragtotal += frag;
|
|
}
|
|
/*
|
|
if (myconnectindex == connecthead)
|
|
{
|
|
mysnprintf(tempbuf, 32, "stats %ld killed %ld %ld\n", i + 1, y + 1, frag);
|
|
sendscore(tempbuf);
|
|
}
|
|
*/
|
|
}
|
|
|
|
mysnprintf(tempbuf, 32, "%-4d", xfragtotal);
|
|
MiniText(101 + (8 * 23), 90 + t, tempbuf, 0);
|
|
|
|
t += 7;
|
|
}
|
|
|
|
for (int y = 0; y < playerswhenstarted; y++)
|
|
{
|
|
int yfragtotal = 0;
|
|
for (int i = 0; i < playerswhenstarted; i++)
|
|
{
|
|
if (i == y)
|
|
yfragtotal += ps[i].fraggedself;
|
|
int frag = frags[i][y];
|
|
yfragtotal += frag;
|
|
}
|
|
mysnprintf(tempbuf, 32, "%-4d", yfragtotal);
|
|
MiniText(92 + (y * 23), 96 + (8 * 7), tempbuf, 0);
|
|
}
|
|
|
|
MiniText(45, 96 + (8 * 7), GStrings("Deaths"), 0);
|
|
return skiprequest ? -1 : 1;
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
class DRRLevelSummaryScreen : public DScreenJob
|
|
{
|
|
const char* lastmapname;
|
|
int gfx_offset;
|
|
int bonuscnt = 0;
|
|
|
|
void SetTotalClock(int tc)
|
|
{
|
|
SetClock(tc * (uint64_t)1'000'000'000 / 120);
|
|
}
|
|
|
|
public:
|
|
DRRLevelSummaryScreen(bool dofadeout = true) : DScreenJob(dofadeout? (fadein | fadeout) : fadein)
|
|
{
|
|
S_PlayBonusMusic();
|
|
if (currentLevel->flags & MI_USERMAP)
|
|
gfx_offset = RRTILE403;
|
|
else if (!isRRRA())
|
|
gfx_offset = RRTILE403 + clamp((currentLevel->levelNumber / 100) * 7 + (currentLevel->levelNumber % 100), 0, 13);
|
|
else
|
|
gfx_offset = LEVELMAP + clamp((currentLevel->levelNumber / 100) * 7 + (currentLevel->levelNumber % 100), 0, 13);
|
|
|
|
|
|
lastmapname = currentLevel->DisplayName();
|
|
}
|
|
|
|
void FormatTime(int time, char* tempbuf)
|
|
{
|
|
mysnprintf(tempbuf, 32, "%02d:%02d", (time / (26 * 60)) % 60, (time / 26) % 60);
|
|
}
|
|
|
|
void PrintTime(int totalclock)
|
|
{
|
|
char tempbuf[32];
|
|
BigText(30, 48, GStrings("TXT_YerTime"), -1);
|
|
BigText(30, 64, GStrings("TXT_ParTime"), -1);
|
|
BigText(30, 80, GStrings("TXT_XTRTIME"), -1);
|
|
|
|
if (bonuscnt == 0)
|
|
bonuscnt++;
|
|
|
|
if (totalclock > (60 * 4))
|
|
{
|
|
if (bonuscnt == 1)
|
|
{
|
|
bonuscnt++;
|
|
S_PlaySound(404, CHAN_AUTO, CHANF_UI);
|
|
}
|
|
FormatTime(ps[myconnectindex].player_par, tempbuf);
|
|
BigText(191, 48, tempbuf, -1);
|
|
|
|
FormatTime(currentLevel->parTime, tempbuf);
|
|
BigText(191, 64, tempbuf, -1);
|
|
|
|
if (!isNamWW2GI())
|
|
{
|
|
FormatTime(currentLevel->designerTime, tempbuf);
|
|
BigText(191, 80, tempbuf, -1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintKills(int totalclock)
|
|
{
|
|
char tempbuf[32];
|
|
BigText(30, 112, GStrings("TXT_VarmintsKilled"), -1);
|
|
BigText(30, 128, GStrings("TXT_VarmintsLeft"), -1);
|
|
|
|
if (bonuscnt == 2)
|
|
bonuscnt++;
|
|
|
|
if (totalclock > (60 * 7))
|
|
{
|
|
if (bonuscnt == 3)
|
|
{
|
|
bonuscnt++;
|
|
S_PlaySound(442, CHAN_AUTO, CHANF_UI);
|
|
}
|
|
mysnprintf(tempbuf, 32, "%-3d", ps[myconnectindex].actors_killed);
|
|
BigText(231, 112, tempbuf, -1);
|
|
if (ud.player_skill > 3)
|
|
{
|
|
mysnprintf(tempbuf, 32, "%s", GStrings("TXT_N_A"));
|
|
BigText(231, 128, tempbuf, -1);
|
|
}
|
|
else
|
|
{
|
|
if ((ps[myconnectindex].max_actors_killed - ps[myconnectindex].actors_killed) < 0)
|
|
mysnprintf(tempbuf, 32, "%-3d", 0);
|
|
else mysnprintf(tempbuf, 32, "%-3d", ps[myconnectindex].max_actors_killed - ps[myconnectindex].actors_killed);
|
|
BigText(231, 128, tempbuf, -1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintSecrets(int totalclock)
|
|
{
|
|
char tempbuf[32];
|
|
BigText(30, 144, GStrings("TXT_SECFND"), -1);
|
|
BigText(30, 160, GStrings("TXT_SECMISS"), -1);
|
|
if (bonuscnt == 4) bonuscnt++;
|
|
|
|
if (totalclock > (60 * 10))
|
|
{
|
|
if (bonuscnt == 5)
|
|
{
|
|
bonuscnt++;
|
|
S_PlaySound(404, CHAN_AUTO, CHANF_UI);
|
|
}
|
|
mysnprintf(tempbuf, 32, "%-3d", ps[myconnectindex].secret_rooms);
|
|
BigText(231, 144, tempbuf, -1);
|
|
if (ps[myconnectindex].secret_rooms > 0)
|
|
sprintf(tempbuf, "%-3d", (100 * ps[myconnectindex].secret_rooms / ps[myconnectindex].max_secret_rooms));
|
|
mysnprintf(tempbuf, 32, "%-3d", ps[myconnectindex].max_secret_rooms - ps[myconnectindex].secret_rooms);
|
|
BigText(231, 160, tempbuf, -1);
|
|
}
|
|
}
|
|
|
|
int Frame(uint64_t clock, bool skiprequest)
|
|
{
|
|
twod->ClearScreen();
|
|
int totalclock = int(clock * 120 / 1'000'000'000);
|
|
DrawTexture(twod, tileGetTexture(gfx_offset, true), 0, 0, DTA_FullscreenEx, 3, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
|
|
|
|
if (lastmapname) BigText(80, 16, lastmapname, -1);
|
|
BigText(15, 192, GStrings("PRESSKEY"), -1);
|
|
|
|
if (totalclock > (60 * 3))
|
|
{
|
|
PrintTime(totalclock);
|
|
}
|
|
if (totalclock > (60 * 6))
|
|
{
|
|
PrintKills(totalclock);
|
|
}
|
|
if (totalclock > (60 * 9))
|
|
{
|
|
PrintSecrets(totalclock);
|
|
}
|
|
|
|
if (totalclock > (1000000000L) && totalclock < (1000000320L))
|
|
{
|
|
int val = (totalclock >> 4) % 15;
|
|
if (val == 0)
|
|
{
|
|
if (bonuscnt == 6)
|
|
{
|
|
bonuscnt++;
|
|
S_PlaySound(425, CHAN_AUTO, CHANF_UI);
|
|
S_PlaySound(BONUS_SPEECH1 + (rand() & 3), CHAN_AUTO, CHANF_UI);
|
|
}
|
|
}
|
|
}
|
|
else if (totalclock > (10240 + 120L)) return 0;
|
|
|
|
if (totalclock > 10240 && totalclock < 10240 + 10240)
|
|
SetTotalClock(1024);
|
|
|
|
if (skiprequest && totalclock > (60 * 2))
|
|
{
|
|
skiprequest = false;
|
|
if (totalclock < (60 * 13))
|
|
{
|
|
SetTotalClock(60 * 13);
|
|
}
|
|
else if (totalclock < (1000000000))
|
|
SetTotalClock(1000000000);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
class DRRRAEndOfGame : public DScreenJob
|
|
{
|
|
public:
|
|
DRRRAEndOfGame() : DScreenJob(fadein|fadeout)
|
|
{
|
|
S_PlaySound(35, CHAN_AUTO, CHANF_UI);
|
|
}
|
|
int Frame(uint64_t clock, bool skiprequest)
|
|
{
|
|
int totalclock = int(clock * 120 / 1'000'000'000);
|
|
auto tex = tileGetTexture(RRTILE8677 + ((totalclock >> 4) & 1));
|
|
DrawTexture(twod, tex, 0, 0, DTA_FullscreenEx, 3, TAG_DONE);
|
|
if (!S_CheckSoundPlaying(-1, 35) && totalclock > 15*120) return 0; // make sure it stays, even if sound is off.
|
|
if (skiprequest)
|
|
{
|
|
S_StopSound(35);
|
|
return -1;
|
|
}
|
|
return 1;
|
|
}
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void dobonus_r(bool bonusonly, const CompletionFunc& completion)
|
|
{
|
|
JobDesc jobs[20];
|
|
int job = 0;
|
|
|
|
FX_StopAllSounds();
|
|
Mus_Stop();
|
|
|
|
if (!bonusonly && !isRRRA() && numplayers < 2 && ud.eog && ud.from_bonus == 0)
|
|
{
|
|
int vol = volfromlevelnum(currentLevel->levelNumber);
|
|
bonussequence_r(vol, jobs, job);
|
|
}
|
|
|
|
if (playerswhenstarted > 1 && ud.coop != 1)
|
|
{
|
|
jobs[job++] = { Create<DRRMultiplayerBonusScreen>(playerswhenstarted) };
|
|
}
|
|
else if (!bonusonly && ud.multimode <= 1)
|
|
{
|
|
if (isRRRA() && !(currentLevel->flags & MI_USERMAP) && currentLevel->levelNumber < 106) // fixme: The logic here is awful. Shift more control to the map records.
|
|
{
|
|
jobs[job++] = { Create<DRRLevelSummaryScreen>(true) };
|
|
int levnum = clamp((currentLevel->levelNumber / 100) * 7 + (currentLevel->levelNumber % 100), 0, 13);
|
|
char fn[20];
|
|
mysnprintf(fn, 20, "lvl%d.anm", levnum + 1);
|
|
static const int framespeed[] = { 20, 20, 7200 }; // wait for one minute on the final frame so that the video doesn't stop before the user notices.
|
|
jobs[job++] = { PlayVideo(fn, nullptr, framespeed) };
|
|
if (ud.eog && currentLevel->levelNumber > 100)
|
|
{
|
|
jobs[job++] = { Create<DRRRAEndOfGame>() };
|
|
}
|
|
}
|
|
else jobs[job++] = { Create<DRRLevelSummaryScreen>(false) };
|
|
}
|
|
if (job)
|
|
RunScreenJob(jobs, job, completion);
|
|
else if (completion) completion(false);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
class DRRLoadScreen : public DScreenJob
|
|
{
|
|
std::function<int(void)> callback;
|
|
MapRecord* rec;
|
|
|
|
public:
|
|
DRRLoadScreen(MapRecord* maprec, std::function<int(void)> callback_) : DScreenJob(fadein | fadeout), callback(callback_), rec(maprec) {}
|
|
|
|
int Frame(uint64_t clock, bool skiprequest)
|
|
{
|
|
DrawTexture(twod, tileGetTexture(LOADSCREEN), 0, 0, DTA_FullscreenEx, 3, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
|
|
|
|
int y = isRRRA()? 140 : 90;
|
|
BigText(160, y, (rec->flags & MI_USERMAP) ? GStrings("TXT_ENTRUM") : GStrings("TXT_ENTERIN"), 0);
|
|
BigText(160, y+24, rec->DisplayName(), 0);
|
|
|
|
// Initiate the level load once the page has been faded in completely.
|
|
if (callback && GetFadeState() == visible)
|
|
{
|
|
callback();
|
|
callback = nullptr;
|
|
}
|
|
if (clock > 5'000'000'000) return 0; // make sure the screen stays long enough to be seen.
|
|
return skiprequest? -1 : 1;
|
|
}
|
|
};
|
|
|
|
void PrintPaused_r()
|
|
{
|
|
BigText(160, 100, GStrings("Game Paused"), 0);
|
|
}
|
|
|
|
void PrintLevelName_r(double alpha)
|
|
{
|
|
BigText(160, 114, currentLevel->DisplayName(), 0, alpha);
|
|
}
|
|
|
|
// Utility for testing the above screens
|
|
CCMD(testrscreen)
|
|
{
|
|
JobDesc jobs[10];
|
|
int job = 0;
|
|
C_HideConsole();
|
|
FX_StopAllSounds();
|
|
Mus_Stop();
|
|
|
|
auto gs = gamestate;
|
|
auto completion = [=](bool)
|
|
{
|
|
if (gs == GS_LEVEL || gs == GS_DEMOSCREEN) gamestate = gs;
|
|
else gamestate = GS_STARTUP;
|
|
};
|
|
|
|
if (argv.argc() > 1)
|
|
{
|
|
int screen = strtol(argv[1], nullptr, 0);
|
|
switch (screen)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
if (!isRRRA())
|
|
{
|
|
bonussequence_r(screen, jobs, job);
|
|
RunScreenJob(jobs, job, completion);
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
jobs[job++] = { Create<DRRMultiplayerBonusScreen>(6) };
|
|
RunScreenJob(jobs, job, completion);
|
|
break;
|
|
|
|
case 3:
|
|
jobs[job++] = { Create<DRRLevelSummaryScreen>() };
|
|
RunScreenJob(jobs, job, completion);
|
|
break;
|
|
|
|
case 4:
|
|
jobs[job++] = { Create<DRRRAEndOfGame>() };
|
|
RunScreenJob(jobs, job, completion);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
END_DUKE_NS
|