summaryrefslogtreecommitdiff
path: root/src/strife/f_finale.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/strife/f_finale.c')
-rw-r--r--src/strife/f_finale.c1024
1 files changed, 1024 insertions, 0 deletions
diff --git a/src/strife/f_finale.c b/src/strife/f_finale.c
new file mode 100644
index 00000000..551a4e24
--- /dev/null
+++ b/src/strife/f_finale.c
@@ -0,0 +1,1024 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// Copyright(C) 2005 Simon Howard
+// Copyright(C) 2010 James Haley, Samuel Villarreal
+//
+// 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)
+{
+#if 0
+ // haleyjd 20111006: see below...
+ patch_t *panel;
+#endif
+
+ gameaction = ga_nothing;
+ gamestate = GS_FINALE;
+ viewactive = false;
+ automapactive = false;
+ wipegamestate = -1; // [STRIFE]
+
+ // [STRIFE] Setup the slide show
+ slideshow_panel = DEH_String("PANEL0");
+
+ // haleyjd 20111006: These two lines of code *are* in vanilla Strife;
+ // however, there, they were completely inconsequential due to the dirty
+ // rects system. No intervening V_MarkRect call means PANEL0 was never
+ // drawn to the framebuffer. In Chocolate Strife, however, with no such
+ // system in place, this only manages to fuck up the fade-out that is
+ // supposed to happen at the beginning of all finales. So, don't do it!
+#if 0
+ panel = (patch_t *)W_CacheLumpName(slideshow_panel, PU_CACHE);
+ V_DrawPatch(0, 0, panel);
+#endif
+
+ 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)) // Computer destroyed (wtf?!)
+ {
+ // 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 is unused.
+//
+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("SS4F1");
+ 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;
+ }
+}
+