ref: 6528c14df3fa13bd3d5aed1e715205975b724f14
dir: /src/strife/f_finale.c/
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 1996 Rogue Entertainment / Velocity, Inc.
// Copyright(C) 2005 Simon Howard
// Copyright(C) 2010 James Haley, Samuel Villareal
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
// DESCRIPTION:
// Game completion, final screen animation.
//
// [STRIFE] Module marked finished 2010-09-13 22:56
//
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <ctype.h>
// Functions.
#include "deh_main.h"
#include "i_system.h"
#include "i_swap.h"
#include "z_zone.h"
#include "v_video.h"
#include "w_wad.h"
#include "s_sound.h"
// Data.
#include "d_main.h"
#include "dstrings.h"
#include "sounds.h"
#include "doomstat.h"
#include "r_state.h"
#include "p_dialog.h" // [STRIFE]
typedef enum
{
F_STAGE_TEXT,
F_STAGE_ARTSCREEN,
F_STAGE_CAST,
} finalestage_t;
// ?
//#include "doomstat.h"
//#include "r_local.h"
//#include "f_finale.h"
// Stage of animation:
finalestage_t finalestage;
unsigned int finalecount;
// haleyjd 09/12/10: [STRIFE] Slideshow variables
char *slideshow_panel;
unsigned int slideshow_tics;
int slideshow_state;
// haleyjd 09/13/10: [STRIFE] All this is unused.
/*
#define TEXTSPEED 3
#define TEXTWAIT 250
typedef struct
{
GameMission_t mission;
int episode, level;
char *background;
char *text;
} textscreen_t;
static textscreen_t textscreens[] =
{
{ doom, 1, 8, "FLOOR4_8", E1TEXT},
{ doom, 2, 8, "SFLR6_1", E2TEXT},
{ doom, 3, 8, "MFLR8_4", E3TEXT},
{ doom, 4, 8, "MFLR8_3", E4TEXT},
{ doom2, 1, 6, "SLIME16", C1TEXT},
{ doom2, 1, 11, "RROCK14", C2TEXT},
{ doom2, 1, 20, "RROCK07", C3TEXT},
{ doom2, 1, 30, "RROCK17", C4TEXT},
{ doom2, 1, 15, "RROCK13", C5TEXT},
{ doom2, 1, 31, "RROCK19", C6TEXT},
{ pack_tnt, 1, 6, "SLIME16", T1TEXT},
{ pack_tnt, 1, 11, "RROCK14", T2TEXT},
{ pack_tnt, 1, 20, "RROCK07", T3TEXT},
{ pack_tnt, 1, 30, "RROCK17", T4TEXT},
{ pack_tnt, 1, 15, "RROCK13", T5TEXT},
{ pack_tnt, 1, 31, "RROCK19", T6TEXT},
{ pack_plut, 1, 6, "SLIME16", P1TEXT},
{ pack_plut, 1, 11, "RROCK14", P2TEXT},
{ pack_plut, 1, 20, "RROCK07", P3TEXT},
{ pack_plut, 1, 30, "RROCK17", P4TEXT},
{ pack_plut, 1, 15, "RROCK13", P5TEXT},
{ pack_plut, 1, 31, "RROCK19", P6TEXT},
};
char* finaletext;
char* finaleflat;
*/
void F_StartCast (void);
void F_CastTicker (void);
boolean F_CastResponder (event_t *ev);
void F_CastDrawer (void);
// [STRIFE] - Slideshow states enumeration
enum
{
// Exit states
SLIDE_EXITHACK = -99, // Hacky exit - start a new dialog
SLIDE_EXIT = -1, // Exit to next finale state
SLIDE_CHOCO = -2, // haleyjd: This state is Choco-specific... see below.
// Unknown
SLIDE_UNKNOWN = 0, // Dunno what it's for, possibly unused
// MAP03 - Macil's Programmer exposition
SLIDE_PROGRAMMER1 = 1,
SLIDE_PROGRAMMER2,
SLIDE_PROGRAMMER3,
SLIDE_PROGRAMMER4, // Next state = -99
// MAP10 - Macil's Sigil exposition
SLIDE_SIGIL1 = 5,
SLIDE_SIGIL2,
SLIDE_SIGIL3,
SLIDE_SIGIL4, // Next state = -99
// MAP29 - Endings
// Good Ending
SLIDE_GOODEND1 = 10,
SLIDE_GOODEND2,
SLIDE_GOODEND3,
SLIDE_GOODEND4, // Next state = -1
// Bad Ending
SLIDE_BADEND1 = 14,
SLIDE_BADEND2,
SLIDE_BADEND3, // Next state = -1
// Blah Ending
SLIDE_BLAHEND1 = 17,
SLIDE_BLAHEND2,
SLIDE_BLAHEND3 // Next state = -1
};
//
// F_StartFinale
//
// [STRIFE]
// haleyjd 09/13/10: Modified to drive slideshow sequences.
//
void F_StartFinale (void)
{
patch_t *panel;
gameaction = ga_nothing;
gamestate = GS_FINALE;
viewactive = false;
automapactive = false;
wipegamestate = -1; // [STRIFE]
// [STRIFE] Setup the slide show
slideshow_panel = DEH_String("PANEL0");
panel = (patch_t *)W_CacheLumpName(slideshow_panel, PU_CACHE);
V_DrawPatch(0, 0, panel);
switch(gamemap)
{
case 3: // Macil's exposition on the Programmer
slideshow_state = SLIDE_PROGRAMMER1;
break;
case 9: // Super hack for death of Programmer
slideshow_state = SLIDE_EXITHACK;
break;
case 10: // Macil's exposition on the Sigil
slideshow_state = SLIDE_SIGIL1;
break;
case 29: // Endings
if(!netgame)
{
if(players[0].health <= 0) // Bad ending
slideshow_state = SLIDE_BADEND1; // - Humanity goes extinct
else
{
if((players[0].questflags & QF_QUEST25) && // Converter destroyed
(players[0].questflags & QF_QUEST27)) // ????
{
// Good ending - You get the hot babe.
slideshow_state = SLIDE_GOODEND1;
}
else
{
// Blah ending - You win the battle, but fail at life.
slideshow_state = SLIDE_BLAHEND1;
}
}
}
break;
case 34: // For the demo version ending
slideshow_state = SLIDE_EXIT;
break;
}
S_ChangeMusic(mus_dark, 1);
slideshow_tics = 7;
finalestage = F_STAGE_TEXT;
finalecount = 0;
}
//
// F_Responder
//
// [STRIFE] Verified unmodified
//
boolean F_Responder (event_t *event)
{
if (finalestage == F_STAGE_CAST)
return F_CastResponder (event);
return false;
}
//
// F_WaitTicker
//
// [STRIFE] New function
// haleyjd 09/13/10: This is called from G_Ticker if gamestate is 1, but we
// have no idea for what it's supposed to be. It may in fact be unused.
// STRIFE-TODO: Determine if this is really used or not!
//
void F_WaitTicker(void)
{
if(++finalecount >= 250)
{
gamestate = GS_FINALE;
finalestage = 0;
finalecount = 0;
}
}
//
// F_DoSlideShow
//
// [STRIFE] New function
// haleyjd 09/13/10: Handles slideshow states. Begging to be tabulated!
//
static void F_DoSlideShow(void)
{
patch_t *patch;
switch(slideshow_state)
{
case SLIDE_UNKNOWN: // state #0, seems to be unused
slideshow_tics = 700;
slideshow_state = SLIDE_EXIT;
// falls through into state 1, so above is pointless? ...
case SLIDE_PROGRAMMER1: // state #1
slideshow_panel = DEH_String("SS2F1");
I_StartVoice(DEH_String("MAC10"));
slideshow_state = SLIDE_PROGRAMMER2;
slideshow_tics = 315;
break;
case SLIDE_PROGRAMMER2: // state #2
slideshow_panel = DEH_String("SS2F2");
I_StartVoice(DEH_String("MAC11"));
slideshow_state = SLIDE_PROGRAMMER3;
slideshow_tics = 350;
break;
case SLIDE_PROGRAMMER3: // state #3
slideshow_panel = DEH_String("SS2F3");
I_StartVoice(DEH_String("MAC12"));
slideshow_state = SLIDE_PROGRAMMER4;
slideshow_tics = 420;
break;
case SLIDE_PROGRAMMER4: // state #4
slideshow_panel = DEH_String("SS2F4");
I_StartVoice(DEH_String("MAC13"));
slideshow_state = SLIDE_EXITHACK; // End of slides
slideshow_tics = 595;
break;
case SLIDE_SIGIL1: // state #5
slideshow_panel = DEH_String("SS3F1");
I_StartVoice(DEH_String("MAC16"));
slideshow_state = SLIDE_SIGIL2;
slideshow_tics = 350;
break;
case SLIDE_SIGIL2: // state #6
slideshow_panel = DEH_String("SS3F2");
I_StartVoice(DEH_String("MAC17"));
slideshow_state = SLIDE_SIGIL3;
slideshow_tics = 420;
break;
case SLIDE_SIGIL3: // state #7
slideshow_panel = DEH_String("SS3F3");
I_StartVoice(DEH_String("MAC18"));
slideshow_tics = 420;
slideshow_state = SLIDE_SIGIL4;
break;
case SLIDE_SIGIL4: // state #8
slideshow_panel = DEH_String("SS3F4");
I_StartVoice(DEH_String("MAC19"));
slideshow_tics = 385;
slideshow_state = SLIDE_EXITHACK; // End of slides
break;
case SLIDE_GOODEND1: // state #10
slideshow_panel = DEH_String("SS4F2");
S_StartMusic(mus_happy);
I_StartVoice(DEH_String("RIE01"));
slideshow_state = SLIDE_GOODEND2;
slideshow_tics = 455;
break;
case SLIDE_GOODEND2: // state #11
slideshow_panel = DEH_String("SS4F2");
I_StartVoice(DEH_String("BBX01"));
slideshow_state = SLIDE_GOODEND3;
slideshow_tics = 385;
break;
case SLIDE_GOODEND3: // state #12
slideshow_panel = DEH_String("SS4F3");
I_StartVoice(DEH_String("BBX02"));
slideshow_state = SLIDE_GOODEND4;
slideshow_tics = 490;
break;
case SLIDE_GOODEND4: // state #13
slideshow_panel = DEH_String("SS4F4");
slideshow_state = SLIDE_EXIT; // Go to end credits
slideshow_tics = 980;
break;
case SLIDE_BADEND1: // state #14
S_StartMusic(mus_sad);
slideshow_panel = DEH_String("SS5F1");
I_StartVoice(DEH_String("SS501b"));
slideshow_state = SLIDE_BADEND2;
slideshow_tics = 385;
break;
case SLIDE_BADEND2: // state #15
slideshow_panel = DEH_String("SS5F2");
I_StartVoice(DEH_String("SS502b"));
slideshow_state = SLIDE_BADEND3;
slideshow_tics = 350;
break;
case SLIDE_BADEND3: // state #16
slideshow_panel = DEH_String("SS5F3");
I_StartVoice(DEH_String("SS503b"));
slideshow_state = SLIDE_EXIT; // Go to end credits
slideshow_tics = 385;
break;
case SLIDE_BLAHEND1: // state #17
S_StartMusic(mus_end);
slideshow_panel = DEH_String("SS6F1");
I_StartVoice(DEH_String("SS601A"));
slideshow_state = SLIDE_BLAHEND2;
slideshow_tics = 280;
break;
case SLIDE_BLAHEND2: // state #18
S_StartMusic(mus_end);
slideshow_panel = DEH_String("SS6F2");
I_StartVoice(DEH_String("SS602A"));
slideshow_state = SLIDE_BLAHEND3;
slideshow_tics = 280;
break;
case SLIDE_BLAHEND3: // state #19
S_StartMusic(mus_end);
slideshow_panel = DEH_String("SS6F3");
I_StartVoice(DEH_String("SS603A"));
slideshow_state = SLIDE_EXIT; // Go to credits
slideshow_tics = 315;
break;
case SLIDE_EXITHACK: // state -99: super hack state
gamestate = GS_LEVEL;
P_DialogStartP1();
break;
case SLIDE_EXIT: // state -1: proceed to next finale stage
finalecount = 0;
finalestage = F_STAGE_ARTSCREEN;
wipegamestate = -1;
S_StartMusic(mus_fast);
slideshow_state = SLIDE_CHOCO; // haleyjd: see below...
break;
case SLIDE_CHOCO:
// haleyjd 09/14/10: This wouldn't be necessary except that Choco
// doesn't support the V_MarkRect dirty rectangles system. This
// just so happens to have hidden the fact that the ending
// does a screenfade every ~19 seconds due to remaining stuck in
// SLIDE_EXIT state above, UNLESS the menus were active - the
// V_MarkRect calls in the menu system cause it to be visible.
// This means that in order to get the same behavior as the vanilla
// EXE, I need different code. So, come to this state and only set
// wipegamestate if menuactive is true.
finalecount = 0;
finalestage = F_STAGE_ARTSCREEN;
if(menuactive)
wipegamestate = -1;
S_StartMusic(mus_fast);
slideshow_state = SLIDE_CHOCO; // remain here.
break;
default:
break;
}
finalecount = 0;
patch = (patch_t *)W_CacheLumpName(DEH_String("PANEL0"), PU_CACHE);
V_DrawPatch(0, 0, patch);
}
//
// F_Ticker
//
// [STRIFE] Modifications for new finales
// haleyjd 09/13/10: Calls F_DoSlideShow
//
void F_Ticker (void)
{
size_t i;
// check for skipping
if (finalecount > 50) // [STRIFE] No commercial check
{
// go on to the next level
for (i=0 ; i<MAXPLAYERS ; i++)
if (players[i].cmd.buttons)
break;
if (i < MAXPLAYERS)
finalecount = slideshow_tics; // [STRIFE]
}
// advance animation
finalecount++;
if (finalestage == F_STAGE_CAST)
F_CastTicker ();
else if(finalecount > slideshow_tics) // [STRIFE] Advance slideshow
F_DoSlideShow();
// [STRIFE]: Rest is unused
/*
if ( gamemode == commercial)
return;
if (finalestage == F_STAGE_TEXT
&& finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT)
{
finalecount = 0;
finalestage = F_STAGE_ARTSCREEN;
wipegamestate = -1; // force a wipe
if (gameepisode == 3)
S_StartMusic (mus_logo);
}
*/
}
// haleyjd 09/13/10: Not present in Strife: Cast drawing functions
#include "hu_stuff.h"
extern patch_t *hu_font[HU_FONTSIZE];
/*
//
// F_TextWrite
//
void F_TextWrite (void)
{
byte* src;
byte* dest;
int x,y,w;
signed int count;
char* ch;
int c;
int cx;
int cy;
// erase the entire screen to a tiled background
src = W_CacheLumpName ( finaleflat , PU_CACHE);
dest = I_VideoBuffer;
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);
}
}
V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
// draw some of the text onto the screen
cx = 10;
cy = 10;
ch = finaletext;
count = ((signed int) finalecount - 10) / TEXTSPEED;
if (count < 0)
count = 0;
for ( ; count ; count-- )
{
c = *ch++;
if (!c)
break;
if (c == '\n')
{
cx = 10;
cy += 11;
continue;
}
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
{
cx += 4;
continue;
}
w = SHORT (hu_font[c]->width);
if (cx+w > SCREENWIDTH)
break;
V_DrawPatch(cx, cy, hu_font[c]);
cx+=w;
}
}
*/
//
// Final DOOM 2 animation
// Casting by id Software.
// in order of appearance
//
typedef struct
{
int isindemo; // [STRIFE] Changed from name, which is in mobjinfo
mobjtype_t type;
} castinfo_t;
// haleyjd: [STRIFE] A new cast order was defined, however it is unused in any
// of the released versions of Strife, even including the demo version :(
castinfo_t castorder[] = {
{ 1, MT_PLAYER },
{ 1, MT_BEGGAR1 },
{ 1, MT_PEASANT2_A },
{ 1, MT_REBEL1 },
{ 1, MT_GUARD1 },
{ 1, MT_CRUSADER },
{ 1, MT_RLEADER2 },
{ 0, MT_SENTINEL },
{ 0, MT_STALKER },
{ 0, MT_PROGRAMMER },
{ 0, MT_REAVER },
{ 0, MT_PGUARD },
{ 0, MT_INQUISITOR },
{ 0, MT_PRIEST },
{ 0, MT_SPECTRE_A },
{ 0, MT_BISHOP },
{ 0, MT_ENTITY },
{ 1, NUMMOBJTYPES }
};
int castnum;
int casttics;
state_t* caststate;
boolean castdeath;
int castframes;
int castonmelee;
boolean castattacking;
extern gamestate_t wipegamestate;
//
// F_StartCast
//
// haleyjd 09/13/10: [STRIFE] Heavily modified, yet unused.
// Evidence suggests this was meant to be started from a menu item.
// See m_menu.c for more info.
//
void F_StartCast (void)
{
usergame = false;
gameaction = ga_nothing;
viewactive = false;
automapactive = false;
castnum = 0;
gamestate = GS_FINALE;
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
casttics = caststate->tics;
if(casttics > 50)
casttics = 50;
wipegamestate = -1; // force a screen wipe
castdeath = false;
finalestage = F_STAGE_CAST;
castframes = 0;
castonmelee = 0;
castattacking = false;
}
//
// F_CastTicker
//
// [STRIFE] Heavily modified, but unused.
// haleyjd 09/13/10: Yeah, I bothered translating this even though it isn't
// going to be seen, in part because I hope some Strife port or another will
// pick it up and finish it, adding it as the optional menu item it was
// meant to be, or just adding it as part of the ending sequence.
//
void F_CastTicker (void)
{
int st;
if (--casttics > 0)
return; // not time to change state yet
if (caststate->tics == -1 || caststate->nextstate == S_NULL)
{
// switch from deathstate to next monster
castnum++;
castdeath = false;
if (isdemoversion)
{
// [STRIFE] Demo version had a shorter cast
if(!castorder[castnum].isindemo)
castnum = 0;
}
// [STRIFE] Break on type == NUMMOBJTYPES rather than name == NULL
if (castorder[castnum].type == NUMMOBJTYPES)
castnum = 0;
if (mobjinfo[castorder[castnum].type].seesound)
S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound);
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
castframes = 0;
}
else
{
int sfx = 0;
// just advance to next state in animation
if (caststate == &states[S_PLAY_05]) // villsa [STRIFE] - updated
goto stopattack; // Oh, gross hack!
st = caststate->nextstate;
caststate = &states[st];
castframes++;
if (st != mobjinfo[castorder[castnum].type].meleestate &&
st != mobjinfo[castorder[castnum].type].missilestate)
{
if (st == S_PLAY_05)
sfx = sfx_rifle;
else
sfx = 0;
}
else
sfx = mobjinfo[castorder[castnum].type].attacksound;
if (sfx)
S_StartSound (NULL, sfx);
}
if (!castdeath && castframes == 12)
{
// go into attack frame
castattacking = true;
if (castonmelee)
caststate=&states[mobjinfo[castorder[castnum].type].meleestate];
else
caststate=&states[mobjinfo[castorder[castnum].type].missilestate];
castonmelee ^= 1;
if (caststate == &states[S_NULL])
{
if (castonmelee)
caststate = &states[mobjinfo[castorder[castnum].type].meleestate];
else
caststate = &states[mobjinfo[castorder[castnum].type].missilestate];
}
}
if (castattacking)
{
if (castframes == 24
|| caststate == &states[mobjinfo[castorder[castnum].type].seestate] )
{
stopattack:
castattacking = false;
castframes = 0;
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
}
}
casttics = caststate->tics;
if (casttics > 50) // [STRIFE] Cap tics
casttics = 50;
else if (casttics == -1)
casttics = 15;
}
//
// F_CastResponder
//
// [STRIFE] This still exists in Strife but is never used.
// It was used at some point in development, however, as they made
// numerous modifications to the cast call system.
//
boolean F_CastResponder (event_t* ev)
{
if (ev->type != ev_keydown)
return false;
if (castdeath)
return true; // already in dying frames
// go into death frame
castdeath = true;
caststate = &states[mobjinfo[castorder[castnum].type].deathstate];
casttics = caststate->tics;
if(casttics > 50) // [STRIFE] Upper bound on casttics
casttics = 50;
castframes = 0;
castattacking = false;
if (mobjinfo[castorder[castnum].type].deathsound)
S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound);
return true;
}
//
// F_CastPrint
//
// [STRIFE] Verified unmodified, and unused.
//
void F_CastPrint (char* text)
{
char* ch;
int c;
int cx;
int w;
int width;
// find width
ch = text;
width = 0;
while (ch)
{
c = *ch++;
if (!c)
break;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
{
width += 4;
continue;
}
w = SHORT (hu_font[c]->width);
width += w;
}
// draw it
cx = 160-width/2;
ch = text;
while (ch)
{
c = *ch++;
if (!c)
break;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
{
cx += 4;
continue;
}
w = SHORT (hu_font[c]->width);
V_DrawPatch(cx, 180, hu_font[c]);
cx+=w;
}
}
// haleyjd 09/13/10: [STRIFE] Unfortunately they removed whatever was
// partway finished of this function from the binary, as there is no
// trace of it. This means we cannot know for sure what the cast call
// would have looked like. :(
/*
//
// F_CastDrawer
//
void F_CastDrawer (void)
{
spritedef_t* sprdef;
spriteframe_t* sprframe;
int lump;
boolean flip;
patch_t* patch;
// erase the entire screen to a background
V_DrawPatch (0, 0, W_CacheLumpName (DEH_String("BOSSBACK"), PU_CACHE));
F_CastPrint (DEH_String(castorder[castnum].name));
// draw the current frame in the middle of the screen
sprdef = &sprites[caststate->sprite];
sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK];
lump = sprframe->lump[0];
flip = (boolean)sprframe->flip[0];
patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE);
if (flip)
V_DrawPatchFlipped(160, 170, patch);
else
V_DrawPatch(160, 170, patch);
}
*/
#ifdef STRIFE_DEMO_CODE
//
// F_DrawPatchCol
//
// [STRIFE] Verified unmodified, but not present in 1.2
// It WAS present in the demo version, however...
//
void
F_DrawPatchCol
( int x,
patch_t* patch,
int col )
{
column_t* column;
byte* source;
byte* dest;
byte* desttop;
int count;
column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
desttop = I_VideoBuffer + x;
// step through the posts in a column
while (column->topdelta != 0xff )
{
source = (byte *)column + 3;
dest = desttop + column->topdelta*SCREENWIDTH;
count = column->length;
while (count--)
{
*dest = *source++;
dest += SCREENWIDTH;
}
column = (column_t *)( (byte *)column + column->length + 4 );
}
}
#endif
//
// F_DrawMap34End
//
// [STRIFE] Modified from F_BunnyScroll
// * In 1.2 and up this just causes a weird black screen.
// * In the demo version, it was an actual scroll between two screens.
// I have implemented both code segments, though only the black screen
// one will currently be used, as full demo version support isn't looking
// likely right now.
//
void F_DrawMap34End (void)
{
signed int scrolled;
int x;
patch_t* p1;
patch_t* p2;
static int laststage;
p1 = W_CacheLumpName (DEH_String("credit"), PU_LEVEL);
p2 = W_CacheLumpName (DEH_String("vellogo"), PU_LEVEL);
V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
scrolled = (320 - ((signed int) finalecount-430)/2);
if (scrolled > 320)
scrolled = 320;
if (scrolled < 0)
scrolled = 0;
#ifdef STRIFE_DEMO_CODE
for ( x=0 ; x<SCREENWIDTH ; x++)
{
if (x+scrolled < 320)
F_DrawPatchCol (x, p1, x+scrolled);
else
F_DrawPatchCol (x, p2, x+scrolled - 320);
}
#else
// wtf this is supposed to do, I have no idea!
x = 1;
do
{
x += 11;
}
while(x < 320);
#endif
}
// haleyjd 09/13/10: [STRIFE] Unused.
/*
static void F_ArtScreenDrawer(void)
{
char *lumpname;
if (gameepisode == 3)
{
F_BunnyScroll();
}
else
{
switch (gameepisode)
{
case 1:
if (gamemode == retail)
{
lumpname = "CREDIT";
}
else
{
lumpname = "HELP2";
}
break;
case 2:
lumpname = "VICTORY2";
break;
case 4:
lumpname = "ENDPIC";
break;
default:
return;
}
lumpname = DEH_String(lumpname);
V_DrawPatch (0, 0, W_CacheLumpName(lumpname, PU_CACHE));
}
}
*/
//
// F_Drawer
//
// [STRIFE]
// haleyjd 09/13/10: Modified for slideshow, demo version, etc.
//
void F_Drawer (void)
{
switch (finalestage)
{
case F_STAGE_CAST:
// Cast didn't have a drawer in any released version
//F_CastDrawer();
break;
case F_STAGE_TEXT:
// Draw slideshow panel
{
patch_t *slide = W_CacheLumpName(slideshow_panel, PU_CACHE);
V_DrawPatch(0, 0, slide);
}
break;
case F_STAGE_ARTSCREEN:
if(gamemap <= 29)
{
// draw credits
patch_t *credits = W_CacheLumpName(DEH_String("CREDIT"), PU_CACHE);
V_DrawPatch(0, 0, credits);
}
else if(gamemap == 34)
{
// demo version - does nothing meaningful in the final version
F_DrawMap34End();
}
break;
}
}