forgotten commit. disabled until egl is adapted.
[AROS-Contrib.git] / Games / Doom / f_finale.c
blob4dbe2589746e63c7faf7012462a4f8e872345a63
1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
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
15 // for more details.
17 // $Log$
18 // Revision 1.1 2000/02/29 18:21:04 stegerg
19 // Doom port based on ADoomPPC. Read README.AROS!
22 // DESCRIPTION:
23 // Game completion, final screen animation.
25 //-----------------------------------------------------------------------------
28 static const char
29 rcsid[] = "$Id$";
31 #include <ctype.h>
33 // Functions.
34 #include "i_system.h"
35 #include "i_video.h"
36 #include "m_swap.h"
37 #include "z_zone.h"
38 #include "v_video.h"
39 #include "w_wad.h"
40 #include "s_sound.h"
42 // Data.
43 #include "dstrings.h"
44 #include "sounds.h"
46 #include "doomstat.h"
47 #include "r_state.h"
49 // ?
50 //#include "doomstat.h"
51 //#include "r_local.h"
52 //#include "f_finale.h"
54 // Stage of animation:
55 // 0 = text, 1 = art screen, 2 = character cast
56 int finalestage;
58 int finalecount;
60 #define TEXTSPEED 3
61 #define TEXTWAIT 250
63 char* e1text = E1TEXT;
64 char* e2text = E2TEXT;
65 char* e3text = E3TEXT;
66 char* e4text = E4TEXT;
68 char* c1text = C1TEXT;
69 char* c2text = C2TEXT;
70 char* c3text = C3TEXT;
71 char* c4text = C4TEXT;
72 char* c5text = C5TEXT;
73 char* c6text = C6TEXT;
75 char* p1text = P1TEXT;
76 char* p2text = P2TEXT;
77 char* p3text = P3TEXT;
78 char* p4text = P4TEXT;
79 char* p5text = P5TEXT;
80 char* p6text = P6TEXT;
82 char* t1text = T1TEXT;
83 char* t2text = T2TEXT;
84 char* t3text = T3TEXT;
85 char* t4text = T4TEXT;
86 char* t5text = T5TEXT;
87 char* t6text = T6TEXT;
89 char* finaletext;
90 char* finaleflat;
92 void F_StartCast (void);
93 void F_CastTicker (void);
94 boolean F_CastResponder (event_t *ev);
95 void F_CastDrawer (void);
98 // F_StartFinale
100 void F_StartFinale (void)
102 gameaction = ga_nothing;
103 gamestate = GS_FINALE;
104 viewactive = false;
105 automapactive = false;
107 // Okay - IWAD dependend stuff.
108 // This has been changed severly, and
109 // some stuff might have changed in the process.
110 switch ( gamemode )
113 // DOOM 1 - E1, E3 or E4, but each nine missions
114 case shareware:
115 case registered:
116 case retail:
118 S_ChangeMusic(mus_victor, true);
120 switch (gameepisode)
122 case 1:
123 finaleflat = "FLOOR4_8";
124 finaletext = e1text;
125 break;
126 case 2:
127 finaleflat = "SFLR6_1";
128 finaletext = e2text;
129 break;
130 case 3:
131 finaleflat = "MFLR8_4";
132 finaletext = e3text;
133 break;
134 case 4:
135 finaleflat = "MFLR8_3";
136 finaletext = e4text;
137 break;
138 default:
139 // Ouch.
140 break;
142 break;
145 // DOOM II and missions packs with E1, M34
146 case commercial:
148 S_ChangeMusic(mus_read_m, true);
150 switch (gamemap)
152 case 6:
153 finaleflat = "SLIME16";
154 finaletext = c1text;
155 break;
156 case 11:
157 finaleflat = "RROCK14";
158 finaletext = c2text;
159 break;
160 case 20:
161 finaleflat = "RROCK07";
162 finaletext = c3text;
163 break;
164 case 30:
165 finaleflat = "RROCK17";
166 finaletext = c4text;
167 break;
168 case 15:
169 finaleflat = "RROCK13";
170 finaletext = c5text;
171 break;
172 case 31:
173 finaleflat = "RROCK19";
174 finaletext = c6text;
175 break;
176 default:
177 // Ouch.
178 break;
180 break;
184 // Indeterminate.
185 default:
186 S_ChangeMusic(mus_read_m, true);
187 finaleflat = "F_SKY1"; // Not used anywhere else.
188 finaletext = c1text; // FIXME - other text, music?
189 break;
192 finalestage = 0;
193 finalecount = 0;
199 boolean F_Responder (event_t *event)
201 if (finalestage == 2)
202 return F_CastResponder (event);
204 return false;
209 // F_Ticker
211 void F_Ticker (void)
213 int i;
215 // check for skipping
216 if ( (gamemode == commercial)
217 && ( finalecount > 50) )
219 // go on to the next level
220 for (i=0 ; i<MAXPLAYERS ; i++)
221 if (players[i].cmd.buttons)
222 break;
224 if (i < MAXPLAYERS)
226 if (gamemap == 30)
227 F_StartCast ();
228 else
229 gameaction = ga_worlddone;
233 // advance animation
234 finalecount++;
236 if (finalestage == 2)
238 F_CastTicker ();
239 return;
242 if ( gamemode == commercial)
243 return;
245 if (!finalestage && finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT)
247 finalecount = 0;
248 finalestage = 1;
249 wipegamestate = -1; // force a wipe
250 if (gameepisode == 3)
251 S_StartMusic (mus_bunny);
258 // F_TextWrite
261 #include "hu_stuff.h"
262 extern patch_t *hu_font[HU_FONTSIZE];
265 void F_TextWrite (void)
267 byte* src;
268 byte* dest;
270 int x,y,w;
271 int count;
272 char* ch;
273 int c;
274 int cx;
275 int cy;
277 // erase the entire screen to a tiled background
278 src = W_CacheLumpName ( finaleflat , PU_CACHE);
279 dest = screens[0];
281 for (y=0 ; y<SCREENHEIGHT ; y++)
283 for (x=0 ; x<SCREENWIDTH/64 ; x++)
285 memcpy (dest, src+((y&63)<<6), 64);
286 dest += 64;
288 if (SCREENWIDTH&63)
290 memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
291 dest += (SCREENWIDTH&63);
295 // draw some of the text onto the screen
296 cx = 10;
297 cy = 10;
298 ch = finaletext;
300 count = (finalecount - 10)/TEXTSPEED;
301 if (count < 0)
302 count = 0;
303 for ( ; count ; count-- )
305 c = *ch++;
306 if (!c)
307 break;
308 if (c == '\n')
310 cx = 10;
311 cy += 11;
312 continue;
315 c = toupper(c) - HU_FONTSTART;
316 if (c < 0 || c> HU_FONTSIZE)
318 cx += 4;
319 continue;
322 w = SWAPSHORT (hu_font[c]->width);
323 if (cx+w > SCREENWIDTH)
324 break;
325 V_DrawPatchInDirect(cx, cy, 0, hu_font[c]);
326 cx+=w;
329 I_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
334 // Final DOOM 2 animation
335 // Casting by id Software.
336 // in order of appearance
338 typedef struct
340 char *name;
341 mobjtype_t type;
342 } castinfo_t;
344 castinfo_t castorder[] = {
345 {CC_ZOMBIE, MT_POSSESSED},
346 {CC_SHOTGUN, MT_SHOTGUY},
347 {CC_HEAVY, MT_CHAINGUY},
348 {CC_IMP, MT_TROOP},
349 {CC_DEMON, MT_SERGEANT},
350 {CC_LOST, MT_SKULL},
351 {CC_CACO, MT_HEAD},
352 {CC_HELL, MT_KNIGHT},
353 {CC_BARON, MT_BRUISER},
354 {CC_ARACH, MT_BABY},
355 {CC_PAIN, MT_PAIN},
356 {CC_REVEN, MT_UNDEAD},
357 {CC_MANCU, MT_FATSO},
358 {CC_ARCH, MT_VILE},
359 {CC_SPIDER, MT_SPIDER},
360 {CC_CYBER, MT_CYBORG},
361 {CC_HERO, MT_PLAYER},
363 {NULL,0}
366 int castnum;
367 int casttics;
368 state_t* caststate;
369 boolean castdeath;
370 int castframes;
371 int castonmelee;
372 boolean castattacking;
376 // F_StartCast
378 extern gamestate_t wipegamestate;
381 void F_StartCast (void)
383 wipegamestate = -1; // force a screen wipe
384 castnum = 0;
385 caststate = &states[mobjinfo[castorder[castnum].type].seestate];
386 casttics = caststate->tics;
387 castdeath = false;
388 finalestage = 2;
389 castframes = 0;
390 castonmelee = 0;
391 castattacking = false;
392 S_ChangeMusic(mus_evil, true);
397 // F_CastTicker
399 void F_CastTicker (void)
401 int st;
402 int sfx;
404 if (--casttics > 0)
405 return; // not time to change state yet
407 if (caststate->tics == -1 || caststate->nextstate == S_NULL)
409 // switch from deathstate to next monster
410 castnum++;
411 castdeath = false;
412 if (castorder[castnum].name == NULL)
413 castnum = 0;
414 if (mobjinfo[castorder[castnum].type].seesound)
415 S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound);
416 caststate = &states[mobjinfo[castorder[castnum].type].seestate];
417 castframes = 0;
419 else
421 // just advance to next state in animation
422 if (caststate == &states[S_PLAY_ATK1])
423 goto stopattack; // Oh, gross hack!
424 st = caststate->nextstate;
425 caststate = &states[st];
426 castframes++;
428 // sound hacks....
429 switch (st)
431 case S_PLAY_ATK1: sfx = sfx_dshtgn; break;
432 case S_POSS_ATK2: sfx = sfx_pistol; break;
433 case S_SPOS_ATK2: sfx = sfx_shotgn; break;
434 case S_VILE_ATK2: sfx = sfx_vilatk; break;
435 case S_SKEL_FIST2: sfx = sfx_skeswg; break;
436 case S_SKEL_FIST4: sfx = sfx_skepch; break;
437 case S_SKEL_MISS2: sfx = sfx_skeatk; break;
438 case S_FATT_ATK8:
439 case S_FATT_ATK5:
440 case S_FATT_ATK2: sfx = sfx_firsht; break;
441 case S_CPOS_ATK2:
442 case S_CPOS_ATK3:
443 case S_CPOS_ATK4: sfx = sfx_shotgn; break;
444 case S_TROO_ATK3: sfx = sfx_claw; break;
445 case S_SARG_ATK2: sfx = sfx_sgtatk; break;
446 case S_BOSS_ATK2:
447 case S_BOS2_ATK2:
448 case S_HEAD_ATK2: sfx = sfx_firsht; break;
449 case S_SKULL_ATK2: sfx = sfx_sklatk; break;
450 case S_SPID_ATK2:
451 case S_SPID_ATK3: sfx = sfx_shotgn; break;
452 case S_BSPI_ATK2: sfx = sfx_plasma; break;
453 case S_CYBER_ATK2:
454 case S_CYBER_ATK4:
455 case S_CYBER_ATK6: sfx = sfx_rlaunc; break;
456 case S_PAIN_ATK3: sfx = sfx_sklatk; break;
457 default: sfx = 0; break;
460 if (sfx)
461 S_StartSound (NULL, sfx);
464 if (castframes == 12)
466 // go into attack frame
467 castattacking = true;
468 if (castonmelee)
469 caststate=&states[mobjinfo[castorder[castnum].type].meleestate];
470 else
471 caststate=&states[mobjinfo[castorder[castnum].type].missilestate];
472 castonmelee ^= 1;
473 if (caststate == &states[S_NULL])
475 if (castonmelee)
476 caststate=
477 &states[mobjinfo[castorder[castnum].type].meleestate];
478 else
479 caststate=
480 &states[mobjinfo[castorder[castnum].type].missilestate];
484 if (castattacking)
486 if (castframes == 24
487 || caststate == &states[mobjinfo[castorder[castnum].type].seestate] )
489 stopattack:
490 castattacking = false;
491 castframes = 0;
492 caststate = &states[mobjinfo[castorder[castnum].type].seestate];
496 casttics = caststate->tics;
497 if (casttics == -1)
498 casttics = 15;
503 // F_CastResponder
506 boolean F_CastResponder (event_t* ev)
508 if (ev->type != ev_keydown)
509 return false;
511 if (castdeath)
512 return true; // already in dying frames
514 // go into death frame
515 castdeath = true;
516 caststate = &states[mobjinfo[castorder[castnum].type].deathstate];
517 casttics = caststate->tics;
518 castframes = 0;
519 castattacking = false;
520 if (mobjinfo[castorder[castnum].type].deathsound)
521 S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound);
523 return true;
527 void F_CastPrint (char* text)
529 char* ch;
530 int c;
531 int cx;
532 int w;
533 int width;
535 // find width
536 ch = text;
537 width = 0;
539 while (ch)
541 c = *ch++;
542 if (!c)
543 break;
544 c = toupper(c) - HU_FONTSTART;
545 if (c < 0 || c> HU_FONTSIZE)
547 width += 4;
548 continue;
551 w = SWAPSHORT (hu_font[c]->width);
552 width += w;
555 // draw it
556 cx = 160-width/2;
557 ch = text;
558 while (ch)
560 c = *ch++;
561 if (!c)
562 break;
563 c = toupper(c) - HU_FONTSTART;
564 if (c < 0 || c> HU_FONTSIZE)
566 cx += 4;
567 continue;
570 w = SWAPSHORT (hu_font[c]->width);
571 V_DrawPatchInDirect(cx, 180, 0, hu_font[c]);
572 cx+=w;
579 // F_CastDrawer
581 //void V_DrawPatchFlipped (int x, int y, int scrn, patch_t *patch);
583 void F_CastDrawer (void)
585 spritedef_t* sprdef;
586 spriteframe_t* sprframe;
587 int lump;
588 boolean flip;
589 patch_t* patch;
591 // erase the entire screen to a background
592 V_DrawPatchInDirect (0,0,0, W_CacheLumpName ("BOSSBACK", PU_CACHE));
594 F_CastPrint (castorder[castnum].name);
596 // draw the current frame in the middle of the screen
597 sprdef = &sprites[caststate->sprite];
598 sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK];
599 lump = sprframe->lump[0];
600 flip = (boolean)sprframe->flip[0];
602 patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE);
603 if (flip)
604 V_DrawPatchInDirectFlipped (160,170,0,patch);
605 else
606 V_DrawPatchInDirect (160,170,0,patch);
611 // F_DrawPatchCol
613 void
614 F_DrawPatchCol
615 ( int x,
616 patch_t* patch,
617 int col )
619 column_t* column;
620 byte* source;
621 byte* dest;
622 byte* desttop;
623 int count;
625 column = (column_t *)((byte *)patch + SWAPLONG(patch->columnofs[col]));
626 // desttop = screens[0]+x;
627 desttop = screens[0]+x+(SCREENWIDTH-320)/2+SCREENWIDTH*((SCREENHEIGHT-200)/2);
629 // step through the posts in a column
630 while (column->topdelta != 0xff )
632 source = (byte *)column + 3;
633 dest = desttop + column->topdelta*SCREENWIDTH;
634 count = column->length;
636 while (count--)
638 *dest = *source++;
639 dest += SCREENWIDTH;
641 column = (column_t *)( (byte *)column + column->length + 4 );
647 // F_BunnyScroll
649 void F_BunnyScroll (void)
651 int scrolled;
652 int x;
653 patch_t* p1;
654 patch_t* p2;
655 char name[10];
656 int stage;
657 static int laststage;
659 p1 = W_CacheLumpName ("PFUB2", PU_LEVEL);
660 p2 = W_CacheLumpName ("PFUB1", PU_LEVEL);
662 scrolled = 320 - (finalecount-230)/2;
663 if (scrolled > 320)
664 scrolled = 320;
665 if (scrolled < 0)
666 scrolled = 0;
668 // for ( x=0 ; x<SCREENWIDTH ; x++)
669 if ((SCREENWIDTH!=320)||(SCREENHEIGHT!=200))
670 memset(screens[0],2,SCREENWIDTH*SCREENHEIGHT);
671 for ( x=0 ; x<320 ; x++)
673 if (x+scrolled < 320)
674 F_DrawPatchCol (x, p1, x+scrolled);
675 else
676 F_DrawPatchCol (x, p2, x+scrolled - 320);
679 if (finalecount < 1130)
680 return;
681 if (finalecount < 1180)
683 V_DrawPatchInDirect ((320-13*8)/2,
684 (200-8*8)/2,0, W_CacheLumpName ("END0",PU_CACHE));
685 laststage = 0;
686 return;
689 stage = (finalecount-1180) / 5;
690 if (stage > 6)
691 stage = 6;
692 if (stage > laststage)
694 S_StartSound (NULL, sfx_pistol);
695 laststage = stage;
698 sprintf (name,"END%i",stage);
699 V_DrawPatchInDirect ((320-13*8)/2, (200-8*8)/2,0, W_CacheLumpName (name,PU_CACHE));
701 I_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
706 // F_Drawer
708 void F_Drawer (void)
710 if (finalestage == 2)
712 F_CastDrawer ();
713 return;
716 if (!finalestage)
717 F_TextWrite ();
718 else
720 switch (gameepisode)
722 case 1:
723 if ( gamemode == retail )
724 V_DrawPatchInDirect (0,0,0,
725 W_CacheLumpName("CREDIT",PU_CACHE));
726 else
727 V_DrawPatchInDirect (0,0,0,
728 W_CacheLumpName("HELP2",PU_CACHE));
729 break;
730 case 2:
731 V_DrawPatchInDirect(0,0,0,
732 W_CacheLumpName("VICTORY2",PU_CACHE));
733 break;
734 case 3:
735 F_BunnyScroll ();
736 break;
737 case 4:
738 V_DrawPatchInDirect (0,0,0,
739 W_CacheLumpName("ENDPIC",PU_CACHE));
740 break;