- more screen job setup work.

* interface for movie player done.
* first cutscene definition done.
* all converted classes removed from C++ code.
This commit is contained in:
Christoph Oelckers 2021-04-25 21:52:58 +02:00
parent 4ff2010bd1
commit 66799d9a6d
7 changed files with 230 additions and 1297 deletions

View file

@ -54,6 +54,14 @@
class MoviePlayer class MoviePlayer
{ {
protected:
enum EMovieFlags
{
NOSOUNDCUTOFF = 1,
FIXEDVIEWPORT = 2, // Forces fixed 640x480 screen size like for Blood's intros.
};
int flags;
public: public:
virtual void Start() {} virtual void Start() {}
virtual bool Frame(uint64_t clock) = 0; virtual bool Frame(uint64_t clock) = 0;
@ -77,16 +85,16 @@ class AnmPlayer : public MoviePlayer
int frametime = 0; int frametime = 0;
int nextframetime = 0; int nextframetime = 0;
AnimTextures animtex; AnimTextures animtex;
const AnimSound* animSnd; const TArray<int> animSnd;
const int* frameTicks; const int* frameTicks;
bool nostopsound;
public: public:
bool isvalid() { return numframes > 0; } bool isvalid() { return numframes > 0; }
AnmPlayer(FileReader& fr, const AnimSound* ans, const int *frameticks, bool nosoundcutoff) AnmPlayer(FileReader& fr, TArray<int>& ans, const int *frameticks, int flags_)
: animSnd(ans), frameTicks(frameticks), nostopsound(nosoundcutoff) : animSnd(std::move(ans)), frameTicks(frameticks)
{ {
flags = flags_;
buffer = fr.ReadPadded(1); buffer = fr.ReadPadded(1);
fr.Close(); fr.Close();
@ -130,11 +138,12 @@ public:
} }
nextframetime += delay; nextframetime += delay;
if (animSnd) for (int i = 0; animSnd[i].framenum >= 0; i++) bool nostopsound = (flags & NOSOUNDCUTOFF);
for (unsigned i = 0; i < animSnd.Size(); i+=2)
{ {
if (animSnd[i].framenum == curframe) if (animSnd[i] == curframe)
{ {
int sound = animSnd[i].soundnum; int sound = animSnd[i+1];
if (sound == -1) if (sound == -1)
soundEngine->StopAllChannels(); soundEngine->StopAllChannels();
else if (SoundEnabled()) else if (SoundEnabled())
@ -148,6 +157,7 @@ public:
void Stop() override void Stop() override
{ {
bool nostopsound = (flags & NOSOUNDCUTOFF);
if (!nostopsound) soundEngine->StopAllChannels(); if (!nostopsound) soundEngine->StopAllChannels();
} }
@ -210,7 +220,7 @@ class VpxPlayer : public MoviePlayer
bool failed = false; bool failed = false;
FileReader fr; FileReader fr;
AnimTextures animtex; AnimTextures animtex;
const AnimSound* animSnd; const TArray<int> animSnd;
unsigned width, height; unsigned width, height;
TArray<uint8_t> Pic; TArray<uint8_t> Pic;
@ -235,10 +245,9 @@ public:
public: public:
bool isvalid() { return !failed; } bool isvalid() { return !failed; }
VpxPlayer(FileReader& fr_, const AnimSound* animSnd_, int origframedelay, FString& error) VpxPlayer(FileReader& fr_, TArray<int>& animSnd_, int flags, int origframedelay, FString& error) : animSnd(std::move(animSnd_))
{ {
fr = std::move(fr_); fr = std::move(fr_);
animSnd = animSnd_;
if (!ReadIVFHeader(origframedelay)) if (!ReadIVFHeader(origframedelay))
{ {
@ -434,18 +443,22 @@ public:
framenum++; framenum++;
if (framenum >= numframes) stop = true; if (framenum >= numframes) stop = true;
bool nostopsound = (flags & NOSOUNDCUTOFF);
int soundframe = convdenom ? Scale(framenum, convnumer, convdenom) : framenum; int soundframe = convdenom ? Scale(framenum, convnumer, convdenom) : framenum;
if (soundframe > lastsoundframe) if (soundframe > lastsoundframe)
{ {
if (animSnd && soundtrack == -1) for (int i = 0; animSnd[i].framenum >= 0; i++) if (soundtrack == -1)
{ {
if (animSnd[i].framenum == soundframe) for (unsigned i = 0; i < animSnd.Size(); i += 2)
{ {
int sound = animSnd[i].soundnum; if (animSnd[i] == soundframe)
if (sound == -1) {
soundEngine->StopAllChannels(); int sound = animSnd[i + 1];
else if (SoundEnabled()) if (sound == -1)
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_AUTO, CHANF_NONE, sound, 1.f, ATTN_NONE); soundEngine->StopAllChannels();
else if (SoundEnabled())
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_AUTO, nostopsound ? CHANF_UI : CHANF_NONE, sound, 1.f, ATTN_NONE);
}
} }
} }
lastsoundframe = soundframe; lastsoundframe = soundframe;
@ -458,6 +471,8 @@ public:
void Stop() void Stop()
{ {
Mus_Stop(); Mus_Stop();
bool nostopsound = (flags & NOSOUNDCUTOFF);
if (!nostopsound) soundEngine->StopAllChannels();
} }
~VpxPlayer() ~VpxPlayer()
@ -499,9 +514,10 @@ class SmkPlayer : public MoviePlayer
bool fullscreenScale; bool fullscreenScale;
uint64_t nFrameNs; uint64_t nFrameNs;
int nFrame = 0; int nFrame = 0;
const AnimSound* animSnd; const TArray<int> animSnd;
FString filename; FString filename;
SoundStream* stream = nullptr; SoundStream* stream = nullptr;
bool hassound = false;
public: public:
bool isvalid() { return hSMK.isValid; } bool isvalid() { return hSMK.isValid; }
@ -535,7 +551,7 @@ public:
} }
SmkPlayer(const char *fn, const AnimSound* ans, bool fixedviewport) SmkPlayer(const char *fn, TArray<int>& ans, int flags) : animSnd(std::move(ans))
{ {
hSMK = Smacker_Open(fn); hSMK = Smacker_Open(fn);
if (!hSMK.isValid) if (!hSMK.isValid)
@ -548,9 +564,8 @@ public:
nFrameNs = 1'000'000'000 / nFrameRate; nFrameNs = 1'000'000'000 / nFrameRate;
nFrames = Smacker_GetNumFrames(hSMK); nFrames = Smacker_GetNumFrames(hSMK);
Smacker_GetPalette(hSMK, palette); Smacker_GetPalette(hSMK, palette);
fullscreenScale = (!fixedviewport || (nWidth <= 320 && nHeight <= 200) || nWidth >= 640 || nHeight >= 480); fullscreenScale = (!(flags & FIXEDVIEWPORT) || (nWidth <= 320 && nHeight <= 200) || nWidth >= 640 || nHeight >= 480);
bool hassound = false;
numAudioTracks = Smacker_GetNumAudioTracks(hSMK); numAudioTracks = Smacker_GetNumAudioTracks(hSMK);
if (numAudioTracks) if (numAudioTracks)
{ {
@ -563,14 +578,12 @@ public:
auto read = Smacker_GetAudioData(hSMK, 0, (int16_t*)audioBuffer.Data()); auto read = Smacker_GetAudioData(hSMK, 0, (int16_t*)audioBuffer.Data());
if (adata.inf.bitsPerSample == 8) copy8bitSamples(read); if (adata.inf.bitsPerSample == 8) copy8bitSamples(read);
else copy16bitSamples(read); else copy16bitSamples(read);
animSnd = nullptr;
hassound = true; hassound = true;
} }
} }
if (!hassound) if (!hassound)
{ {
adata.inf = {}; adata.inf = {};
animSnd = ans;
} }
} }
@ -625,15 +638,16 @@ public:
{ {
nFrame++; nFrame++;
Smacker_GetNextFrame(hSMK); Smacker_GetNextFrame(hSMK);
if (animSnd) for (int i = 0; animSnd[i].framenum >= 0; i++) bool nostopsound = (flags & NOSOUNDCUTOFF);
if (!hassound) for (unsigned i = 0; i < animSnd.Size(); i += 2)
{ {
if (animSnd[i].framenum == nFrame) if (animSnd[i] == nFrame)
{ {
int sound = animSnd[i].soundnum; int sound = animSnd[i + 1];
if (sound == -1) if (sound == -1)
soundEngine->StopAllChannels(); soundEngine->StopAllChannels();
else if (SoundEnabled()) else if (SoundEnabled())
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_AUTO, CHANF_NONE, sound, 1.f, ATTN_NONE); soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_AUTO, nostopsound ? CHANF_UI : CHANF_NONE, sound, 1.f, ATTN_NONE);
} }
} }
} }
@ -641,78 +655,31 @@ public:
return nFrame < nFrames; return nFrame < nFrames;
} }
void Stop() override
{
if (stream) S_StopCustomStream(stream);
bool nostopsound = (flags & NOSOUNDCUTOFF);
if (!nostopsound && !hassound) soundEngine->StopAllChannels();
}
~SmkPlayer() ~SmkPlayer()
{ {
Smacker_Close(hSMK); Smacker_Close(hSMK);
if (stream) S_StopCustomStream(stream);
soundEngine->StopAllChannels();
animtex.Clean(); animtex.Clean();
} }
}; };
#if 0
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// //
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
class DMoviePlayer : public DSkippableScreenJob MoviePlayer* OpenMovie(const char* filename, TArray<int>& ans, const int* frameticks, int flags, FString& error)
{
MoviePlayer* player;
bool started = false;
public:
DMoviePlayer(MoviePlayer* mp)
{
player = mp;
pausable = false;
}
void Draw(double smoothratio) override
{
if (!player)
{
state = stopped;
return;
}
if (!started)
{
started = true;
player->Start();
}
uint64_t clock = (ticks + smoothratio) * 1'000'000'000. / GameTicRate;
if (state == running && !player->Frame(clock))
{
state = finished;
}
}
void OnDestroy() override
{
if (player)
{
player->Stop();
delete player;
}
player = nullptr;
}
};
#endif
#if 0
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
MoviePlayer* OpenMovie(const char* filename, const AnimSound* ans, const int* frameticks, bool nosoundcutoff, FString& error)
{ {
FileReader fr; FileReader fr;
// first try as .ivf - but only if sounds are provided - the decoder is video only. // first try as .ivf - but only if sounds are provided - the decoder is video only.
if (ans) if (ans.Size())
{ {
auto fn = StripExtension(filename); auto fn = StripExtension(filename);
DefaultExtension(fn, ".ivf"); DefaultExtension(fn, ".ivf");
@ -742,7 +709,7 @@ MoviePlayer* OpenMovie(const char* filename, const AnimSound* ans, const int* fr
if (!memcmp(id, "LPF ", 4)) if (!memcmp(id, "LPF ", 4))
{ {
auto anm = new AnmPlayer(fr, ans, frameticks, nosoundcutoff); auto anm = new AnmPlayer(fr, ans, frameticks, flags);
if (!anm->isvalid()) if (!anm->isvalid())
{ {
error.Format("%s: invalid ANM file.\n", filename); error.Format("%s: invalid ANM file.\n", filename);
@ -754,7 +721,7 @@ MoviePlayer* OpenMovie(const char* filename, const AnimSound* ans, const int* fr
else if (!memcmp(id, "SMK2", 4)) else if (!memcmp(id, "SMK2", 4))
{ {
fr.Close(); fr.Close();
auto anm = new SmkPlayer(filename, ans, isBlood()); // Fixme: Handle Blood's video scaling behavior more intelligently. auto anm = new SmkPlayer(filename, ans, flags);
if (!anm->isvalid()) if (!anm->isvalid())
{ {
error.Format("%s: invalid SMK file.\n", filename); error.Format("%s: invalid SMK file.\n", filename);
@ -775,7 +742,7 @@ MoviePlayer* OpenMovie(const char* filename, const AnimSound* ans, const int* fr
} }
else if (!memcmp(id, "DKIF\0\0 \0VP80", 12)) else if (!memcmp(id, "DKIF\0\0 \0VP80", 12))
{ {
auto anm = new VpxPlayer(fr, ans, frameticks ? frameticks[1] : 0, error); auto anm = new VpxPlayer(fr, ans, frameticks ? frameticks[1] : 0, flags, error);
if (!anm->isvalid()) if (!anm->isvalid())
{ {
delete anm; delete anm;
@ -798,29 +765,26 @@ MoviePlayer* OpenMovie(const char* filename, const AnimSound* ans, const int* fr
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
DScreenJob* PlayVideo(const char* filename, const AnimSound* ans, const int* frameticks, bool nosoundcutoff) DEFINE_ACTION_FUNCTION(_MoviePlayer, Create)
{ {
if (!filename) PARAM_PROLOGUE;
{ PARAM_STRING(filename);
return Create<DBlackScreen>(1); PARAM_POINTER(sndinf, TArray<int>);
} PARAM_INT(flags);
PARAM_INT(frametime);
PARAM_INT(firstframetime);
PARAM_INT(lastframetime);
FString error; FString error;
auto movie = OpenMovie(filename, ans, frameticks, nosoundcutoff, error); if (firstframetime == -1) firstframetime = frametime;
if (lastframetime == -1) lastframetime = frametime;
int frametimes[] = { firstframetime, frametime, lastframetime };
auto movie = OpenMovie(filename, *sndinf, frametime == -1? nullptr : frametimes, flags, error);
if (!movie) if (!movie)
{ {
Printf(TEXTCOLOR_YELLOW, "%s", error.GetChars()); Printf(TEXTCOLOR_YELLOW, "%s", error.GetChars());
return Create<DBlackScreen>(1);
} }
return Create<DMoviePlayer>(movie); ACTION_RETURN_POINTER(movie);
}
#endif
DEFINE_ACTION_FUNCTION(_MoviePlayer, OpenMovie)
{
PARAM_PROLOGUE;
// todo
return 0;
} }
DEFINE_ACTION_FUNCTION(_MoviePlayer, Start) DEFINE_ACTION_FUNCTION(_MoviePlayer, Start)

View file

@ -198,12 +198,6 @@ bool ScreenJobResponder(event_t* ev);
void ScreenJobTick(); void ScreenJobTick();
bool ScreenJobDraw(); bool ScreenJobDraw();
struct AnimSound
{
int framenum;
int soundnum;
};
#if 0 #if 0
DScreenJob *PlayVideo(const char *filename, const AnimSound *ans = nullptr, const int *frameticks = nullptr, bool nosoundstop = false); DScreenJob *PlayVideo(const char *filename, const AnimSound *ans = nullptr, const int *frameticks = nullptr, bool nosoundstop = false);
#endif #endif

View file

@ -131,7 +131,6 @@ void InitFonts_d()
} }
#if 0
//========================================================================== //==========================================================================
// //
// wrappers around DrawText to allow easier reuse of the old code. // wrappers around DrawText to allow easier reuse of the old code.
@ -146,155 +145,6 @@ static void BigText(double x, double y, const char* text, int align = -1, double
DrawText(twod, BigFont, CR_UNTRANSLATED, x, y - 12, text, DTA_FullscreenScale, FSMode_Fit320x200, DTA_Alpha, alpha, TAG_DONE); DrawText(twod, BigFont, CR_UNTRANSLATED, x, y - 12, text, DTA_FullscreenScale, FSMode_Fit320x200, DTA_Alpha, alpha, TAG_DONE);
} }
static void GameText(double x, double y, const char* t, int shade, int align = -1, int trans = 0)
{
if (align != -1)
x -= SmallFont->StringWidth(t) * (align == 0 ? 0.5 : 1);
DrawText(twod, SmallFont, CR_UNDEFINED, x, y + 2, t, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TranslationIndex, TRANSLATION(Translation_Remap, trans), DTA_Color, shadeToLight(shade), TAG_DONE);
}
static void MiniText(double x, double y, const char* t, int shade, int align = -1, int trans = 0)
{
if (align != -1)
x -= SmallFont2->StringWidth(t) * (align == 0 ? 0.5 : 1);
DrawText(twod, SmallFont2, CR_UNDEFINED, x, y, t, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TranslationIndex, TRANSLATION(Translation_Remap, trans), DTA_Color, shadeToLight(shade), TAG_DONE);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DDRealmsScreen : public DSkippableScreenJob
{
public:
DDRealmsScreen() : DSkippableScreenJob(fadein | fadeout) {}
void Start() override
{
S_PlaySpecialMusic(MUS_INTRO);
}
void OnTick() override
{
if (ticks >= 7 * GameTicRate) state = finished;
}
void Draw(double smoothratio) override
{
const auto tex = tileGetTexture(DREALMS, true);
int translation = tex->GetTexture()->GetImage()->UseGamePalette() ? TRANSLATION(Translation_BasePalettes, DREALMSPAL) : 0;
twod->ClearScreen();
DrawTexture(twod, tex, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
}
};
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DTitleScreen : public DSkippableScreenJob
{
int soundanm = 0;
public:
DTitleScreen() : DSkippableScreenJob(fadein | fadeout)
{
}
void Start() override
{
if (isNam() || userConfig.nologo) S_PlaySpecialMusic(MUS_INTRO);
}
void OnTick() override
{
int clock = ticks * 120 / GameTicRate;
if (soundanm == 0 && clock >= 120 && clock < 120 + 60)
{
soundanm = 1;
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
}
if (soundanm == 1 && clock > 220 && clock < (220 + 30))
{
soundanm = 2;
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
}
if (soundanm == 2 && clock >= 280 && clock < 395)
{
soundanm = 3;
if (isPlutoPak()) S_PlaySound(FLY_BY, CHAN_AUTO, CHANF_UI);
}
else if (soundanm == 3 && clock >= 395)
{
soundanm = 4;
if (isPlutoPak()) S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
}
if (clock > (860 + 120))
{
state = finished;
}
}
void Draw(double smoothratio) override
{
twod->ClearScreen();
int clock = (ticks + smoothratio) * 120 / GameTicRate;
twod->ClearScreen();
// Only translate if the image depends on the global palette.
auto tex = tileGetTexture(BETASCREEN, true);
int translation = tex->GetTexture()->GetImage()->UseGamePalette() ? TRANSLATION(Translation_BasePalettes, TITLEPAL) : 0;
DrawTexture(twod, tex, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
double scale = clamp(clock - 120, 0, 60) / 64.;
if (scale > 0.)
{
tex = tileGetTexture(DUKENUKEM, true);
translation = tex->GetTexture()->GetImage()->UseGamePalette() ? TRANSLATION(Translation_BasePalettes, TITLEPAL) : 0;
DrawTexture(twod, tileGetTexture(DUKENUKEM, true), 160, 104, DTA_FullscreenScale, FSMode_Fit320x200,
DTA_CenterOffsetRel, true, DTA_TranslationIndex, translation, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE);
}
scale = clamp(clock - 220, 0, 30) / 32.;
if (scale > 0.)
{
tex = tileGetTexture(THREEDEE, true);
translation = tex->GetTexture()->GetImage()->UseGamePalette() ? TRANSLATION(Translation_BasePalettes, TITLEPAL) : 0;
DrawTexture(twod, tileGetTexture(THREEDEE, true), 160, 129, DTA_FullscreenScale, FSMode_Fit320x200,
DTA_CenterOffsetRel, true, DTA_TranslationIndex, translation, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE);
}
if (isPlutoPak())
{
scale = (410 - clamp(clock, 280, 395)) / 16.;
if (scale > 0. && clock > 280)
{
tex = tileGetTexture(PLUTOPAKSPRITE + 1, true);
translation = tex->GetTexture()->GetImage()->UseGamePalette() ? TRANSLATION(Translation_BasePalettes, TITLEPAL) : 0;
DrawTexture(twod, tileGetTexture(PLUTOPAKSPRITE + 1, true), 160, 151, DTA_FullscreenScale, FSMode_Fit320x200,
DTA_CenterOffsetRel, true, DTA_TranslationIndex, translation, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE);
}
}
}
void OnDestroy() override
{
S_PlaySound(NITEVISION_ONOFF, CHAN_AUTO, CHANF_UI);
}
};
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// //
@ -327,6 +177,7 @@ void Logo_d(const CompletionFunc &completion)
#endif #endif
} }
#if 0 #if 0
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
@ -334,282 +185,6 @@ void Logo_d(const CompletionFunc &completion)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
class DEpisode1End1 : public DSkippableScreenJob
{
int bonuscnt = 0;
int bossani = -1;
int breatheani = -1;
bool breathebg = false;
static inline const int breathe_time[] = { 0, 30, 60, 90 };
static inline const int breathe_time2[] = { 30, 60, 90, 120 };
static inline const int breathe_tile[] = { VICTORY2, VICTORY3, VICTORY2, 0 };
static const int breathe_x = 176;
static const int breathe_y = 59;
static inline const int boss_time[] = { 0, 220, 260, 290, 320, 350, 350 };
static inline const int boss_time2[] = { 120, 260, 290, 320, 350, 380, 380 };
static inline const int boss_tile[] = { VICTORY4, VICTORY5, VICTORY6, VICTORY7, VICTORY8, VICTORY9, VICTORY9 };
static const int boss_x = 86;
static const int boss_y = 59;
public:
DEpisode1End1() : DSkippableScreenJob(fadein | fadeout) {}
void OnTick()
{
int currentclock = ticks * 120 / GameTicRate;
bossani = -1;
breathebg = false;
breatheani = -1;
// boss
if (currentclock > 390 && currentclock < 780)
{
for (int t = 0, tt = 0; t < 35; t +=5, tt++) if ((currentclock % 390) > boss_time[tt] && (currentclock % 390) <= boss_time2[tt])
{
if (t == 10 && bonuscnt == 1)
{
S_PlaySound(SHOTGUN_FIRE, CHAN_AUTO, CHANF_UI);
S_PlaySound(SQUISHED, CHAN_AUTO, CHANF_UI);
bonuscnt++;
}
bossani = tt;
}
}
// Breathe
if (currentclock < 450 || currentclock >= 750)
{
if (currentclock >= 750)
{
breathebg = true;
if (currentclock >= 750 && bonuscnt == 2)
{
S_PlaySound(DUKETALKTOBOSS, CHAN_AUTO, CHANF_UI);
bonuscnt++;
}
}
for (int t = 0, tt = 0; t < 20; t += 5, tt++)
if (breathe_tile[tt] && (currentclock % 120) > breathe_time[tt] && (currentclock % 120) <= breathe_time2[tt])
{
if (t == 5 && bonuscnt == 0)
{
S_PlaySound(BOSSTALKTODUKE, CHAN_AUTO, CHANF_UI);
bonuscnt++;
}
breatheani = tt;
}
}
}
void Draw(double) override
{
auto translation = TRANSLATION(Translation_BasePalettes, ENDINGPAL);
twod->ClearScreen();
DrawTexture(twod, tileGetTexture(VICTORY1, true), 0, 50, DTA_FullscreenScale, FSMode_Fit320x200,
DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal, DTA_TopLeft, true, TAG_DONE);
if (bossani != -1)
{
DrawTexture(twod, tileGetTexture(boss_tile[bossani], true), boss_x, boss_y, DTA_FullscreenScale, FSMode_Fit320x200,
DTA_TranslationIndex, translation, DTA_TopLeft, true, TAG_DONE);
}
if (breathebg)
{
DrawTexture(twod, tileGetTexture(VICTORY9, true), 86, 59, DTA_FullscreenScale, FSMode_Fit320x200,
DTA_TranslationIndex, translation, DTA_TopLeft, true, TAG_DONE);
}
if (breatheani != -1)
{
DrawTexture(twod, tileGetTexture(breathe_tile[breatheani], true), breathe_x, breathe_y, DTA_FullscreenScale, FSMode_Fit320x200,
DTA_TranslationIndex, translation, DTA_TopLeft, true, TAG_DONE);
}
}
};
class DE2EndScreen : public DImageScreen
{
public:
DE2EndScreen() : DImageScreen(E2ENDSCREEN, DScreenJob::fadein | DScreenJob::fadeout | DScreenJob::stopsound, 0x7fffffff, 0)
{}
void Start() override
{
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
}
};
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DEpisode3End : public DImageScreen
{
int sound = 0;
int64_t waittime = 0;
public:
FGameTexture* getTexture()
{
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:
DEpisode3End() : DImageScreen(getTexture(), fadein|fadeout, 0x7fffffff)
{
}
void Skipped() override
{
FX_StopAllSounds();
}
void OnTick() override
{
switch (sound)
{
case 0:
S_PlaySound(ENDSEQVOL3SND5, CHAN_AUTO, CHANF_UI);
sound++;
break;
case 1:
if (!S_CheckSoundPlaying(ENDSEQVOL3SND5))
{
S_PlaySound(ENDSEQVOL3SND6, CHAN_AUTO, CHANF_UI);
sound++;
}
break;
case 2:
if (!S_CheckSoundPlaying(ENDSEQVOL3SND6))
{
S_PlaySound(ENDSEQVOL3SND7, CHAN_AUTO, CHANF_UI);
sound++;
}
break;
case 3:
if (!S_CheckSoundPlaying(ENDSEQVOL3SND7))
{
S_PlaySound(ENDSEQVOL3SND8, CHAN_AUTO, CHANF_UI);
sound++;
}
break;
case 4:
if (!S_CheckSoundPlaying(ENDSEQVOL3SND8))
{
S_PlaySound(ENDSEQVOL3SND9, CHAN_AUTO, CHANF_UI);
sound++;
}
break;
case 5:
if (!S_CheckSoundPlaying(ENDSEQVOL3SND9))
{
sound++;
waittime = ticks + GameTicRate * (SoundEnabled() ? 1 : 5); // if sound is off this wouldn't wait without a longer delay here.
}
break;
case 6:
if (isPlutoPak())
{
if (ticks > waittime) state = finished;
}
break;
default:
break;
}
if (state != running) FX_StopAllSounds();
}
void OnDestroy() override
{
if (!isPlutoPak()) S_PlaySound(ENDSEQVOL3SND4, CHAN_AUTO, CHANF_UI);
}
};
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DEpisode4Text : public DSkippableScreenJob
{
public:
DEpisode4Text() : DSkippableScreenJob(fadein | fadeout) {}
void Draw(double) override
{
twod->ClearScreen();
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."));
}
void Start() override
{
S_PlaySound(ENDSEQVOL3SND4, CHAN_AUTO, CHANF_UI);
}
};
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DEpisode5End : public DImageScreen
{
int sound = 0;
public:
DEpisode5End() : DImageScreen(FIREFLYGROWEFFECT, fadein|fadeout|stopsound)
{
}
void OnTick() override
{
switch (sound)
{
case 0:
sound++;
break;
case 1:
S_PlaySound(E5L7_DUKE_QUIT_YOU, CHAN_AUTO, CHANF_UI);
sound++;
break;
default:
break;
}
}
};
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void bonussequence_d(int num, TArray<DScreenJob*>& jobs) static void bonussequence_d(int num, TArray<DScreenJob*>& jobs)
{ {
static const AnimSound cineov2sound[] = static const AnimSound cineov2sound[] =
@ -749,349 +324,6 @@ void doorders(const CompletionFunc& completion)
#endif #endif
} }
#if 0
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DDukeMultiplayerBonusScreen : public DSkippableScreenJob
{
int playerswhenstarted;
public:
DDukeMultiplayerBonusScreen(int pws) : DSkippableScreenJob(fadein|fadeout)
{
playerswhenstarted = pws;
}
void Start() override
{
S_PlayBonusMusic();
}
void Draw(double smoothratio) override
{
char tempbuf[32];
int currentclock = int((ticks + smoothratio) * 120 / GameTicRate);
twod->ClearScreen();
DrawTexture(twod, tileGetTexture(MENUSCREEN), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_Color, 0xff808080, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
DrawTexture(twod, tileGetTexture(INGAMEDUKETHREEDEE, true), 160, 34, DTA_FullscreenScale, FSMode_Fit320x200, DTA_CenterOffsetRel, true, TAG_DONE);
if (isPlutoPak())
DrawTexture(twod, tileGetTexture(PLUTOPAKSPRITE+2, true), 260, 36, DTA_FullscreenScale, FSMode_Fit320x200, DTA_CenterOffsetRel, true, TAG_DONE);
GameText(160, 58 + 2, GStrings("Multiplayer Totals"), 0, 0);
GameText(160, 58 + 10, currentLevel->DisplayName(), 0, 0);
GameText(160, 165, GStrings("Presskey"), 8 - int(sin(currentclock / 10.) * 8), 0);
int t = 0;
MiniText(38, 80, GStrings("Name"), 0, -1, 8);
MiniText(269+20, 80, GStrings("Kills"), 0, 1, 8);
for (int i = 0; i < playerswhenstarted; i++)
{
mysnprintf(tempbuf, 32, "%-4d", i + 1);
MiniText(92 + (i * 23), 80, tempbuf, 0, -1, 3);
}
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, PlayerName(i), 0, -1, ps[i].palookup);
for (int y = 0; y < playerswhenstarted; y++)
{
int frag = ps[i].frags[y];
if (i == y)
{
mysnprintf(tempbuf, 32, "%-4d", ps[y].fraggedself);
MiniText(92 + (y * 23), 90 + t, tempbuf, 0, -1, 2);
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, -1, 2);
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 = ps[i].frags[y];
yfragtotal += frag;
}
mysnprintf(tempbuf, 32, "%-4d", yfragtotal);
MiniText(92 + (y * 23), 96 + (8 * 7), tempbuf, 0, -1, 2);
}
MiniText(45, 96 + (8 * 7), GStrings("Deaths"), 0, -1, 8);
}
};
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DDukeLevelSummaryScreen : public DScreenJob
{
const char* lastmapname;
int gfx_offset;
int speech = -1;
int displaystate = 0;
int dukeAnimStart;
enum
{
printTimeText = 1,
printTimeVal = 2,
printKillsText = 4,
printKillsVal = 8,
printSecretsText = 16,
printSecretsVal = 32,
printStatsAll = 63,
dukeAnim = 64,
dukeWait = 128,
};
public:
DDukeLevelSummaryScreen() : DScreenJob(fadein | fadeout)
{
int vol = volfromlevelnum(currentLevel->levelNumber);
gfx_offset = BONUSSCREEN + ((vol == 1) ? 5 : 0);
lastmapname = currentLevel->DisplayName();
}
void FormatTime(int time, char* tempbuf)
{
mysnprintf(tempbuf, 32, "%02d:%02d", (time / (26 * 60)) % 60, (time / 26) % 60);
}
bool OnEvent(event_t* ev) override
{
if (ev->type == EV_KeyDown && !specialKeyEvent(ev))
{
if ((displaystate & printStatsAll) != printStatsAll)
{
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
displaystate = printStatsAll;
}
else if (!(displaystate & dukeAnim))
{
displaystate |= dukeAnim;
dukeAnimStart = ticks;
S_PlaySound(SHOTGUN_COCK, CHAN_AUTO, CHANF_UI);
static const uint16_t speeches[] = { BONUS_SPEECH1, BONUS_SPEECH2, BONUS_SPEECH3, BONUS_SPEECH4 };
speech = speeches[(rand() & 3)];
S_PlaySound(speech, CHAN_AUTO, CHANF_UI, 1);
}
return true;
}
return false;
}
void Start() override
{
S_PlayBonusMusic();
}
void OnTick() override
{
if ((displaystate & printStatsAll) != printStatsAll)
{
if (ticks == 15 * 3)
{
displaystate |= printTimeText;
}
else if (ticks == 15 * 4)
{
displaystate |= printTimeVal;
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
}
else if (ticks == 15 * 6)
{
displaystate |= printKillsText;
S_PlaySound(FLY_BY, CHAN_AUTO, CHANF_UI);
}
else if (ticks == 15 * 7)
{
displaystate |= printKillsVal;
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
}
else if (ticks == 15 * 9)
{
displaystate |= printSecretsText;
}
else if (ticks == 15 * 10)
{
displaystate |= printSecretsVal;
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
}
}
if (displaystate & dukeAnim)
{
if (ticks >= dukeAnimStart + 60)
{
displaystate ^= dukeAnim | dukeWait;
}
}
if (displaystate & dukeWait)
{
if (speech <= 0 || !S_CheckSoundPlaying(speech))
state = finished;
}
}
void PrintTime()
{
char tempbuf[32];
GameText(10, 59 + 9, GStrings("TXT_YourTime"), 0);
GameText(10, 69 + 9, GStrings("TXT_ParTime"), 0);
if (!isNamWW2GI())
GameText(10, 79 + 9, GStrings("TXT_3DRTIME"), 0);
if (displaystate & printTimeVal)
{
FormatTime(ps[myconnectindex].player_par, tempbuf);
GameText((320 >> 2) + 71, 59 + 9, tempbuf, 0);
FormatTime(currentLevel->parTime, tempbuf);
GameText((320 >> 2) + 71, 69 + 9, tempbuf, 0);
if (!isNamWW2GI())
{
FormatTime(currentLevel->designerTime, tempbuf);
GameText((320 >> 2) + 71, 79 + 9, tempbuf, 0);
}
}
}
void PrintKills()
{
char tempbuf[32];
GameText(10, 94 + 9, GStrings("TXT_EnemiesKilled"), 0);
GameText(10, 104 + 9, GStrings("TXT_EnemiesLeft"), 0);
if (displaystate & printKillsVal)
{
mysnprintf(tempbuf, 32, "%-3d", ps[myconnectindex].actors_killed);
GameText((320 >> 2) + 70, 94 + 9, tempbuf, 0);
if (ud.player_skill > 3)
{
mysnprintf(tempbuf, 32, "%s", GStrings("TXT_N_A"));
}
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);
}
GameText((320 >> 2) + 70, 104 + 9, tempbuf, 0);
}
}
void PrintSecrets()
{
char tempbuf[32];
GameText(10, 119 + 9, GStrings("TXT_SECFND"), 0);
GameText(10, 129 + 9, GStrings("TXT_SECMISS"), 0);
if (displaystate & printSecretsVal)
{
mysnprintf(tempbuf, 32, "%-3d", ps[myconnectindex].secret_rooms);
GameText((320 >> 2) + 70, 119 + 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, 129 + 9, tempbuf, 0);
}
}
void Draw(double) override
{
twod->ClearScreen();
DrawTexture(twod, tileGetTexture(gfx_offset, true), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
GameText(160, 190, GStrings("PRESSKEY"), 8 - int(sin(ticks * 12 / GameTicRate) * 8), 0);
if (displaystate & printTimeText)
{
PrintTime();
}
if (displaystate & printKillsText)
{
PrintKills();
}
if (displaystate & printSecretsText)
{
PrintSecrets();
}
if (displaystate & dukeAnim)
{
switch (((ticks - dukeAnimStart) >> 2) % 15)
{
case 0:
case 1:
case 4:
case 5:
DrawTexture(twod, tileGetTexture(gfx_offset + 3), 199, 31, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TopLeft, true, TAG_DONE);
break;
case 2:
case 3:
DrawTexture(twod, tileGetTexture(gfx_offset + 4), 199, 31, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TopLeft, true, TAG_DONE);
break;
}
}
else if (!(displaystate & dukeWait))
{
switch((ticks >> 3) & 3)
{
case 1:
case 3:
DrawTexture(twod, tileGetTexture(gfx_offset + 1), 199, 31, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TopLeft, true, TAG_DONE);
break;
case 2:
DrawTexture(twod, tileGetTexture(gfx_offset + 2), 199, 31, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TopLeft, true, TAG_DONE);
break;
}
}
if (lastmapname) BigText(160, 20 - 6, lastmapname);
BigText(160, 36 - 6, GStrings("Completed"));
}
};
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// //
@ -1175,28 +407,6 @@ void e4intro(const CompletionFunc& completion)
} }
#if 0 #if 0
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DDukeLoadScreen : public DScreenJob
{
MapRecord* rec;
public:
DDukeLoadScreen(MapRecord *maprec) : DScreenJob(0), rec(maprec) {}
void Draw(double) override
{
twod->ClearScreen();
DrawTexture(twod, tileGetTexture(LOADSCREEN), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
BigText(160, 90, (rec->flags & MI_USERMAP)? GStrings("TXT_LOADUM") : GStrings("TXT_LOADING"));
BigText(160, 114, rec->DisplayName());
}
};
void loadscreen_d(MapRecord *rec, CompletionFunc func) void loadscreen_d(MapRecord *rec, CompletionFunc func)
{ {
@ -1209,7 +419,7 @@ void loadscreen_d(MapRecord *rec, CompletionFunc func)
void PrintPaused_d() void PrintPaused_d()
{ {
//BigText(160, 100, GStrings("Game Paused")); BigText(160, 100, GStrings("Game Paused"));
} }

View file

@ -123,7 +123,6 @@ void InitFonts_r()
} }
#if 0
//========================================================================== //==========================================================================
// //
// wrappers around DrawText to allow easier reuse of the old code. // wrappers around DrawText to allow easier reuse of the old code.
@ -139,22 +138,6 @@ static void BigText(double x, double y, const char* text, int align, double alph
DrawText(twod, BigFont, CR_UNTRANSLATED, x, y - 12, text, DTA_FullscreenScale, FSMode_Fit320x200, DTA_ScaleX, 0.4, DTA_ScaleY, 0.4, DTA_Alpha, alpha, TAG_DONE); DrawText(twod, BigFont, CR_UNTRANSLATED, x, y - 12, text, DTA_FullscreenScale, FSMode_Fit320x200, 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);
DrawText(twod, SmallFont, CR_UNDEFINED, x, y + 2, t, DTA_FullscreenScale, FSMode_Fit640x400, DTA_TranslationIndex, TRANSLATION(Translation_Remap, trans), DTA_Color, shadeToLight(shade), 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);
DrawText(twod, SmallFont2, CR_UNDEFINED, x, y, t, DTA_FullscreenScale, FSMode_Fit640x400, DTA_TranslationIndex, TRANSLATION(Translation_Remap, trans), DTA_Color, shadeToLight(shade), TAG_DONE);
}
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
@ -253,344 +236,6 @@ static void bonussequence_r(int num, TArray<DScreenJob*>& jobs)
} }
#endif #endif
#if 0
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DRRMultiplayerBonusScreen : public DScreenJob
{
int playerswhenstarted;
public:
DRRMultiplayerBonusScreen(int pws) : DScreenJob(fadein | fadeout)
{
playerswhenstarted = pws;
}
void Start() override
{
S_PlayBonusMusic();
}
void Draw(double) override
{
char tempbuf[32];
twod->ClearScreen();
DrawTexture(twod, tileGetTexture(MENUSCREEN), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_Color, 0xff808080, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
double scale = 0.36;
DrawTexture(twod, tileGetTexture(INGAMEDUKETHREEDEE, true), 160, 34, DTA_FullscreenScale, FSMode_Fit320x200,
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, PlayerName(i), 0, -1, ps[i].palookup);
for (int y = 0; y < playerswhenstarted; y++)
{
int frag = ps[i].frags[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 = ps[i].frags[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);
}
};
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DRRLevelSummaryScreen : public DScreenJob
{
const char* lastmapname;
int gfx_offset;
int displaystate = 0;
int speech = -1;
int exitSoundStart;
enum
{
printTimeText = 1,
printTimeVal = 2,
printKillsText = 4,
printKillsVal = 8,
printSecretsText = 16,
printSecretsVal = 32,
printStatsAll = 63,
exitSound = 64,
exitWait = 128,
};
public:
DRRLevelSummaryScreen(bool dofadeout = true) : DScreenJob(dofadeout? (fadein | fadeout) : fadein)
{
if (currentLevel->flags & MI_USERMAP)
gfx_offset = BONUSPIC01;
else if (!isRRRA())
gfx_offset = BONUSPIC01 + clamp((currentLevel->levelNumber / 1000) * 7 + (currentLevel->levelNumber % 1000), 0, 13);
else
gfx_offset = LEVELMAP01 + clamp((currentLevel->levelNumber / 1000) * 7 + (currentLevel->levelNumber % 1000), 0, 13);
lastmapname = currentLevel->DisplayName();
}
void FormatTime(int time, char* tempbuf)
{
mysnprintf(tempbuf, 32, "%02d:%02d", (time / (26 * 60)) % 60, (time / 26) % 60);
}
bool OnEvent(event_t* ev) override
{
if (ev->type == EV_KeyDown && !specialKeyEvent(ev))
{
if ((displaystate & printStatsAll) != printStatsAll)
{
S_PlaySound(404, CHAN_AUTO, CHANF_UI);
displaystate = printStatsAll;
}
else if (!(displaystate & exitSound))
{
displaystate |= exitSound;
exitSoundStart = ticks;
S_PlaySound(425, CHAN_AUTO, CHANF_UI);
speech = BONUS_SPEECH1 + (rand() & 3);
S_PlaySound(speech, CHAN_AUTO, CHANF_UI);
}
return true;
}
return false;
}
void Start() override
{
S_PlayBonusMusic();
}
void OnTick() override
{
if ((displaystate & printStatsAll) != printStatsAll)
{
if (ticks == 15 * 3)
{
displaystate |= printTimeText;
}
else if (ticks == 15 * 4)
{
displaystate |= printTimeVal;
S_PlaySound(404, CHAN_AUTO, CHANF_UI);
}
else if (ticks == 15 * 6)
{
displaystate |= printKillsText;
}
else if (ticks == 15 * 7)
{
displaystate |= printKillsVal;
S_PlaySound(404, CHAN_AUTO, CHANF_UI);
}
else if (ticks == 15 * 9)
{
displaystate |= printSecretsText;
}
else if (ticks == 15 * 10)
{
displaystate |= printSecretsVal;
S_PlaySound(404, CHAN_AUTO, CHANF_UI);
}
}
if (displaystate & exitSound)
{
if (ticks >= exitSoundStart + 60)
{
displaystate ^= exitSound | exitWait;
}
}
if (displaystate & exitWait)
{
if (speech <= 0 || !S_CheckSoundPlaying(speech))
state = finished;
}
}
void PrintTime()
{
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 (displaystate & printTimeVal)
{
FormatTime(ps[myconnectindex].player_par, tempbuf);
BigText(191, 48, tempbuf, -1);
FormatTime(currentLevel->parTime, tempbuf);
BigText(191, 64, tempbuf, -1);
FormatTime(currentLevel->designerTime, tempbuf);
BigText(191, 80, tempbuf, -1);
}
}
void PrintKills()
{
char tempbuf[32];
BigText(30, 112, GStrings("TXT_VarmintsKilled"), -1);
BigText(30, 128, GStrings("TXT_VarmintsLeft"), -1);
if (displaystate & printKillsVal)
{
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()
{
char tempbuf[32];
BigText(30, 144, GStrings("TXT_SECFND"), -1);
BigText(30, 160, GStrings("TXT_SECMISS"), -1);
if (displaystate & printSecretsVal)
{
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);
}
}
void Draw(double) override
{
twod->ClearScreen();
DrawTexture(twod, tileGetTexture(gfx_offset, true), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_LegacyRenderStyle, STYLE_Normal, TAG_DONE);
if (lastmapname) BigText(80, 16, lastmapname, -1);
BigText(15, 192, GStrings("PRESSKEY"), -1);
if (displaystate & printTimeText)
{
PrintTime();
}
if (displaystate & printKillsText)
{
PrintKills();
}
if (displaystate & printSecretsText)
{
PrintSecrets();
}
}
};
class DRRRAEndOfGame : public DSkippableScreenJob
{
public:
DRRRAEndOfGame() : DSkippableScreenJob(fadein|fadeout)
{
}
void Skipped() override
{
S_StopSound(35);
}
void Start() override
{
S_PlaySound(35, CHAN_AUTO, CHANF_UI);
}
void OnTick() override
{
if (!S_CheckSoundPlaying(35) && ticks > 15 * GameTicRate) state = finished; // make sure it stays, even if sound is off.
}
void Draw(double) override
{
auto tex = tileGetTexture(ENDGAME + ((ticks >> 2) & 1));
DrawTexture(twod, tex, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, TAG_DONE);
}
};
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
@ -647,22 +292,6 @@ void dobonus_r(int bonusonly, const CompletionFunc& completion)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
class DRRLoadScreen : public DScreenJob
{
MapRecord* rec;
public:
DRRLoadScreen(MapRecord* maprec) : DScreenJob(0), rec(maprec) {}
void Draw(double) override
{
DrawTexture(twod, tileGetTexture(LOADSCREEN), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, 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);
}
};
void loadscreen_r(MapRecord* rec, CompletionFunc func) void loadscreen_r(MapRecord* rec, CompletionFunc func)
{ {
@ -675,7 +304,7 @@ void loadscreen_r(MapRecord* rec, CompletionFunc func)
void PrintPaused_r() void PrintPaused_r()
{ {
//BigText(160, 100, GStrings("Game Paused"), 0); BigText(160, 100, GStrings("Game Paused"), 0);
} }

View file

@ -0,0 +1,58 @@
//-------------------------------------------------------------------------
/*
Copyright (C) 1996, 2003 - 3D Realms Entertainment
Copyright (C) 2020-2021 Christoph Oelckers
This file is part of Raze.
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
( not much left of the original code, though... ;) )
*/
//-------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DukeIntro : ScreenJobRunner
{
void Init()
{
Raze.StopMusic();
Raze.StopAllSounds();
if (!userConfig.nologo)
{
if (!Raze.isShareware())
{
Array<int> soundinfo;
soundinfo.Push(1);
soundinfo.Push(DukeSnd.FLY_BY+1);
soundinfo.Push(19);
soundinfo.Push(DukeSnd.PIPEBOMB_EXPLODE+1);
jobs.Push(MoviePlayerJob.CreateWithSoundinfo("logo.anm", soundinfo, 9, 9, 9));
}
if (!Raze.isNam()) jobs.Push(new("DRealmsScreen").Init());
}
jobs.Push(new("DukeTitleScreen").Init());
}
}

View file

@ -1,3 +1,31 @@
//-------------------------------------------------------------------------
/*
Copyright (C) 1996, 2003 - 3D Realms Entertainment
Copyright (C) 2020-2021 Christoph Oelckers
This file is part of Raze.
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
( not much left of the original code, though... ;) )
*/
//-------------------------------------------------------------------------
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -8,9 +36,10 @@
class DRealmsScreen : SkippableScreenJob class DRealmsScreen : SkippableScreenJob
{ {
void Init() ScreenJob Init()
{ {
Super.Init(fadein | fadeout); Super.Init(fadein | fadeout);
return self;
} }
override void Start() override void Start()
@ -43,10 +72,11 @@ class TitleScreen : SkippableScreenJob
{ {
int soundanm; int soundanm;
void Init() ScreenJob Init()
{ {
Super.Init(fadein | fadeout); Super.Init(fadein | fadeout);
soundanm = 0; soundanm = 0;
return self;
} }
override void Start() override void Start()
@ -154,13 +184,14 @@ class Episode1End1 : SkippableScreenJob
const boss_x = 86; const boss_x = 86;
const boss_y = 59; const boss_y = 59;
void Init() ScreenJob Init()
{ {
bonuscnt = 0; bonuscnt = 0;
breathebg = false; breathebg = false;
bossani.SetInvalid(); bossani.SetInvalid();
breatheani.SetInvalid(); breatheani.SetInvalid();
Super.Init(fadein | fadeout); Super.Init(fadein | fadeout);
return self;
} }
@ -259,9 +290,10 @@ class Episode1End1 : SkippableScreenJob
class E2EndScreen : ImageScreen class E2EndScreen : ImageScreen
{ {
void Init() ScreenJob Init()
{ {
Super.InitNamed("E2ENDSCREEN", fadein | fadeout | stopsound, 0x7fffffff, 0); Super.InitNamed("E2ENDSCREEN", fadein | fadeout | stopsound, 0x7fffffff, 0);
return self;
} }
override void Start() override void Start()
@ -281,11 +313,12 @@ class Episode3End : ImageScreen
int soundstate; int soundstate;
int finishtime; int finishtime;
void Init() ScreenJob Init()
{ {
Super.InitNamed("radlogo.anm", fadein|fadeout, 0x7fffffff); Super.InitNamed("radlogo.anm", fadein|fadeout, 0x7fffffff);
soundstate = 0; soundstate = 0;
finishtime = 0; finishtime = 0;
return self;
} }
override void OnSkip() override void OnSkip()
@ -369,9 +402,10 @@ class Episode3End : ImageScreen
class Episode4Text : SkippableScreenJob class Episode4Text : SkippableScreenJob
{ {
void Init() ScreenJob Init()
{ {
Super.Init(fadein|fadeout); Super.Init(fadein|fadeout);
return self;
} }
@ -399,9 +433,10 @@ class Episode4Text : SkippableScreenJob
class Episode5End : ImageScreen class Episode5End : ImageScreen
{ {
void Init() ScreenJob Init()
{ {
Super.InitNamed("FIREFLYGROWEFFECT", fadein|fadeout|stopsound); Super.InitNamed("FIREFLYGROWEFFECT", fadein|fadeout|stopsound);
return self;
} }
override void OnTick() override void OnTick()
@ -420,10 +455,11 @@ class DukeMultiplayerBonusScreen : SkippableScreenJob
{ {
int playerswhenstarted; int playerswhenstarted;
void Init(int pws) ScreenJob Init(int pws)
{ {
Super.Init(fadein|fadeout); Super.Init(fadein|fadeout);
playerswhenstarted = pws; playerswhenstarted = pws;
return self;
} }
override void Start() override void Start()
@ -545,7 +581,7 @@ class DukeLevelSummaryScreen : SummaryScreenBase
} }
void Init() ScreenJob Init()
{ {
Super.Init(fadein | fadeout); Super.Init(fadein | fadeout);
int vol = level.volumeNum(); int vol = level.volumeNum();
@ -559,7 +595,7 @@ class DukeLevelSummaryScreen : SummaryScreenBase
lastmapname = level.DisplayName(); lastmapname = level.DisplayName();
speech = -1; speech = -1;
displaystate = 0; displaystate = 0;
return self;
} }
override bool OnEvent(InputEvent ev) override bool OnEvent(InputEvent ev)
@ -783,7 +819,7 @@ class RRLevelSummaryScreen : SummaryScreenBase
} }
void Init(bool dofadeout = true) ScreenJob Init(bool dofadeout = true)
{ {
Super.Init(dofadeout? (fadein | fadeout) : fadein); Super.Init(dofadeout? (fadein | fadeout) : fadein);
String s; String s;
@ -796,6 +832,7 @@ class RRLevelSummaryScreen : SummaryScreenBase
lastmapname = level.DisplayName(); lastmapname = level.DisplayName();
texBg = TexMan.CheckForTexture(s); texBg = TexMan.CheckForTexture(s);
return self;
} }
override bool OnEvent(InputEvent ev) override bool OnEvent(InputEvent ev)
@ -960,9 +997,10 @@ class RRLevelSummaryScreen : SummaryScreenBase
class RRRAEndOfGame : SkippableScreenJob class RRRAEndOfGame : SkippableScreenJob
{ {
void Init() ScreenJob Init()
{ {
Super.Init(fadein|fadeout); Super.Init(fadein|fadeout);
return self;
} }
override void OnSkip() override void OnSkip()
@ -997,10 +1035,11 @@ class DukeLoadScreen : ScreenJob
{ {
MapRecord rec; MapRecord rec;
void Init(MapRecord maprec) ScreenJob Init(MapRecord maprec)
{ {
Super.Init(); Super.Init();
rec = maprec; rec = maprec;
return self;
} }
override void Draw(double sr) override void Draw(double sr)

View file

@ -98,11 +98,17 @@ class BlackScreen : ScreenJob
int wait; int wait;
bool cleared; bool cleared;
void Init(int w, int flags = 0) ScreenJob Init(int w, int flags = 0)
{ {
Super.Init(flags & ~(fadein|fadeout)); Super.Init(flags & ~(fadein|fadeout));
wait = w; wait = w;
cleared = false; cleared = false;
return self;
}
static ScreenJob Create(int w, int flags = 0)
{
return new("BlackScreen").Init(w, flags);
} }
override void OnTick() override void OnTick()
@ -135,23 +141,36 @@ class ImageScreen : SkippableScreenJob
bool cleared; bool cleared;
TextureID texid; TextureID texid;
void Init(TextureID tile, int fade = fadein | fadeout, int wait = 3000, int translation = 0) ScreenJob Init(TextureID tile, int fade = fadein | fadeout, int wait = 3000, int translation = 0)
{ {
Super.Init(fade); Super.Init(fade);
waittime = wait; waittime = wait;
texid = tile; texid = tile;
trans = translation; trans = translation;
cleared = false; cleared = false;
return self;
} }
void InitNamed(String tex, int fade = fadein | fadeout, int wait = 3000, int translation = 0) ScreenJob InitNamed(String tex, int fade = fadein | fadeout, int wait = 3000, int translation = 0)
{ {
Super.Init(fade); Super.Init(fade);
waittime = wait; waittime = wait;
texid = TexMan.CheckForTexture(tex, TexMan.Type_Any, TexMan.TryAny | TexMan.ForceLookup); texid = TexMan.CheckForTexture(tex, TexMan.Type_Any, TexMan.TryAny | TexMan.ForceLookup);
trans = translation; trans = translation;
cleared = false; cleared = false;
return self;
} }
static ScreenJob Create(TextureID tile, int fade = fadein | fadeout, int wait = 3000, int translation = 0)
{
return new("ImageScreen").Init(tile, fade, wait, translation);
}
static ScreenJob CreateNamed(String tex, int fade = fadein | fadeout, int wait = 3000, int translation = 0)
{
return new("ImageScreen").InitNamed(tex, fade, wait, translation);
}
override void OnTick() override void OnTick()
{ {
if (cleared) if (cleared)
@ -209,15 +228,15 @@ class SummaryScreenBase : ScreenJob
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
struct AnmControl // ANM has no internal timing and sound info. Ugh...
{
Array<int> sounds;
int frameticks[3]; // first and last frame have their own durations.
}
struct MoviePlayer native struct MoviePlayer native
{ {
native static MoviePlayer OpenMovie(String filename, AnmControl ans, bool nosoundcutoff, out String error); enum EMovieFlags
{
NOSOUNDCUTOFF = 1,
FIXEDVIEWPORT = 2, // Forces fixed 640x480 screen size like for Blood's intros.
}
native static MoviePlayer Create(String filename, Array<int> soundinfo, int flags, int frametime, int firstframetime, int lastframetime);
native void Start(); native void Start();
native bool Frame(double clock); native bool Frame(double clock);
native bool Destroy(); native bool Destroy();
@ -234,10 +253,30 @@ class MoviePlayerJob : SkippableScreenJob
MoviePlayer player; MoviePlayer player;
bool started; bool started;
void Init(MoviePlayer mp) ScreenJob Init(MoviePlayer mp)
{ {
player = mp; player = mp;
pausable = false; pausable = false;
return self;
}
static ScreenJob CreateWithSoundInfo(String filename, Array<int> soundinfo, int flags, int frametime, int firstframetime = -1, int lastframetime = -1)
{
let movie = MoviePlayer.Create(filename, soundinfo, flags, frametime, firstframetime, lastframetime);
if (movie) return new("MoviePlayerJob").Init(movie);
return BlackScreen.Create(1); // do not return null.
}
static ScreenJob Create(String filename, int flags, int frametime = -1)
{
Array<int> empty;
return CreateWithSoundInfo(filename, empty, flags, frametime);
}
static ScreenJob CreateWithSound(String filename, Sound soundname, int flags, int frametime = -1)
{
Array<int> empty;
empty.Push(1);
empty.Push(int(soundname));
return CreateWithSoundInfo(filename, empty, flags, frametime);
} }
override void Draw(double smoothratio) override void Draw(double smoothratio)