1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
20 // Game completion, final screen animation.
22 //-----------------------------------------------------------------------------
26 rcsid[] = "$Id: f_finale.c,v 1.5 1997/02/03 21:26:34 b1 Exp $";
46 //#include "doomstat.h"
47 //#include "r_local.h"
48 //#include "f_finale.h"
50 // Stage of animation:
51 // 0 = text, 1 = art screen, 2 = character cast
59 char* e1text = E1TEXT;
60 char* e2text = E2TEXT;
61 char* e3text = E3TEXT;
62 char* e4text = E4TEXT;
64 char* c1text = C1TEXT;
65 char* c2text = C2TEXT;
66 char* c3text = C3TEXT;
67 char* c4text = C4TEXT;
68 char* c5text = C5TEXT;
69 char* c6text = C6TEXT;
71 char* p1text = P1TEXT;
72 char* p2text = P2TEXT;
73 char* p3text = P3TEXT;
74 char* p4text = P4TEXT;
75 char* p5text = P5TEXT;
76 char* p6text = P6TEXT;
78 char* t1text = T1TEXT;
79 char* t2text = T2TEXT;
80 char* t3text = T3TEXT;
81 char* t4text = T4TEXT;
82 char* t5text = T5TEXT;
83 char* t6text = T6TEXT;
88 void F_StartCast (void);
89 void F_CastTicker (void);
90 boolean F_CastResponder (event_t *ev);
91 void F_CastDrawer (void);
96 void F_StartFinale (void)
98 gameaction = ga_nothing;
99 gamestate = GS_FINALE;
101 automapactive = false;
103 // Okay - IWAD dependend stuff.
104 // This has been changed severly, and
105 // some stuff might have changed in the process.
109 // DOOM 1 - E1, E3 or E4, but each nine missions
114 S_ChangeMusic(mus_victor, true);
119 finaleflat = "FLOOR4_8";
123 finaleflat = "SFLR6_1";
127 finaleflat = "MFLR8_4";
131 finaleflat = "MFLR8_3";
141 // DOOM II and missions packs with E1, M34
144 S_ChangeMusic(mus_read_m, true);
149 finaleflat = "SLIME16";
153 finaleflat = "RROCK14";
157 finaleflat = "RROCK07";
161 finaleflat = "RROCK17";
165 finaleflat = "RROCK13";
169 finaleflat = "RROCK19";
182 S_ChangeMusic(mus_read_m, true);
183 finaleflat = "F_SKY1"; // Not used anywhere else.
184 finaletext = c1text; // FIXME - other text, music?
195 boolean F_Responder (event_t *event)
197 if (finalestage == 2)
198 return F_CastResponder (event);
211 // check for skipping
212 if ( (gamemode == commercial)
213 && ( finalecount > 50) )
215 // go on to the next level
216 for (i=0 ; i<MAXPLAYERS ; i++)
217 if (players[i].cmd.buttons)
225 gameaction = ga_worlddone;
232 if (finalestage == 2)
238 if ( gamemode == commercial)
241 if (!finalestage && finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT)
245 wipegamestate = -1; // force a wipe
246 if (gameepisode == 3)
247 S_StartMusic (mus_bunny);
257 #include "hu_stuff.h"
258 extern patch_t *hu_font[HU_FONTSIZE];
261 void F_TextWrite (void)
273 // erase the entire screen to a tiled background
274 src = W_CacheLumpName ( finaleflat , PU_CACHE);
277 for (y=0 ; y<SCREENHEIGHT ; y++)
279 for (x=0 ; x<SCREENWIDTH/64 ; x++)
281 memcpy (dest, src+((y&63)<<6), 64);
286 memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
287 dest += (SCREENWIDTH&63);
291 V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
293 // draw some of the text onto the screen
298 count = (finalecount - 10)/TEXTSPEED;
301 for ( ; count ; count-- )
313 c = toupper(c) - HU_FONTSTART;
314 if (c < 0 || c> HU_FONTSIZE)
320 w = SHORT (hu_font[c]->width);
321 if (cx+w > SCREENWIDTH)
323 V_DrawPatch(cx, cy, 0, hu_font[c]);
330 // Final DOOM 2 animation
331 // Casting by id Software.
332 // in order of appearance
340 castinfo_t castorder[] = {
341 {CC_ZOMBIE, MT_POSSESSED},
342 {CC_SHOTGUN, MT_SHOTGUY},
343 {CC_HEAVY, MT_CHAINGUY},
345 {CC_DEMON, MT_SERGEANT},
348 {CC_HELL, MT_KNIGHT},
349 {CC_BARON, MT_BRUISER},
352 {CC_REVEN, MT_UNDEAD},
353 {CC_MANCU, MT_FATSO},
355 {CC_SPIDER, MT_SPIDER},
356 {CC_CYBER, MT_CYBORG},
357 {CC_HERO, MT_PLAYER},
368 boolean castattacking;
374 extern gamestate_t wipegamestate;
377 void F_StartCast (void)
379 wipegamestate = -1; // force a screen wipe
381 caststate = &states[mobjinfo[castorder[castnum].type].seestate];
382 casttics = caststate->tics;
387 castattacking = false;
388 S_ChangeMusic(mus_evil, true);
395 void F_CastTicker (void)
401 return; // not time to change state yet
403 if (caststate->tics == -1 || caststate->nextstate == S_NULL)
405 // switch from deathstate to next monster
408 if (castorder[castnum].name == NULL)
410 if (mobjinfo[castorder[castnum].type].seesound)
411 S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound);
412 caststate = &states[mobjinfo[castorder[castnum].type].seestate];
417 // just advance to next state in animation
418 if (caststate == &states[S_PLAY_ATK1])
419 goto stopattack; // Oh, gross hack!
420 st = caststate->nextstate;
421 caststate = &states[st];
427 case S_PLAY_ATK1: sfx = sfx_dshtgn; break;
428 case S_POSS_ATK2: sfx = sfx_pistol; break;
429 case S_SPOS_ATK2: sfx = sfx_shotgn; break;
430 case S_VILE_ATK2: sfx = sfx_vilatk; break;
431 case S_SKEL_FIST2: sfx = sfx_skeswg; break;
432 case S_SKEL_FIST4: sfx = sfx_skepch; break;
433 case S_SKEL_MISS2: sfx = sfx_skeatk; break;
436 case S_FATT_ATK2: sfx = sfx_firsht; break;
439 case S_CPOS_ATK4: sfx = sfx_shotgn; break;
440 case S_TROO_ATK3: sfx = sfx_claw; break;
441 case S_SARG_ATK2: sfx = sfx_sgtatk; break;
444 case S_HEAD_ATK2: sfx = sfx_firsht; break;
445 case S_SKULL_ATK2: sfx = sfx_sklatk; break;
447 case S_SPID_ATK3: sfx = sfx_shotgn; break;
448 case S_BSPI_ATK2: sfx = sfx_plasma; break;
451 case S_CYBER_ATK6: sfx = sfx_rlaunc; break;
452 case S_PAIN_ATK3: sfx = sfx_sklatk; break;
453 default: sfx = 0; break;
457 S_StartSound (NULL, sfx);
460 if (castframes == 12)
462 // go into attack frame
463 castattacking = true;
465 caststate=&states[mobjinfo[castorder[castnum].type].meleestate];
467 caststate=&states[mobjinfo[castorder[castnum].type].missilestate];
469 if (caststate == &states[S_NULL])
473 &states[mobjinfo[castorder[castnum].type].meleestate];
476 &states[mobjinfo[castorder[castnum].type].missilestate];
483 || caststate == &states[mobjinfo[castorder[castnum].type].seestate] )
486 castattacking = false;
488 caststate = &states[mobjinfo[castorder[castnum].type].seestate];
492 casttics = caststate->tics;
502 boolean F_CastResponder (event_t* ev)
504 if (ev->type != ev_keydown)
508 return true; // already in dying frames
510 // go into death frame
512 caststate = &states[mobjinfo[castorder[castnum].type].deathstate];
513 casttics = caststate->tics;
515 castattacking = false;
516 if (mobjinfo[castorder[castnum].type].deathsound)
517 S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound);
523 void F_CastPrint (char* text)
540 c = toupper(c) - HU_FONTSTART;
541 if (c < 0 || c> HU_FONTSIZE)
547 w = SHORT (hu_font[c]->width);
559 c = toupper(c) - HU_FONTSTART;
560 if (c < 0 || c> HU_FONTSIZE)
566 w = SHORT (hu_font[c]->width);
567 V_DrawPatch(cx, 180, 0, hu_font[c]);
577 void V_DrawPatchFlipped (int x, int y, int scrn, patch_t *patch);
579 void F_CastDrawer (void)
582 spriteframe_t* sprframe;
587 // erase the entire screen to a background
588 V_DrawPatch (0,0,0, W_CacheLumpName ("BOSSBACK", PU_CACHE));
590 F_CastPrint (castorder[castnum].name);
592 // draw the current frame in the middle of the screen
593 sprdef = &sprites[caststate->sprite];
594 sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK];
595 lump = sprframe->lump[0];
596 flip = (boolean)sprframe->flip[0];
598 patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE);
600 V_DrawPatchFlipped (160,170,0,patch);
602 V_DrawPatch (160,170,0,patch);
621 column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
622 desttop = screens[0]+x;
624 // step through the posts in a column
625 while (column->topdelta != 0xff )
627 source = (byte *)column + 3;
628 dest = desttop + column->topdelta*SCREENWIDTH;
629 count = column->length;
636 column = (column_t *)( (byte *)column + column->length + 4 );
644 void F_BunnyScroll (void)
652 static int laststage;
654 p1 = W_CacheLumpName ("PFUB2", PU_LEVEL);
655 p2 = W_CacheLumpName ("PFUB1", PU_LEVEL);
657 V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
659 scrolled = 320 - (finalecount-230)/2;
665 for ( x=0 ; x<SCREENWIDTH ; x++)
667 if (x+scrolled < 320)
668 F_DrawPatchCol (x, p1, x+scrolled);
670 F_DrawPatchCol (x, p2, x+scrolled - 320);
673 if (finalecount < 1130)
675 if (finalecount < 1180)
677 V_DrawPatch ((SCREENWIDTH-13*8)/2,
678 (SCREENHEIGHT-8*8)/2,0, W_CacheLumpName ("END0",PU_CACHE));
683 stage = (finalecount-1180) / 5;
686 if (stage > laststage)
688 S_StartSound (NULL, sfx_pistol);
692 sprintf (name,"END%i",stage);
693 V_DrawPatch ((SCREENWIDTH-13*8)/2, (SCREENHEIGHT-8*8)/2,0, W_CacheLumpName (name,PU_CACHE));
702 if (finalestage == 2)
715 if ( gamemode == retail )
717 W_CacheLumpName("CREDIT",PU_CACHE));
720 W_CacheLumpName("HELP2",PU_CACHE));
724 W_CacheLumpName("VICTORY2",PU_CACHE));
731 W_CacheLumpName("ENDPIC",PU_CACHE));