ref: 7110aba73616e4f84b933a0db1ff96c4c22a9d6f
dir: /f_finale.c/
// F_finale.c
#include "h2stdinc.h"
#include <ctype.h>
#include "doomdef.h"
#include "soundst.h"
#include "v_compat.h"
#define TEXTSPEED 3
#define TEXTWAIT 250
#ifdef RENDER3D
#define V_DrawPatch(x,y,p) OGL_DrawPatch((x),(y),(p))
#define V_DrawRawScreen(a) OGL_DrawRawScreen((a))
#endif
extern boolean viewactive;
extern boolean MenuActive;
extern boolean askforquit;
static int finalestage; /* 0 = text, 1 = art screen */
static int finalecount;
static int finaletextcount;
static boolean underwater_init;
static int nextscroll;
static int scroll_yval;
static int FontABaseLump;
static const char *e1text = E1TEXT;
static const char *e2text = E2TEXT;
static const char *e3text = E3TEXT;
static const char *e4text = E4TEXT;
static const char *e5text = E5TEXT;
static const char *finaletext;
static const char *finaleflat;
static void F_TextWrite (void);
static void F_DrawBackground(void);
static void F_DemonScroll(void);
static void F_DrawUnderwater(void);
static void F_InitUnderWater(void);
static void F_KillUnderWater(void);
void F_StartFinale (void)
{
gameaction = ga_nothing;
gamestate = GS_FINALE;
viewactive = false;
automapactive = false;
players[consoleplayer].messageTics = 1;
players[consoleplayer].message = NULL;
switch (gameepisode)
{
case 1:
finaleflat = "FLOOR25";
finaletext = e1text;
break;
case 2:
finaleflat = "FLATHUH1";
finaletext = e2text;
break;
case 3:
finaleflat = "FLTWAWA2";
finaletext = e3text;
break;
case 4:
finaleflat = "FLOOR28";
finaletext = e4text;
break;
case 5:
finaleflat = "FLOOR08";
finaletext = e5text;
break;
}
finalestage = 0;
finalecount = 0;
finaletextcount = strlen(finaletext)*TEXTSPEED + TEXTWAIT;
#ifndef RENDER3D
scroll_yval = 0;
#else
scroll_yval = 200;
#endif
nextscroll = 0;
underwater_init = false;
FontABaseLump = W_GetNumForName("FONTA_S") + 1;
S_StartSong(mus_cptd, true);
}
boolean F_Responder (event_t *event)
{
if (event->type != ev_keydown)
{
return false;
}
if (finalestage == 1 && gameepisode == 2)
{
/* we're showing the water pic,
* make any key kick to demo mode
*/
finalestage++;
F_KillUnderWater();
return true;
}
return false;
}
void F_Ticker (void)
{
finalecount++;
if (!finalestage && finalecount > finaletextcount)
{
finalecount = 0;
finalestage = 1;
}
}
static void F_TextWrite (void)
{
int count;
const char *ch;
int c;
int cx, cy;
patch_t *w;
int width;
F_DrawBackground();
cx = 20;
cy = 5;
ch = finaletext;
count = (finalecount - 10)/TEXTSPEED;
if (count < 0)
count = 0;
for ( ; count; count--)
{
c = *ch++;
if (!c)
break;
if (c == '\n')
{
cx = 20;
cy += 9;
continue;
}
c = toupper(c);
if (c < 33)
{
cx += 5;
continue;
}
w = (patch_t *) W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE);
width = SHORT(w->width);
if (cx + width > SCREENWIDTH)
break;
#ifdef RENDER3D
OGL_DrawPatch (cx, cy, FontABaseLump + c - 33);
#else
V_DrawPatch(cx, cy, w);
#endif
cx += width;
}
}
#if defined(RENDER3D)
static void F_DrawBackground(void)
{
/* erase the entire screen to a tiled background.
*/
OGL_SetFlat (R_FlatNumForName(finaleflat));
OGL_DrawRectTiled(0, 0, SCREENWIDTH, SCREENHEIGHT, 64, 64);
}
static void F_DemonScroll(void)
{
if (finalecount < 70)
{
OGL_DrawRawScreen(W_GetNumForName("FINAL1"));
nextscroll = finalecount;
return;
}
if (finalecount >= nextscroll && scroll_yval > 0)
--scroll_yval;
if (scroll_yval > 0)
{
OGL_DrawRawScreenOfs(W_GetNumForName("FINAL2"), 0, -scroll_yval);
OGL_DrawRawScreenOfs(W_GetNumForName("FINAL1"), 0, 200 - scroll_yval);
if (finalecount >= nextscroll)
nextscroll = finalecount + 2; // + 3;
}
else
{
OGL_DrawRawScreen(W_GetNumForName("FINAL2"));
}
}
static void F_InitUnderWater(void)
{
OGL_SetPaletteLump("E2PAL");
}
static void F_KillUnderWater(void)
{
OGL_SetPaletteLump("PLAYPAL");
}
static void F_DrawUnderwater(void)
{
switch (finalestage)
{
case 1:
paused = false;
MenuActive = false;
askforquit = false;
if (!underwater_init)
{
underwater_init = true;
F_InitUnderWater();
}
OGL_DrawRawScreen(W_GetNumForName("E2END"));
break;
case 2:
OGL_DrawRawScreen(W_GetNumForName("TITLE"));
break;
}
}
#else /* RENDER3D */
static void F_DrawBackground(void)
{
/* erase the entire screen to a tiled background.
*/
int x, y;
byte *src, *dest;
src = (byte *) W_CacheLumpName(finaleflat, PU_CACHE);
dest = screens;
for (y = 0; y < SCREENHEIGHT; y++)
{
for (x = 0; x < SCREENWIDTH/64; x++)
{
memcpy (dest, src + ((y & 63)<<6), 64);
dest += 64;
}
if (SCREENWIDTH & 63)
{
memcpy (dest, src + ((y & 63)<<6), SCREENWIDTH & 63);
dest += (SCREENWIDTH & 63);
}
}
}
static void F_DemonScroll(void)
{
byte *p1, *p2;
if (finalecount < nextscroll)
{
return;
}
p1 = (byte *) W_CacheLumpName("FINAL1", PU_LEVEL);
p2 = (byte *) W_CacheLumpName("FINAL2", PU_LEVEL);
if (finalecount < 70)
{
memcpy(screens, p1, SCREENHEIGHT*SCREENWIDTH);
nextscroll = finalecount;
return;
}
if (scroll_yval < 64000)
{
memcpy(screens, p2 + SCREENHEIGHT*SCREENWIDTH - scroll_yval, scroll_yval);
memcpy(screens + scroll_yval, p1, SCREENHEIGHT*SCREENWIDTH - scroll_yval);
scroll_yval += SCREENWIDTH;
nextscroll = finalecount + 3;
}
else
{
memcpy(screens, p2, SCREENWIDTH*SCREENHEIGHT);
}
}
static void F_InitUnderWater(void)
{
# if defined(__WATCOMC__) && defined(_DOS)
memset((byte *)0xa0000, 0, SCREENWIDTH * SCREENHEIGHT); /* pcscreen */
# endif /* DOS */
I_SetPalette((byte *)W_CacheLumpName("E2PAL", PU_CACHE));
}
static void F_KillUnderWater(void)
{
# if defined(__WATCOMC__) && defined(_DOS)
memset((byte *)0xa0000, 0, SCREENWIDTH * SCREENHEIGHT); /* pcscreen */
memset(screen, 0, SCREENWIDTH * SCREENHEIGHT);
# endif /* DOS */
I_SetPalette((byte *)W_CacheLumpName("PLAYPAL", PU_CACHE));
}
static void F_DrawUnderwater(void)
{
switch (finalestage)
{
case 1:
paused = false;
MenuActive = false;
askforquit = false;
if (!underwater_init)
{
underwater_init = true;
F_InitUnderWater();
/* draw underwater picture only once during finalestage 1,
* no need to update it thereafter. */
V_DrawRawScreen((byte *)W_CacheLumpName("E2END", PU_CACHE));
}
break;
case 2:
V_DrawRawScreen((byte *) W_CacheLumpName("TITLE", PU_CACHE));
break;
}
}
#endif /* ! RENDER3D */
void F_Drawer(void)
{
UpdateState |= I_FULLSCRN;
if (!finalestage)
F_TextWrite ();
else
{
switch (gameepisode)
{
case 1:
if (shareware)
V_DrawRawScreen((BYTE_REF) WR_CacheLumpName("ORDER", PU_CACHE));
else
V_DrawRawScreen((BYTE_REF) WR_CacheLumpName("CREDIT", PU_CACHE));
break;
case 2:
F_DrawUnderwater();
break;
case 3:
F_DemonScroll();
break;
case 4: /* Just show credits screen for extended episodes */
case 5:
V_DrawRawScreen((BYTE_REF) WR_CacheLumpName("CREDIT", PU_CACHE));
break;
}
}
}