ref: 08b1ff3b0ba4796908d9aee601c62d9ce54f091f
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; 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; size_t i; 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("MAC16"); slideshow_state = SLIDE_SIGIL2; slideshow_tics = 350; break; case SLIDE_SIGIL2: // state #6 slideshow_panel = DEH_String("SS3F2"); I_StartVoice("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; char name[10]; int stage; 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; } }