
Iskhodnyy_kod_Doom
.pdf{
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; |
// |
|
111
// 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; |
112
case S_CPOS_ATK2: case S_CPOS_ATK3: case S_CPOS_ATK4: case S_TROO_ATK3: case S_SARG_ATK2: case S_BOSS_ATK2: case S_BOS2_ATK2: case S_HEAD_ATK2: case S_SKULL_ATK2: case S_SPID_ATK2: case S_SPID_ATK3: case S_BSPI_ATK2: case S_CYBER_ATK2: case S_CYBER_ATK4: case S_CYBER_ATK6: case S_PAIN_ATK3:
default: sfx = 0; break;
sfx = sfx_shotgn; break; sfx = sfx_claw; break; sfx = sfx_sgtatk; break;
sfx = sfx_firsht; break; sfx = sfx_sklatk; break;
sfx = sfx_shotgn; break; sfx = sfx_plasma; break;
sfx = sfx_rlaunc; break; sfx = sfx_sklatk; 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
//
113
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);
114
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--)
115
{
*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));
}
116

//
// 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;
}
}
}
4.2f finale.h
// Emacs style mode select -*- C++ -*- //-----------------------------------------------------------------------------
//
//$Id:$
//Copyright (C) 1993-1996 by id Software, Inc.
//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.
//
// DESCRIPTION:
//
//
117

//-----------------------------------------------------------------------------
#ifndef __F_FINALE__ #define __F_FINALE__
#include "doomtype.h" #include "d_event.h"
//
//FINALE
//Called by main loop.
boolean F_Responder (event_t* ev);
//Called by main loop. void F_Ticker (void);
//Called by main loop. void F_Drawer (void);
void F_StartFinale (void);
#endif
//-----------------------------------------------------------------------------
//
// $Log:$
//
//-----------------------------------------------------------------------------
4.3 f wipe.c
// Emacs style mode select -*- C++ -*- //-----------------------------------------------------------------------------
//
//$Id:$
//Copyright (C) 1993-1996 by id Software, Inc.
//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.
//
//$Log:$
//DESCRIPTION:
//Mission begin melt/wipe screen special effect.
//-----------------------------------------------------------------------------
static const char rcsid[] = "$Id: f_wipe.c,v 1.2 1997/02/03 22:45:09 b1 Exp $";
118
#include "z_zone.h" #include "i_video.h" #include "v_video.h" #include "m_random.h"
#include "doomdef.h"
#include "f_wipe.h"
//
// SCREEN WIPE PACKAGE
//
// when zero, stop the wipe
static boolean |
go = 0; |
|
static byte* |
wipe_scr_start; |
|
static |
byte* |
wipe_scr_end; |
static |
byte* |
wipe_scr; |
void wipe_shittyColMajorXform
( short* |
array, |
int |
width, |
int |
height ) |
{ |
|
int |
x; |
int |
y; |
short* |
dest; |
dest = (short*) Z_Malloc(width*height*2, PU_STATIC, 0);
for(y=0;y<height;y++)
for(x=0;x<width;x++)
dest[x*height+y] = array[y*width+x];
memcpy(array, dest, width*height*2);
Z_Free(dest);
}
int wipe_initColorXForm
( int |
width, |
int |
height, |
int |
ticks ) |
{ |
|
memcpy(wipe_scr, wipe_scr_start, width*height); return 0;
}
int wipe_doColorXForm
( int |
width, |
int |
height, |
int |
ticks ) |
{ |
|
boolean |
changed; |
byte* |
w; |
byte* |
e; |
int |
newval; |
119
changed = false; w = wipe_scr;
e = wipe_scr_end;
while (w!=wipe_scr+width*height)
{
if (*w != *e)
{
if (*w > *e)
{
newval = *w - ticks; if (newval < *e)
*w = *e;
else
*w = newval; changed = true;
}
else if (*w < *e)
{
newval = *w + ticks; if (newval > *e)
*w = *e;
else
*w = newval; changed = true;
}
}
w++;
e++;
}
return !changed;
}
int wipe_exitColorXForm
( int |
width, |
int |
height, |
int |
ticks ) |
{ |
|
return 0; |
|
} |
|
static int* |
y; |
int |
|
wipe_initMelt |
|
( int |
width, |
int |
height, |
int |
ticks ) |
{ |
|
int i, r; |
|
// copy start screen to main screen memcpy(wipe_scr, wipe_scr_start, width*height);
// makes this wipe faster (in theory) // to have stuff in column-major format
wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height); wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height);
//setup initial column positions
//(y<0 => not ready to scroll yet)
120