123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739 |
- // Emacs style mode select -*- C++ -*-
- //-----------------------------------------------------------------------------
- //
- // $Id:$
- //
- // Copyright (C) 1993-1996 by id Software, Inc.
- //
- // This source is available for distribution and/or modification
- // only under the terms of the DOOM Source Code License as
- // published by id Software. All rights reserved.
- //
- // The source is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
- // for more details.
- //
- // $Log:$
- //
- // DESCRIPTION:
- // Game completion, final screen animation.
- //
- //-----------------------------------------------------------------------------
- static const char
- rcsid[] = "$Id: f_finale.c,v 1.5 1997/02/03 21:26:34 b1 Exp $";
- #include <ctype.h>
- // Functions.
- #include "i_system.h"
- #include "m_swap.h"
- #include "z_zone.h"
- #include "v_video.h"
- #include "w_wad.h"
- #include "s_sound.h"
- // Data.
- #include "dstrings.h"
- #include "sounds.h"
- #include "doomstat.h"
- #include "r_state.h"
- // ?
- //#include "doomstat.h"
- //#include "r_local.h"
- //#include "f_finale.h"
- // Stage of animation:
- // 0 = text, 1 = art screen, 2 = character cast
- int finalestage;
- int finalecount;
- #define TEXTSPEED 3
- #define TEXTWAIT 250
- char* e1text = E1TEXT;
- char* e2text = E2TEXT;
- char* e3text = E3TEXT;
- char* e4text = E4TEXT;
- char* c1text = C1TEXT;
- char* c2text = C2TEXT;
- char* c3text = C3TEXT;
- char* c4text = C4TEXT;
- char* c5text = C5TEXT;
- char* c6text = C6TEXT;
- char* p1text = P1TEXT;
- char* p2text = P2TEXT;
- char* p3text = P3TEXT;
- char* p4text = P4TEXT;
- char* p5text = P5TEXT;
- char* p6text = P6TEXT;
- char* t1text = T1TEXT;
- char* t2text = T2TEXT;
- char* t3text = T3TEXT;
- char* t4text = T4TEXT;
- char* t5text = T5TEXT;
- char* t6text = T6TEXT;
- char* finaletext;
- char* finaleflat;
- void F_StartCast (void);
- void F_CastTicker (void);
- boolean F_CastResponder (event_t *ev);
- void F_CastDrawer (void);
- //
- // F_StartFinale
- //
- void F_StartFinale (void)
- {
- gameaction = ga_nothing;
- gamestate = GS_FINALE;
- viewactive = false;
- automapactive = false;
- // Okay - IWAD dependend stuff.
- // This has been changed severly, and
- // some stuff might have changed in the process.
- switch ( gamemode )
- {
- // DOOM 1 - E1, E3 or E4, but each nine missions
- case shareware:
- case registered:
- case retail:
- {
- S_ChangeMusic(mus_victor, true);
-
- switch (gameepisode)
- {
- case 1:
- finaleflat = "FLOOR4_8";
- finaletext = e1text;
- break;
- case 2:
- finaleflat = "SFLR6_1";
- finaletext = e2text;
- break;
- case 3:
- finaleflat = "MFLR8_4";
- finaletext = e3text;
- break;
- case 4:
- finaleflat = "MFLR8_3";
- finaletext = e4text;
- break;
- default:
- // Ouch.
- break;
- }
- break;
- }
-
- // DOOM II and missions packs with E1, M34
- case commercial:
- {
- S_ChangeMusic(mus_read_m, true);
- switch (gamemap)
- {
- case 6:
- finaleflat = "SLIME16";
- finaletext = c1text;
- break;
- case 11:
- finaleflat = "RROCK14";
- finaletext = c2text;
- break;
- case 20:
- finaleflat = "RROCK07";
- finaletext = c3text;
- break;
- case 30:
- finaleflat = "RROCK17";
- finaletext = c4text;
- break;
- case 15:
- finaleflat = "RROCK13";
- finaletext = c5text;
- break;
- case 31:
- finaleflat = "RROCK19";
- finaletext = c6text;
- break;
- default:
- // Ouch.
- break;
- }
- break;
- }
-
- // Indeterminate.
- default:
- S_ChangeMusic(mus_read_m, true);
- finaleflat = "F_SKY1"; // Not used anywhere else.
- finaletext = c1text; // FIXME - other text, music?
- break;
- }
-
- finalestage = 0;
- finalecount = 0;
-
- }
- boolean F_Responder (event_t *event)
- {
- if (finalestage == 2)
- return F_CastResponder (event);
-
- return false;
- }
- //
- // F_Ticker
- //
- void F_Ticker (void)
- {
- int i;
-
- // check for skipping
- if ( (gamemode == commercial)
- && ( finalecount > 50) )
- {
- // go on to the next level
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (players[i].cmd.buttons)
- break;
-
- if (i < MAXPLAYERS)
- {
- if (gamemap == 30)
- F_StartCast ();
- else
- gameaction = ga_worlddone;
- }
- }
-
- // advance animation
- finalecount++;
-
- if (finalestage == 2)
- {
- F_CastTicker ();
- return;
- }
-
- if ( gamemode == commercial)
- return;
-
- if (!finalestage && finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT)
- {
- finalecount = 0;
- finalestage = 1;
- wipegamestate = -1; // force a wipe
- if (gameepisode == 3)
- S_StartMusic (mus_bunny);
- }
- }
- //
- // F_TextWrite
- //
- #include "hu_stuff.h"
- extern patch_t *hu_font[HU_FONTSIZE];
- void F_TextWrite (void)
- {
- byte* src;
- byte* dest;
-
- int x,y,w;
- 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 = screens[0];
-
- 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 = (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, 0, hu_font[c]);
- cx+=w;
- }
-
- }
- //
- // Final DOOM 2 animation
- // Casting by id Software.
- // in order of appearance
- //
- typedef struct
- {
- char *name;
- mobjtype_t type;
- } castinfo_t;
- castinfo_t castorder[] = {
- {CC_ZOMBIE, MT_POSSESSED},
- {CC_SHOTGUN, MT_SHOTGUY},
- {CC_HEAVY, MT_CHAINGUY},
- {CC_IMP, MT_TROOP},
- {CC_DEMON, MT_SERGEANT},
- {CC_LOST, MT_SKULL},
- {CC_CACO, MT_HEAD},
- {CC_HELL, MT_KNIGHT},
- {CC_BARON, MT_BRUISER},
- {CC_ARACH, MT_BABY},
- {CC_PAIN, MT_PAIN},
- {CC_REVEN, MT_UNDEAD},
- {CC_MANCU, MT_FATSO},
- {CC_ARCH, MT_VILE},
- {CC_SPIDER, MT_SPIDER},
- {CC_CYBER, MT_CYBORG},
- {CC_HERO, MT_PLAYER},
- {NULL,0}
- };
- int castnum;
- int casttics;
- state_t* caststate;
- boolean castdeath;
- int castframes;
- int castonmelee;
- boolean castattacking;
- //
- // F_StartCast
- //
- extern gamestate_t wipegamestate;
- void F_StartCast (void)
- {
- wipegamestate = -1; // force a screen wipe
- castnum = 0;
- caststate = &states[mobjinfo[castorder[castnum].type].seestate];
- casttics = caststate->tics;
- castdeath = false;
- finalestage = 2;
- castframes = 0;
- castonmelee = 0;
- castattacking = false;
- S_ChangeMusic(mus_evil, true);
- }
- //
- // F_CastTicker
- //
- void F_CastTicker (void)
- {
- int st;
- int sfx;
-
- 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 (castorder[castnum].name == NULL)
- 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
- {
- // just advance to next state in animation
- if (caststate == &states[S_PLAY_ATK1])
- goto stopattack; // Oh, gross hack!
- st = caststate->nextstate;
- caststate = &states[st];
- castframes++;
-
- // sound hacks....
- switch (st)
- {
- case S_PLAY_ATK1: sfx = sfx_dshtgn; break;
- case S_POSS_ATK2: sfx = sfx_pistol; break;
- case S_SPOS_ATK2: sfx = sfx_shotgn; break;
- case S_VILE_ATK2: sfx = sfx_vilatk; break;
- case S_SKEL_FIST2: sfx = sfx_skeswg; break;
- case S_SKEL_FIST4: sfx = sfx_skepch; break;
- case S_SKEL_MISS2: sfx = sfx_skeatk; break;
- case S_FATT_ATK8:
- case S_FATT_ATK5:
- case S_FATT_ATK2: sfx = sfx_firsht; break;
- case S_CPOS_ATK2:
- case S_CPOS_ATK3:
- case S_CPOS_ATK4: sfx = sfx_shotgn; break;
- case S_TROO_ATK3: sfx = sfx_claw; break;
- case S_SARG_ATK2: sfx = sfx_sgtatk; break;
- case S_BOSS_ATK2:
- case S_BOS2_ATK2:
- case S_HEAD_ATK2: sfx = sfx_firsht; break;
- case S_SKULL_ATK2: sfx = sfx_sklatk; break;
- case S_SPID_ATK2:
- case S_SPID_ATK3: sfx = sfx_shotgn; break;
- case S_BSPI_ATK2: sfx = sfx_plasma; break;
- case S_CYBER_ATK2:
- case S_CYBER_ATK4:
- case S_CYBER_ATK6: sfx = sfx_rlaunc; break;
- case S_PAIN_ATK3: sfx = sfx_sklatk; break;
- default: sfx = 0; break;
- }
-
- if (sfx)
- S_StartSound (NULL, sfx);
- }
-
- if (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 == -1)
- casttics = 15;
- }
- //
- // F_CastResponder
- //
- 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;
- castframes = 0;
- castattacking = false;
- if (mobjinfo[castorder[castnum].type].deathsound)
- S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound);
-
- return true;
- }
- 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, 0, hu_font[c]);
- cx+=w;
- }
-
- }
- //
- // F_CastDrawer
- //
- void V_DrawPatchFlipped (int x, int y, int scrn, patch_t *patch);
- 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,0, W_CacheLumpName ("BOSSBACK", PU_CACHE));
- F_CastPrint (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,0,patch);
- else
- V_DrawPatch (160,170,0,patch);
- }
- //
- // F_DrawPatchCol
- //
- 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 = screens[0]+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 );
- }
- }
- //
- // F_BunnyScroll
- //
- void F_BunnyScroll (void)
- {
- int scrolled;
- int x;
- patch_t* p1;
- patch_t* p2;
- char name[10];
- int stage;
- static int laststage;
-
- p1 = W_CacheLumpName ("PFUB2", PU_LEVEL);
- p2 = W_CacheLumpName ("PFUB1", PU_LEVEL);
- V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
-
- scrolled = 320 - (finalecount-230)/2;
- if (scrolled > 320)
- scrolled = 320;
- if (scrolled < 0)
- scrolled = 0;
-
- for ( x=0 ; x<SCREENWIDTH ; x++)
- {
- if (x+scrolled < 320)
- F_DrawPatchCol (x, p1, x+scrolled);
- else
- F_DrawPatchCol (x, p2, x+scrolled - 320);
- }
-
- if (finalecount < 1130)
- return;
- if (finalecount < 1180)
- {
- V_DrawPatch ((SCREENWIDTH-13*8)/2,
- (SCREENHEIGHT-8*8)/2,0, W_CacheLumpName ("END0",PU_CACHE));
- laststage = 0;
- return;
- }
-
- stage = (finalecount-1180) / 5;
- if (stage > 6)
- stage = 6;
- if (stage > laststage)
- {
- S_StartSound (NULL, sfx_pistol);
- laststage = stage;
- }
-
- sprintf (name,"END%i",stage);
- V_DrawPatch ((SCREENWIDTH-13*8)/2, (SCREENHEIGHT-8*8)/2,0, W_CacheLumpName (name,PU_CACHE));
- }
- //
- // F_Drawer
- //
- void F_Drawer (void)
- {
- if (finalestage == 2)
- {
- F_CastDrawer ();
- return;
- }
- if (!finalestage)
- F_TextWrite ();
- else
- {
- switch (gameepisode)
- {
- case 1:
- if ( gamemode == retail )
- V_DrawPatch (0,0,0,
- W_CacheLumpName("CREDIT",PU_CACHE));
- else
- V_DrawPatch (0,0,0,
- W_CacheLumpName("HELP2",PU_CACHE));
- break;
- case 2:
- V_DrawPatch(0,0,0,
- W_CacheLumpName("VICTORY2",PU_CACHE));
- break;
- case 3:
- F_BunnyScroll ();
- break;
- case 4:
- V_DrawPatch (0,0,0,
- W_CacheLumpName("ENDPIC",PU_CACHE));
- break;
- }
- }
-
- }
|