2020-06-25 19:51:44 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1996, 2003 - 3D Realms Entertainment
|
|
|
|
|
|
|
|
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
|
2020-06-27 09:48:32 +00:00
|
|
|
aint with this program; if not, write to the Free Software
|
2020-06-25 19:51:44 +00:00
|
|
|
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)
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
2020-06-26 20:49:56 +00:00
|
|
|
#include "ns.h"
|
|
|
|
#include "duke3d.h"
|
|
|
|
#include "names.h"
|
|
|
|
#include "animtexture.h"
|
|
|
|
#include "animlib.h"
|
2020-06-27 09:48:32 +00:00
|
|
|
#include "raze_music.h"
|
|
|
|
#include "mapinfo.h"
|
2020-06-27 22:32:28 +00:00
|
|
|
#include "screenjob.h"
|
2020-06-28 08:14:42 +00:00
|
|
|
#include "texturemanager.h"
|
2020-06-28 19:38:25 +00:00
|
|
|
#include "buildtiles.h"
|
2020-06-26 20:49:56 +00:00
|
|
|
|
|
|
|
BEGIN_DUKE_NS
|
2020-06-25 19:51:44 +00:00
|
|
|
|
2020-06-28 08:14:42 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Sets up the game fonts.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void InitFonts_d()
|
|
|
|
{
|
|
|
|
GlyphSet fontdata;
|
|
|
|
|
|
|
|
// Small font
|
|
|
|
for (int i = 0; i < 95; i++)
|
|
|
|
{
|
|
|
|
auto tile = tileGetTexture(STARTALPHANUM + i);
|
2020-06-29 18:50:18 +00:00
|
|
|
if (tile && tile->isValid() && tile->GetTexelWidth() > 0 && tile->GetTexelHeight() > 0)
|
2020-06-28 08:14:42 +00:00
|
|
|
fontdata.Insert('!' + i, tile);
|
|
|
|
}
|
2020-06-29 18:50:18 +00:00
|
|
|
SmallFont = new ::FFont("SmallFont", nullptr, "defsmallfont", 0, 0, 0, -1, 5, false, false, false, &fontdata);
|
2020-06-28 08:14:42 +00:00
|
|
|
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));
|
2020-06-29 11:19:36 +00:00
|
|
|
// The texture offsets in this font are useless for font printing. This should only apply to these glyphs, not for international extensions, though.
|
|
|
|
GlyphSet::Iterator it(fontdata);
|
|
|
|
GlyphSet::Pair* pair;
|
|
|
|
while (it.NextPair(pair)) pair->Value->SetOffsetsNotForFont();
|
|
|
|
BigFont = new ::FFont("BigFont", nullptr, "defbigfont", 0, 0, 0, -1, 5, false, false, false, &fontdata);
|
2020-06-28 08:14:42 +00:00
|
|
|
fontdata.Clear();
|
|
|
|
|
|
|
|
// Tiny font
|
|
|
|
for (int i = 0; i < 95; i++)
|
|
|
|
{
|
|
|
|
auto tile = tileGetTexture(MINIFONT + i);
|
2020-06-29 18:50:18 +00:00
|
|
|
if (tile && tile->isValid() && tile->GetTexelWidth() > 0 && tile->GetTexelHeight() > 0)
|
2020-06-28 08:14:42 +00:00
|
|
|
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.
|
2020-06-29 20:00:38 +00:00
|
|
|
SmallFont2 = new ::FFont("SmallFont2", nullptr, "defsmallfont2", 0, 0, 0, -1, 3, false, false, false, &fontdata);
|
2020-06-29 18:50:18 +00:00
|
|
|
SmallFont2->SetKerning(1);
|
|
|
|
fontdata.Clear();
|
2020-06-28 08:14:42 +00:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-06-25 19:51:44 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
2020-06-25 19:51:44 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
static void BigText(double x, double y, const char* text)
|
2020-06-25 19:51:44 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
auto width = BigFont->StringWidth(text);
|
|
|
|
DrawText(twod, BigFont, CR_UNTRANSLATED, x - width / 2, y - 12, text, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, TAG_DONE);
|
2020-06-25 19:51:44 +00:00
|
|
|
}
|
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
static void GameText(double x, double y, const char* t, int shade, int align = -1, int trans = 0)
|
2020-06-25 19:51:44 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
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, 320, DTA_VirtualHeight, 200, DTA_TranslationIndex, TRANSLATION(Translation_Remap, trans), DTA_Color, pe, TAG_DONE);
|
2020-06-25 19:51:44 +00:00
|
|
|
}
|
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
static void MiniText(double x, double y, const char* t, int shade, int align = -1, int trans = 0)
|
2020-06-25 19:51:44 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
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, 320, DTA_VirtualHeight, 200, DTA_TranslationIndex, TRANSLATION(Translation_Remap, trans), DTA_Color, pe, TAG_DONE);
|
2020-06-25 19:51:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-06-26 20:49:56 +00:00
|
|
|
|
2020-06-27 22:32:28 +00:00
|
|
|
class DDRealmsScreen : public DScreenJob
|
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
public:
|
|
|
|
DDRealmsScreen() : DScreenJob(fadein | fadeout) {}
|
|
|
|
|
2020-06-27 22:32:28 +00:00
|
|
|
int Frame(uint64_t clock, bool skiprequest) override
|
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
const uint64_t duration = 7'000'000'000;
|
2020-06-28 19:38:25 +00:00
|
|
|
const auto tex = tileGetTexture(DREALMS, true);
|
2020-06-27 22:32:28 +00:00
|
|
|
const int translation = TRANSLATION(Translation_BasePalettes, DREALMSPAL);
|
|
|
|
|
2020-06-28 12:42:31 +00:00
|
|
|
twod->ClearScreen();
|
2020-07-01 10:55:32 +00:00
|
|
|
DrawTexture(twod, tex, 0, 0, DTA_FullscreenEx, 3, DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
|
|
|
|
return skiprequest ? -1 : clock < duration ? 1 : 0;
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class DTitleScreen : public DScreenJob
|
|
|
|
{
|
|
|
|
int soundanm = 0;
|
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
public:
|
|
|
|
DTitleScreen() : DScreenJob(fadein | fadeout) {}
|
|
|
|
|
2020-06-27 22:32:28 +00:00
|
|
|
int Frame(uint64_t nsclock, bool skiprequest) override
|
|
|
|
{
|
|
|
|
twod->ClearScreen();
|
|
|
|
int clock = nsclock * 120 / 1'000'000'000;
|
|
|
|
|
|
|
|
auto translation = TRANSLATION(Translation_BasePalettes, TITLEPAL);
|
|
|
|
|
|
|
|
twod->ClearScreen();
|
2020-07-01 10:55:32 +00:00
|
|
|
DrawTexture(twod, tileGetTexture(BETASCREEN, true), 0, 0, DTA_FullscreenEx, 3, DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
|
|
|
if (soundanm == 0 && clock >= 120 && clock < 120 + 60)
|
|
|
|
{
|
|
|
|
soundanm = 1;
|
2020-06-28 12:42:31 +00:00
|
|
|
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
if (soundanm == 1 && clock > 220 && clock < (220 + 30))
|
|
|
|
{
|
|
|
|
soundanm = 2;
|
2020-06-28 12:42:31 +00:00
|
|
|
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
if (soundanm == 2 && clock >= 280 && clock < 395)
|
|
|
|
{
|
|
|
|
soundanm = 3;
|
2020-06-28 12:42:31 +00:00
|
|
|
S_PlaySound(FLY_BY, CHAN_AUTO, CHANF_UI);
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
else if (soundanm == 3 && clock >= 395)
|
|
|
|
{
|
|
|
|
soundanm = 4;
|
2020-06-28 12:42:31 +00:00
|
|
|
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
double scale = clamp(clock - 120, 0, 60) / 64.;
|
|
|
|
if (scale > 0.)
|
2020-06-28 19:38:25 +00:00
|
|
|
DrawTexture(twod, tileGetTexture(DUKENUKEM, true), 160, 104, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200,
|
2020-07-01 10:55:32 +00:00
|
|
|
DTA_CenterOffset, true, DTA_TranslationIndex, translation, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
|
|
|
scale = clamp(clock - 220, 0, 30) / 32.;
|
|
|
|
if (scale > 0.)
|
2020-06-28 19:38:25 +00:00
|
|
|
DrawTexture(twod, tileGetTexture(THREEDEE, true), 160, 129, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200,
|
2020-07-01 10:55:32 +00:00
|
|
|
DTA_CenterOffset, true, DTA_TranslationIndex, translation, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
|
|
|
if (PLUTOPAK)
|
|
|
|
{
|
|
|
|
scale = (410 - clamp(clock, 280, 395)) / 16.;
|
2020-06-28 19:38:25 +00:00
|
|
|
if (scale > 0. && clock > 280)
|
|
|
|
DrawTexture(twod, tileGetTexture(PLUTOPAKSPRITE+1, true), 160, 151, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200,
|
2020-07-01 10:55:32 +00:00
|
|
|
DTA_CenterOffset, true, DTA_TranslationIndex, translation, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (clock > (860 + 120))
|
|
|
|
{
|
|
|
|
return 0;
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
2020-07-01 10:55:32 +00:00
|
|
|
|
2020-06-27 22:32:28 +00:00
|
|
|
return skiprequest ? -1 : 1;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-06-28 08:14:42 +00:00
|
|
|
void Logo_d(CompletionFunc completion)
|
2020-06-25 19:51:44 +00:00
|
|
|
{
|
2020-06-27 22:32:28 +00:00
|
|
|
Mus_Stop();
|
|
|
|
FX_StopAllSounds(); // JBF 20031228
|
|
|
|
|
|
|
|
static const AnimSound logosound[] =
|
|
|
|
{
|
|
|
|
{ 1, FLY_BY+1 },
|
|
|
|
{ 19, PIPEBOMB_EXPLODE+1 },
|
|
|
|
{ -1, -1 }
|
|
|
|
};
|
|
|
|
static const int logoframetimes[] = { 9, 9, 9 };
|
|
|
|
|
2020-06-28 19:38:25 +00:00
|
|
|
JobDesc jobs[3];
|
|
|
|
int job = 0;
|
|
|
|
if (VOLUMEALL && !inputState.CheckAllInput()) jobs[job++] = { PlayVideo("logo.anm", logosound, logoframetimes), []() { S_PlaySpecialMusic(MUS_INTRO); } };
|
|
|
|
if (!isNam()) jobs[job++] = { Create<DDRealmsScreen>(), nullptr };
|
|
|
|
jobs[job++] = { Create<DTitleScreen>(), []() { S_PlaySound(NITEVISION_ONOFF, CHAN_AUTO, CHANF_UI); } };
|
|
|
|
RunScreenJob(jobs, job, completion);
|
2020-06-25 19:51:44 +00:00
|
|
|
}
|
|
|
|
|
2020-06-28 12:42:31 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-06-28 08:14:42 +00:00
|
|
|
|
2020-06-28 12:42:31 +00:00
|
|
|
class DEpisode1End1 : public DScreenJob
|
2020-06-25 19:51:44 +00:00
|
|
|
{
|
2020-06-28 12:42:31 +00:00
|
|
|
int bonuscnt = 0;
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-28 12:42:31 +00:00
|
|
|
public:
|
2020-07-01 10:55:32 +00:00
|
|
|
DEpisode1End1() : DScreenJob(fadein | fadeout) {}
|
|
|
|
|
2020-06-28 12:42:31 +00:00
|
|
|
int Frame(uint64_t nsclock, bool skiprequest) override
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-28 12:42:31 +00:00
|
|
|
static const int breathe[] =
|
|
|
|
{
|
|
|
|
0, 30,VICTORY1 + 1,176,59,
|
|
|
|
30, 60,VICTORY1 + 2,176,59,
|
|
|
|
60, 90,VICTORY1 + 1,176,59,
|
|
|
|
90, 120,0 ,176,59
|
|
|
|
};
|
|
|
|
|
|
|
|
static const int bossmove[] =
|
|
|
|
{
|
|
|
|
0, 120,VICTORY1 + 3,86,59,
|
|
|
|
220, 260,VICTORY1 + 4,86,59,
|
|
|
|
260, 290,VICTORY1 + 5,86,59,
|
|
|
|
290, 320,VICTORY1 + 6,86,59,
|
|
|
|
320, 350,VICTORY1 + 7,86,59,
|
|
|
|
350, 380,VICTORY1 + 8,86,59
|
|
|
|
};
|
|
|
|
|
|
|
|
auto translation = TRANSLATION(Translation_BasePalettes, ENDINGPAL);
|
|
|
|
|
|
|
|
int totalclock = nsclock * 120 / 1'000'000'000;
|
|
|
|
|
|
|
|
uint64_t span = nsclock / 1'000'000;
|
|
|
|
|
|
|
|
twod->ClearScreen();
|
2020-06-28 19:38:25 +00:00
|
|
|
DrawTexture(twod, tileGetTexture(VICTORY1, true), 0, 50, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200,
|
2020-07-01 10:55:32 +00:00
|
|
|
DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
|
2020-06-28 12:42:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
// boss
|
|
|
|
if (totalclock > 390 && totalclock < 780)
|
|
|
|
for (int t = 0; t < 35; t += 5) if (bossmove[t + 2] && (totalclock % 390) > bossmove[t] && (totalclock % 390) <= bossmove[t + 1])
|
|
|
|
{
|
|
|
|
if (t == 10 && bonuscnt == 1)
|
|
|
|
{
|
|
|
|
S_PlaySound(SHOTGUN_FIRE, CHAN_AUTO, CHANF_UI);
|
|
|
|
S_PlaySound(SQUISHED, CHAN_AUTO, CHANF_UI);
|
|
|
|
bonuscnt++;
|
|
|
|
}
|
2020-06-28 19:38:25 +00:00
|
|
|
DrawTexture(twod, tileGetTexture(bossmove[t + 2], true), bossmove[t + 3], bossmove[t + 4], DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200,
|
2020-07-01 10:55:32 +00:00
|
|
|
DTA_TranslationIndex, translation, TAG_DONE);
|
2020-06-28 12:42:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Breathe
|
|
|
|
if (totalclock < 450 || totalclock >= 750)
|
|
|
|
{
|
|
|
|
if (totalclock >= 750)
|
|
|
|
{
|
2020-06-28 19:38:25 +00:00
|
|
|
DrawTexture(twod, tileGetTexture(VICTORY1 + 8, true), 86, 59, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200,
|
2020-07-01 10:55:32 +00:00
|
|
|
DTA_TranslationIndex, translation, TAG_DONE);
|
2020-06-28 12:42:31 +00:00
|
|
|
if (totalclock >= 750 && bonuscnt == 2)
|
|
|
|
{
|
|
|
|
S_PlaySound(DUKETALKTOBOSS, CHAN_AUTO, CHANF_UI);
|
|
|
|
bonuscnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int t = 0; t < 20; t += 5)
|
|
|
|
if (breathe[t + 2] && (totalclock % 120) > breathe[t] && (totalclock % 120) <= breathe[t + 1])
|
|
|
|
{
|
|
|
|
if (t == 5 && bonuscnt == 0)
|
|
|
|
{
|
|
|
|
S_PlaySound(BOSSTALKTODUKE, CHAN_AUTO, CHANF_UI);
|
|
|
|
bonuscnt++;
|
|
|
|
}
|
2020-06-28 19:38:25 +00:00
|
|
|
DrawTexture(twod, tileGetTexture(breathe[t + 2], true), breathe[t + 3], breathe[t + 4], DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200,
|
2020-07-01 10:55:32 +00:00
|
|
|
DTA_TranslationIndex, translation, TAG_DONE);
|
2020-06-28 12:42:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Only end after having faded out.
|
2020-07-01 10:55:32 +00:00
|
|
|
return skiprequest ? -1 : 1;
|
2020-06-28 12:42:31 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-28 12:42:31 +00:00
|
|
|
class DBlackScreen : public DScreenJob
|
|
|
|
{
|
|
|
|
int wait;
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-28 19:38:25 +00:00
|
|
|
public:
|
2020-06-28 12:42:31 +00:00
|
|
|
DBlackScreen(int w) : wait(w) {}
|
|
|
|
int Frame(uint64_t clock, bool skiprequest)
|
|
|
|
{
|
|
|
|
int span = int(clock / 1'000'000);
|
|
|
|
twod->ClearScreen();
|
|
|
|
return span < wait ? 1 : -1;
|
|
|
|
}
|
|
|
|
};
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-28 12:42:31 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-06-28 19:38:25 +00:00
|
|
|
class DEpisode3End : public DImageScreen
|
2020-06-28 12:42:31 +00:00
|
|
|
{
|
|
|
|
int sound = 0;
|
|
|
|
int64_t waittime = 0;
|
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
public:
|
|
|
|
|
2020-06-28 12:42:31 +00:00
|
|
|
FGameTexture* getTexture()
|
|
|
|
{
|
|
|
|
// Here we must provide a real texture, even if invalid, so that the sounds play.
|
|
|
|
auto texid = TexMan.CheckForTexture("radlogo.anm", ETextureType::Any, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ForceLookup);
|
|
|
|
if (texid.isValid()) return TexMan.GetGameTexture(texid);
|
|
|
|
else return TexMan.GameByIndex(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2020-07-01 10:55:32 +00:00
|
|
|
DEpisode3End() : DImageScreen(getTexture(), fadein|fadeout)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-28 12:42:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Frame(uint64_t clock, bool skiprequest)
|
|
|
|
{
|
|
|
|
switch (sound)
|
|
|
|
{
|
2020-06-27 22:32:28 +00:00
|
|
|
case 0:
|
2020-06-28 12:42:31 +00:00
|
|
|
S_PlaySound(ENDSEQVOL3SND5, CHAN_AUTO, CHANF_UI);
|
|
|
|
sound++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
2020-06-28 19:38:25 +00:00
|
|
|
if (!S_CheckSoundPlaying(ENDSEQVOL3SND5))
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-28 12:42:31 +00:00
|
|
|
S_PlaySound(ENDSEQVOL3SND6, CHAN_AUTO, CHANF_UI);
|
|
|
|
sound++;
|
|
|
|
}
|
|
|
|
break;
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-28 12:42:31 +00:00
|
|
|
case 2:
|
2020-06-28 19:38:25 +00:00
|
|
|
if (!S_CheckSoundPlaying(ENDSEQVOL3SND6))
|
2020-06-28 12:42:31 +00:00
|
|
|
{
|
|
|
|
S_PlaySound(ENDSEQVOL3SND7, CHAN_AUTO, CHANF_UI);
|
|
|
|
sound++;
|
|
|
|
}
|
|
|
|
break;
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-28 12:42:31 +00:00
|
|
|
case 3:
|
2020-06-28 19:38:25 +00:00
|
|
|
if (!S_CheckSoundPlaying(ENDSEQVOL3SND7))
|
2020-06-28 12:42:31 +00:00
|
|
|
{
|
|
|
|
S_PlaySound(ENDSEQVOL3SND8, CHAN_AUTO, CHANF_UI);
|
|
|
|
sound++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
2020-06-28 19:38:25 +00:00
|
|
|
if (!S_CheckSoundPlaying(ENDSEQVOL3SND8))
|
2020-06-28 12:42:31 +00:00
|
|
|
{
|
|
|
|
S_PlaySound(ENDSEQVOL3SND9, CHAN_AUTO, CHANF_UI);
|
|
|
|
sound++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 5:
|
2020-06-28 19:38:25 +00:00
|
|
|
if (!S_CheckSoundPlaying(ENDSEQVOL3SND8))
|
2020-06-28 12:42:31 +00:00
|
|
|
{
|
|
|
|
sound++;
|
2020-07-01 10:55:32 +00:00
|
|
|
waittime = clock + SoundEnabled()? 1'000'000'000 : 5'000'000'000; // if sound is off this wouldn't wait without a longer delay here.
|
2020-06-28 12:42:31 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
if (PLUTOPAK)
|
|
|
|
{
|
|
|
|
if (clock > waittime) skiprequest = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2020-06-28 19:38:25 +00:00
|
|
|
int ret = DImageScreen::Frame(clock, skiprequest);
|
2020-06-28 12:42:31 +00:00
|
|
|
if (ret != 1) FX_StopAllSounds();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-06-28 19:38:25 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class DEpisode4Text : public DScreenJob
|
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
public:
|
|
|
|
DEpisode4Text() : DScreenJob(fadein | fadeout) {}
|
2020-06-29 11:19:36 +00:00
|
|
|
|
2020-06-28 19:38:25 +00:00
|
|
|
int Frame(uint64_t clock, bool skiprequest)
|
|
|
|
{
|
|
|
|
twod->ClearScreen();
|
2020-06-29 18:50:18 +00:00
|
|
|
BigText(160, 60, GStrings("Thanks to all our"));
|
|
|
|
BigText(160, 60 + 16, GStrings("fans for giving"));
|
|
|
|
BigText(160, 60 + 16 + 16, GStrings("us big heads."));
|
|
|
|
BigText(160, 70 + 16 + 16 + 16, GStrings("Look for a Duke Nukem 3D"));
|
|
|
|
BigText(160, 70 + 16 + 16 + 16 + 16, GStrings("sequel soon."));
|
2020-06-28 19:38:25 +00:00
|
|
|
return skiprequest ? -1 : 1;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class DEpisode5End : public DImageScreen
|
|
|
|
{
|
|
|
|
int sound = 0;
|
|
|
|
|
|
|
|
public:
|
2020-07-01 10:55:32 +00:00
|
|
|
DEpisode5End() : DImageScreen(FIREFLYGROWEFFECT, fadein|fadeout)
|
2020-06-28 19:38:25 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int Frame(uint64_t clock, bool skiprequest)
|
|
|
|
{
|
|
|
|
switch (sound)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
sound++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
S_PlaySound(E5L7_DUKE_QUIT_YOU, CHAN_AUTO, CHANF_UI);
|
|
|
|
sound++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int ret = DImageScreen::Frame(clock, skiprequest);
|
|
|
|
if (ret != 1) FX_StopAllSounds();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
};
|
2020-06-28 12:42:31 +00:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 18:31:29 +00:00
|
|
|
static void bonussequence_d(int num, JobDesc *jobs, int &job)
|
2020-06-28 12:42:31 +00:00
|
|
|
{
|
|
|
|
static const AnimSound cineov2sound[] =
|
|
|
|
{
|
|
|
|
{ 1, WIND_AMBIENCE+1 },
|
|
|
|
{ 26, ENDSEQVOL2SND1+1 },
|
|
|
|
{ 36, ENDSEQVOL2SND2+1 },
|
|
|
|
{ 54, THUD+1 },
|
|
|
|
{ 62, ENDSEQVOL2SND3+1 },
|
|
|
|
{ 75, ENDSEQVOL2SND4 + 1 },
|
|
|
|
{ 81, ENDSEQVOL2SND5 + 1 },
|
|
|
|
{ 115, ENDSEQVOL2SND6 + 1 },
|
|
|
|
{ 124, ENDSEQVOL2SND7 + 1 },
|
|
|
|
{ -1, -1 }
|
|
|
|
};
|
|
|
|
|
2020-06-28 19:38:25 +00:00
|
|
|
static const AnimSound cineov3sound[] =
|
2020-06-28 12:42:31 +00:00
|
|
|
{
|
|
|
|
{ 1, WIND_REPEAT + 1 },
|
|
|
|
{ 98, DUKE_GRUNT + 1 },
|
|
|
|
{ 102, THUD + 1 },
|
|
|
|
{ 102, SQUISHED + 1 },
|
|
|
|
{ 124, ENDSEQVOL3SND3 + 1 },
|
|
|
|
{ 134, ENDSEQVOL3SND2 + 1 },
|
|
|
|
{ 158, PIPEBOMB_EXPLODE + 1 },
|
|
|
|
{ -1,-1 }
|
|
|
|
};
|
2020-06-28 19:38:25 +00:00
|
|
|
|
|
|
|
static const AnimSound vol4e1[] =
|
|
|
|
{
|
|
|
|
{ 3, DUKE_UNDERWATER+1 },
|
|
|
|
{ 35, VOL4ENDSND1+1 },
|
|
|
|
{ -1,-1 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const AnimSound vol4e2[] =
|
|
|
|
{
|
|
|
|
{ 11, DUKE_UNDERWATER+1 },
|
|
|
|
{ 20, VOL4ENDSND1+1 },
|
|
|
|
{ 39, VOL4ENDSND2+1 },
|
|
|
|
{ 50, -1 },
|
|
|
|
{ -1,-1 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const AnimSound vol4e3[] =
|
|
|
|
{
|
2020-06-28 20:17:27 +00:00
|
|
|
{ 1, BOSS4_DEADSPEECH+1 },
|
|
|
|
{ 40, VOL4ENDSND1+1 },
|
|
|
|
{ 40, DUKE_UNDERWATER+1 },
|
|
|
|
{ 50, BIGBANG+1 },
|
|
|
|
{ -1,-1 }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2020-06-28 19:38:25 +00:00
|
|
|
static const int framespeed_10[] = { 10, 10, 10 };
|
|
|
|
static const int framespeed_14[] = { 14, 14, 14 };
|
|
|
|
static const int framespeed_18[] = { 18, 18, 18 };
|
2020-06-28 12:42:31 +00:00
|
|
|
|
|
|
|
switch (num)
|
|
|
|
{
|
|
|
|
case 0:
|
2020-06-28 19:38:25 +00:00
|
|
|
jobs[job++] = { Create<DEpisode1End1>(), nullptr };
|
|
|
|
jobs[job++] = { Create<DImageScreen>(E1ENDSCREEN), nullptr };
|
2020-06-28 12:42:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
2020-06-28 19:38:25 +00:00
|
|
|
jobs[job++] = { PlayVideo("cineov2.anm", cineov2sound, framespeed_18), []() { S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI); } };
|
2020-07-01 18:31:29 +00:00
|
|
|
jobs[job++] = { Create<DImageScreen>(E2ENDSCREEN), []() { FX_StopAllSounds(); } };
|
2020-06-28 12:42:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2020-06-28 19:38:25 +00:00
|
|
|
jobs[job++] = { PlayVideo("cineov3.anm", cineov3sound, framespeed_10), nullptr };
|
|
|
|
jobs[job++] = { Create<DBlackScreen>(200), []() { FX_StopAllSounds(); } };
|
|
|
|
jobs[job++] = { Create<DEpisode3End>(), []() { if (!PLUTOPAK) S_PlaySound(ENDSEQVOL3SND4, CHAN_AUTO, CHANF_UI); } };
|
2020-07-01 18:31:29 +00:00
|
|
|
if (!PLUTOPAK) jobs[job++] = { Create<DImageScreen>(TexMan.GetGameTextureByName("DUKETEAM.ANM", false, FTextureManager::TEXMAN_ForceLookup)), []() { FX_StopAllSounds(); } };
|
2020-06-28 19:38:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
jobs[job++] = { PlayVideo("vol4e1.anm", vol4e1, framespeed_10), nullptr };
|
|
|
|
jobs[job++] = { PlayVideo("vol4e2.anm", vol4e2, framespeed_10), nullptr };
|
|
|
|
jobs[job++] = { PlayVideo("vol4e3.anm", vol4e3, framespeed_10), []() { S_PlaySound(ENDSEQVOL3SND4, CHAN_AUTO, CHANF_UI); } };
|
|
|
|
jobs[job++] = { Create<DEpisode4Text>(), nullptr };
|
|
|
|
jobs[job++] = { Create<DImageScreen>(TexMan.GetGameTextureByName("DUKETEAM.ANM", false, FTextureManager::TEXMAN_ForceLookup)), []() { FX_StopAllSounds(); } };
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
jobs[job++] = { Create<DEpisode5End>(), []() { FX_StopAllSounds(); } };
|
2020-06-28 12:42:31 +00:00
|
|
|
break;
|
|
|
|
}
|
2020-06-28 19:38:25 +00:00
|
|
|
}
|
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
void showtwoscreens(CompletionFunc completion)
|
|
|
|
{
|
|
|
|
JobDesc jobs[2];
|
|
|
|
int job = 0;
|
|
|
|
|
|
|
|
jobs[job++] = { Create<DImageScreen>(3291), nullptr };
|
|
|
|
jobs[job++] = { Create<DImageScreen>(3290), nullptr };
|
|
|
|
RunScreenJob(jobs, job, completion);
|
|
|
|
}
|
|
|
|
|
|
|
|
void doorders(CompletionFunc completion)
|
|
|
|
{
|
|
|
|
JobDesc jobs[4];
|
|
|
|
int job = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
jobs[job++] = { Create<DImageScreen>(ORDERING + i), nullptr };
|
|
|
|
RunScreenJob(jobs, job, completion);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
static void PlayBonusMusic()
|
2020-06-28 12:42:31 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
if (MusicEnabled() && mus_enabled)
|
|
|
|
S_PlaySound(BONUSMUSIC, CHAN_AUTO, CHANF_UI);
|
2020-06-25 19:51:44 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
}
|
2020-06-25 19:51:44 +00:00
|
|
|
|
2020-06-29 20:00:38 +00:00
|
|
|
class DDukeMultiplayerBonusScreen : public DScreenJob
|
2020-06-29 18:50:18 +00:00
|
|
|
{
|
|
|
|
int playerswhenstarted;
|
2020-06-25 19:51:44 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
public:
|
2020-07-01 10:55:32 +00:00
|
|
|
DDukeMultiplayerBonusScreen(int pws) : DScreenJob(fadein|fadeout)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
playerswhenstarted = pws;
|
2020-07-01 18:31:29 +00:00
|
|
|
PlayBonusMusic();
|
2020-06-29 18:50:18 +00:00
|
|
|
}
|
2020-06-25 19:51:44 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
int Frame(uint64_t clock, bool skiprequest)
|
|
|
|
{
|
|
|
|
char tempbuf[32];
|
2020-07-01 20:14:11 +00:00
|
|
|
int totalclock = int(clock * 120 / 1'000'000'000);
|
2020-06-29 18:50:18 +00:00
|
|
|
twod->ClearScreen();
|
|
|
|
DrawTexture(twod, tileGetTexture(MENUSCREEN), 0, 0, DTA_FullscreenEx, 3, DTA_Color, 0xff808080, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
|
|
|
|
DrawTexture(twod, tileGetTexture(INGAMEDUKETHREEDEE, true), 160, 34, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_CenterOffset, true, TAG_DONE);
|
|
|
|
if (PLUTOPAK)
|
|
|
|
DrawTexture(twod, tileGetTexture(PLUTOPAKSPRITE+2, true), 260, 36, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, DTA_CenterOffset, true, TAG_DONE);
|
2020-06-25 19:51:44 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
GameText(160, 58 + 2, GStrings("Multiplayer Totals"), 0, 0);
|
|
|
|
GameText(160, 58 + 10, currentLevel->DisplayName(), 0, 0);
|
2020-07-01 20:14:11 +00:00
|
|
|
GameText(160, 165, GStrings("Presskey"), 8 - int(sin(totalclock / 10.) * 8), 0);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
int t = 0;
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
MiniText(38, 80, GStrings("Name"), 0, -1, 8);
|
|
|
|
MiniText(269+20, 80, GStrings("Kills"), 0, 1, 8);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
for (int i = 0; i < playerswhenstarted; i++)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
mysnprintf(tempbuf, 32, "%-4ld", i + 1);
|
|
|
|
MiniText(92 + (i * 23), 80, tempbuf, 0, -1, 3);
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
for (int i = 0; i < playerswhenstarted; i++)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
int xfragtotal = 0;
|
|
|
|
mysnprintf(tempbuf, 32, "%ld", i + 1);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
MiniText(30, 90 + t, tempbuf, 0);
|
|
|
|
MiniText(38, 90 + t, g_player[i].user_name, 0, -1, ps[i].palookup);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
for (int y = 0; y < playerswhenstarted; y++)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
int frag = g_player[i].frags[y];// frags[i][y]);
|
|
|
|
if (i == y)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
mysnprintf(tempbuf, 32, "%-4ld", ps[y].fraggedself);
|
|
|
|
MiniText(92 + (y * 23), 90 + t, tempbuf, 0, -1, 2);
|
2020-06-27 22:32:28 +00:00
|
|
|
xfragtotal -= ps[y].fraggedself;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
mysnprintf(tempbuf, 32, "%-4ld", frag);
|
|
|
|
MiniText(92 + (y * 23), 90 + t, tempbuf, 0);
|
|
|
|
xfragtotal += frag;
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
2020-06-29 18:50:18 +00:00
|
|
|
/*
|
|
|
|
if (myconnectindex == connecthead)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
mysnprintf(tempbuf, 32, "stats %ld killed %ld %ld\n", i + 1, y + 1, frag);
|
2020-06-27 22:32:28 +00:00
|
|
|
sendscore(tempbuf);
|
|
|
|
}
|
2020-06-29 18:50:18 +00:00
|
|
|
*/
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
mysnprintf(tempbuf, 32, "%-4ld", xfragtotal);
|
|
|
|
MiniText(101 + (8 * 23), 90 + t, tempbuf, 0, -1, 2);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
|
|
|
t += 7;
|
|
|
|
}
|
|
|
|
|
2020-06-29 18:50:18 +00:00
|
|
|
for (int y = 0; y < playerswhenstarted; y++)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
int yfragtotal = 0;
|
|
|
|
for (int i = 0; i < playerswhenstarted; i++)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-06-29 18:50:18 +00:00
|
|
|
if (i == y)
|
2020-06-27 22:32:28 +00:00
|
|
|
yfragtotal += ps[i].fraggedself;
|
2020-06-29 18:50:18 +00:00
|
|
|
int frag = g_player[i].frags[y];// frags[i][y]);
|
|
|
|
yfragtotal += frag;
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
2020-06-29 18:50:18 +00:00
|
|
|
mysnprintf(tempbuf, 32, "%-4ld", yfragtotal);
|
2020-06-29 20:00:38 +00:00
|
|
|
MiniText(92 + (y * 23), 96 + (8 * 7), tempbuf, 0, -1, 2);
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
|
2020-06-29 20:00:38 +00:00
|
|
|
MiniText(45, 96 + (8 * 7), GStrings("Deaths"), 0, -1, 8);
|
2020-06-29 18:50:18 +00:00
|
|
|
return skiprequest ? -1 : 1;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-06-29 22:15:48 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
class DDukeLevelSummaryScreen : public DScreenJob
|
2020-06-29 22:15:48 +00:00
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
const char* lastmapname;
|
|
|
|
int gfx_offset;
|
|
|
|
int bonuscnt = 0;
|
2020-06-29 18:50:18 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
void SetTotalClock(int tc)
|
2020-06-29 18:50:18 +00:00
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
SetClock(tc * (uint64_t)1'000'000'000 / 120);
|
2020-06-29 18:50:18 +00:00
|
|
|
}
|
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
public:
|
|
|
|
DDukeLevelSummaryScreen() : DScreenJob(fadein | fadeout)
|
|
|
|
{
|
|
|
|
gfx_offset = BONUSSCREEN + ((ud.volume_number == 1) ? 5 : 0);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (ud.volume_number == 0 && ud.last_level == 8 && boardfilename[0]) // todo: get rid of this awful hack.
|
|
|
|
{
|
|
|
|
lastmapname = strrchr(boardfilename, '\\');
|
|
|
|
if (!lastmapname) lastmapname = strrchr(boardfilename, '/');
|
|
|
|
if (!lastmapname) lastmapname = boardfilename;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lastmapname = currentLevel->DisplayName();
|
|
|
|
}
|
|
|
|
PlayBonusMusic();
|
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
void FormatTime(int time, char* tempbuf)
|
|
|
|
{
|
|
|
|
mysnprintf(tempbuf, 32, "%02ld:%02ld", (time / (26 * 60)) % 60, (time / 26) % 60);
|
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
void PrintTime(int totalclock)
|
|
|
|
{
|
|
|
|
char tempbuf[32];
|
|
|
|
GameText(10, 59 + 9, GStrings("TXT_YourTime"), 0);
|
|
|
|
GameText(10, 69 + 9, GStrings("TXT_ParTime"), 0);
|
|
|
|
if (!isNamWW2GI())
|
|
|
|
GameText(10, 78 + 9, GStrings("TXT_3DRTIME"), 0);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (bonuscnt == 0)
|
|
|
|
bonuscnt++;
|
2020-06-29 18:50:18 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (totalclock > (60 * 4))
|
|
|
|
{
|
|
|
|
if (bonuscnt == 1)
|
|
|
|
{
|
|
|
|
bonuscnt++;
|
|
|
|
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
|
|
|
|
}
|
|
|
|
FormatTime(ps[myconnectindex].player_par, tempbuf);
|
|
|
|
GameText((320 >> 2) + 71, 60 + 9, tempbuf, 0);
|
2020-06-29 18:50:18 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
FormatTime(currentLevel->parTime, tempbuf);
|
|
|
|
GameText((320 >> 2) + 71, 69 + 9, tempbuf, 0);
|
2020-06-29 18:50:18 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (!isNamWW2GI())
|
|
|
|
{
|
|
|
|
FormatTime(currentLevel->designerTime, tempbuf);
|
|
|
|
GameText((320 >> 2) + 71, 78 + 9, tempbuf, 0);
|
|
|
|
}
|
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
2020-06-25 19:51:44 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
void PrintKills(int totalclock)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
GameText(10, 94 + 9, GStrings("TXT_EnemiesKilled"), 0);
|
|
|
|
GameText(10, 99 + 4 + 9, GStrings("TXT_EnemiesLeft"), 0);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (bonuscnt == 2)
|
|
|
|
{
|
|
|
|
bonuscnt++;
|
|
|
|
S_PlaySound(FLY_BY, CHAN_AUTO, CHANF_UI);
|
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (totalclock > (60 * 7))
|
|
|
|
{
|
|
|
|
if (bonuscnt == 3)
|
|
|
|
{
|
|
|
|
bonuscnt++;
|
|
|
|
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
|
|
|
|
}
|
|
|
|
mysnprintf(tempbuf, 32, "%-3ld", ps[myconnectindex].actors_killed);
|
|
|
|
GameText((320 >> 2) + 70, 93 + 9, tempbuf, 0);
|
|
|
|
if (ud.player_skill > 3)
|
|
|
|
{
|
|
|
|
mysnprintf(tempbuf, 32, GStrings("TXT_N_A"));
|
|
|
|
GameText((320 >> 2) + 70, 99 + 4 + 9, tempbuf, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((ps[myconnectindex].max_actors_killed - ps[myconnectindex].actors_killed) < 0)
|
|
|
|
mysnprintf(tempbuf, 32, "%-3ld", 0);
|
|
|
|
else mysnprintf(tempbuf, 32, "%-3ld", ps[myconnectindex].max_actors_killed - ps[myconnectindex].actors_killed);
|
|
|
|
GameText((320 >> 2) + 70, 99 + 4 + 9, tempbuf, 0);
|
|
|
|
}
|
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
void PrintSecrets(int totalclock)
|
|
|
|
{
|
|
|
|
GameText(10, 120 + 9, GStrings("TXT_SECFND"), 0);
|
|
|
|
GameText(10, 130 + 9, GStrings("TXT_SECMISS"), 0);
|
|
|
|
if (bonuscnt == 4) bonuscnt++;
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (totalclock > (60 * 10))
|
|
|
|
{
|
|
|
|
if (bonuscnt == 5)
|
|
|
|
{
|
|
|
|
bonuscnt++;
|
|
|
|
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
|
|
|
|
}
|
|
|
|
mysnprintf(tempbuf, 32, "%-3d", ps[myconnectindex].secret_rooms);
|
|
|
|
GameText((320 >> 2) + 70, 120 + 9, tempbuf, 0);
|
|
|
|
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);
|
|
|
|
GameText((320 >> 2) + 70, 130 + 9, tempbuf, 0);
|
|
|
|
}
|
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
int Frame(uint64_t clock, bool skiprequest)
|
|
|
|
{
|
2020-07-01 20:14:11 +00:00
|
|
|
twod->ClearScreen();
|
2020-07-01 10:55:32 +00:00
|
|
|
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);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (lastmapname) BigText(160, 20 - 6, lastmapname);
|
|
|
|
BigText(160, 36 - 6, GStrings("Completed"));
|
2020-07-01 20:14:11 +00:00
|
|
|
GameText(160, 192, GStrings("PRESSKEY"), 8 - int(sin(totalclock / 10.) * 8), 0);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (totalclock > (60 * 3))
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
PrintTime(totalclock);
|
|
|
|
}
|
|
|
|
if (totalclock > (60 * 6))
|
|
|
|
{
|
|
|
|
PrintKills(totalclock);
|
|
|
|
}
|
|
|
|
if (totalclock > (60 * 9))
|
|
|
|
{
|
|
|
|
PrintSecrets(totalclock);
|
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (totalclock > (1000000000L) && totalclock < (1000000320L))
|
|
|
|
{
|
|
|
|
int val = (totalclock >> 4) % 15;
|
|
|
|
if (val == 0)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
if (bonuscnt == 6)
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
bonuscnt++;
|
|
|
|
S_PlaySound(SHOTGUN_COCK, CHAN_AUTO, CHANF_UI);
|
|
|
|
S_PlaySound(BONUS_SPEECH1 + (rand() & 3), CHAN_AUTO, CHANF_UI);
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
int tile = val == 2 || val == 3 ? gfx_offset + 4 : gfx_offset + 3;
|
|
|
|
DrawTexture(twod, tileGetTexture(tile), 199, 31, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, TAG_DONE);
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
2020-07-01 10:55:32 +00:00
|
|
|
}
|
|
|
|
else if (totalclock > (10240 + 120L)) return 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int val = (totalclock >> 5) & 3;
|
|
|
|
int tile = val == 2 ? gfx_offset + 2 : gfx_offset + 1;
|
|
|
|
DrawTexture(twod, tileGetTexture(tile), 199, 31, DTA_FullscreenScale, 3, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, TAG_DONE);
|
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (totalclock > 10240 && totalclock < 10240 + 10240)
|
|
|
|
SetTotalClock(1024);
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
if (skiprequest && totalclock > (60 * 2))
|
|
|
|
{
|
|
|
|
skiprequest = false;
|
|
|
|
if (totalclock < (60 * 13))
|
2020-06-27 22:32:28 +00:00
|
|
|
{
|
2020-07-01 10:55:32 +00:00
|
|
|
SetTotalClock(60 * 13);
|
|
|
|
}
|
|
|
|
else if (totalclock < (1000000000))
|
|
|
|
SetTotalClock(1000000000);
|
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
};
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 18:31:29 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void dobonus_d(bool bonusonly, CompletionFunc completion)
|
2020-07-01 10:55:32 +00:00
|
|
|
{
|
2020-07-01 18:31:29 +00:00
|
|
|
JobDesc jobs[20];
|
|
|
|
int job = 0;
|
|
|
|
|
|
|
|
FX_StopAllSounds();
|
|
|
|
Mus_Stop();
|
|
|
|
|
|
|
|
if (!bonusonly && numplayers < 2 && ud.eog && ud.from_bonus == 0)
|
|
|
|
{
|
|
|
|
bonussequence_d(ud.volume_number, jobs, job);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (playerswhenstarted > 1 && ud.coop != 1)
|
|
|
|
{
|
|
|
|
jobs[job++] = { Create<DDukeMultiplayerBonusScreen>(playerswhenstarted) };
|
|
|
|
}
|
|
|
|
else if (!bonusonly && ud.multimode <= 1)
|
|
|
|
{
|
|
|
|
jobs[job++] = { Create<DDukeLevelSummaryScreen>() };
|
|
|
|
}
|
|
|
|
if (job)
|
|
|
|
RunScreenJob(jobs, job, completion);
|
|
|
|
else if (completion) completion(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void e4intro(CompletionFunc completion)
|
|
|
|
{
|
|
|
|
JobDesc jobs[5];
|
|
|
|
int job = 0;
|
|
|
|
|
|
|
|
static const AnimSound vol42a[] =
|
|
|
|
{
|
|
|
|
{ 1, INTRO4_B + 1 },
|
|
|
|
{ 12, SHORT_CIRCUIT + 1 },
|
|
|
|
{ 18, INTRO4_5 + 1 },
|
|
|
|
{ 34, SHORT_CIRCUIT + 1 },
|
|
|
|
{ -1,-1 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const AnimSound vol41a[] =
|
|
|
|
{
|
|
|
|
{ 1, INTRO4_1 + 1 },
|
|
|
|
{ 7, INTRO4_3 + 1 },
|
|
|
|
{ 12, INTRO4_2 + 1 },
|
|
|
|
{ 26, INTRO4_4 + 1 },
|
|
|
|
{ -1,-1 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const AnimSound vol43a[] =
|
|
|
|
{
|
|
|
|
{ 10, INTRO4_6 + 1 },
|
|
|
|
{ -1,-1 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const int framespeed_10[] = { 10, 10, 10 };
|
|
|
|
static const int framespeed_14[] = { 14, 14, 14 };
|
|
|
|
|
|
|
|
S_PlaySpecialMusic(MUS_BRIEFING);
|
|
|
|
jobs[job++] = { PlayVideo("vol41a.anm", vol41a, framespeed_10), nullptr };
|
|
|
|
jobs[job++] = { PlayVideo("vol42a.anm", vol42a, framespeed_14), nullptr };
|
|
|
|
jobs[job++] = { PlayVideo("vol43a.anm", vol43a, framespeed_10), nullptr };
|
|
|
|
RunScreenJob(jobs, job, completion);
|
2020-07-01 10:55:32 +00:00
|
|
|
}
|
2020-06-27 22:32:28 +00:00
|
|
|
|
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
// Utility for testing the above screens
|
|
|
|
CCMD(testscreen)
|
|
|
|
{
|
2020-07-01 18:31:29 +00:00
|
|
|
JobDesc jobs[10];
|
|
|
|
int job = 0;
|
2020-07-01 10:55:32 +00:00
|
|
|
C_HideConsole();
|
2020-07-01 18:31:29 +00:00
|
|
|
FX_StopAllSounds();
|
|
|
|
Mus_Stop();
|
2020-07-01 10:55:32 +00:00
|
|
|
if (argv.argc() > 1)
|
|
|
|
{
|
|
|
|
int screen = strtol(argv[1], nullptr, 0);
|
|
|
|
switch (screen)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
case 4:
|
2020-07-01 18:31:29 +00:00
|
|
|
bonussequence_d(screen, jobs, job);
|
|
|
|
RunScreenJob(jobs, job, nullptr);
|
|
|
|
break;
|
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
case 5:
|
2020-07-01 18:31:29 +00:00
|
|
|
e4intro(nullptr);
|
2020-07-01 10:55:32 +00:00
|
|
|
break;
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
case 6:
|
2020-07-01 18:31:29 +00:00
|
|
|
jobs[job++] = { Create<DDukeMultiplayerBonusScreen>(6) };
|
|
|
|
RunScreenJob(jobs, job, nullptr);
|
2020-07-01 10:55:32 +00:00
|
|
|
break;
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
case 7:
|
|
|
|
showtwoscreens(nullptr);
|
|
|
|
break;
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
case 8:
|
|
|
|
doorders(nullptr);
|
|
|
|
break;
|
2020-06-27 22:32:28 +00:00
|
|
|
|
2020-07-01 10:55:32 +00:00
|
|
|
case 9:
|
2020-07-01 18:31:29 +00:00
|
|
|
jobs[job++] = { Create<DDukeLevelSummaryScreen>() };
|
|
|
|
RunScreenJob(jobs, job, nullptr);
|
2020-07-01 10:55:32 +00:00
|
|
|
break;
|
2020-07-01 20:14:11 +00:00
|
|
|
|
|
|
|
case 10:
|
|
|
|
ud.eog = true;
|
|
|
|
jobs[job++] = { Create<DDukeLevelSummaryScreen>() };
|
|
|
|
RunScreenJob(jobs, job, nullptr);
|
|
|
|
ud.eog = false;
|
|
|
|
break;
|
|
|
|
|
2020-06-27 22:32:28 +00:00
|
|
|
}
|
|
|
|
}
|
2020-06-25 19:51:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-26 20:49:56 +00:00
|
|
|
END_DUKE_NS
|