home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ST-Computer Leser-CD 2000 January
/
LCD_01_2000.iso
/
games
/
doom
/
pmdoom
/
src
/
f_finale.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-12-17
|
19KB
|
900 lines
/* 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"
#include "i_video.h"
/* Data. */
#include "dstrings.h"
#include "sounds.h"
#include "doomstat.h"
#include "r_state.h"
#include "i_video.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,*src1;
byte* dest;
unsigned short *destsrc;
unsigned long *destsrc32;
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);
switch (pixel_size)
{
case 1:
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);
}
}
break;
case 2:
destsrc = (unsigned short *) screens[0];
for (y=0 ; y<SCREENHEIGHT ; y++)
{
unsigned short *dest1;
src1 = src + ((y & 63) << 6);
dest1 = destsrc;
for (x=0; x<SCREENWIDTH ; x++)
{
*dest1++ = truecolor_palette[ src1[x & 63] ];
}
destsrc += SCREENWIDTH;
}
break;
case 3:
dest=screens[0];
for (y=0 ; y<SCREENHEIGHT ; y++)
{
byte *dest1;
src1 = src + ((y & 63) << 6);
dest1 = dest;
for (x=0; x<SCREENWIDTH ; x++)
{
unsigned long couleur;
couleur = truecolor_palette[ src1[x & 63] ];
*dest1++ = couleur;
*dest1++ = couleur >> 8;
*dest1++ = couleur >> 16;
}
dest += SCREENWIDTH*3;
}
break;
case 4:
destsrc32 = (unsigned long *) screens[0];
for (y=0 ; y<SCREENHEIGHT ; y++)
{
unsigned long *dest1;
src1 = src + ((y & 63) << 6);
dest1 = destsrc32;
for (x=0; x<SCREENWIDTH ; x++)
{
*dest1++ = truecolor_palette[ src1[x & 63] ];
}
destsrc32 += SCREENWIDTH;
}
break;
}
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_DrawPatchCol8
( 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 );
}
}
void
F_DrawPatchCol16
( int x,
patch_t* patch,
int col )
{
column_t* column;
byte* source;
unsigned short *desttop,*dest;
int count;
column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
desttop = (unsigned short *) (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 = truecolor_palette[*source++];
dest += SCREENWIDTH;
}
column = (column_t *)( (byte *)column + column->length + 4 );
}
}
void
F_DrawPatchCol24
( int x,
patch_t* patch,
int col )
{
column_t* column;
byte* source;
byte* dest;
byte* desttop;
int count;
unsigned long couleur;
column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
desttop = screens[0]+x*3;
/* step through the posts in a column */
while (column->topdelta != 0xff )
{
source = (byte *)column + 3;
dest = desttop + column->topdelta*SCREENWIDTH*3;
count = column->length;
while (count--)
{
couleur = truecolor_palette[*source++];
*dest++ = couleur;
*dest++ = couleur >> 8;
*dest++ = couleur >> 16;
dest += (SCREENWIDTH*3)-3;
}
column = (column_t *)( (byte *)column + column->length + 4 );
}
}
void
F_DrawPatchCol32
( int x,
patch_t* patch,
int col )
{
column_t* column;
byte* source;
unsigned long *desttop,*dest;
int count;
column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
desttop = (unsigned long *) (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 = truecolor_palette[*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;
}
}
}