f_finale.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:16k
源码类别:

射击游戏

开发平台:

Visual C++

  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.
  11. //
  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.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. // Game completion, final screen animation.
  21. //
  22. //-----------------------------------------------------------------------------
  23. static const char
  24. rcsid[] = "$Id: f_finale.c,v 1.5 1997/02/03 21:26:34 b1 Exp $";
  25. #include <ctype.h>
  26. // Functions.
  27. #include "i_system.h"
  28. #include "m_swap.h"
  29. #include "z_zone.h"
  30. #include "v_video.h"
  31. #include "w_wad.h"
  32. #include "s_sound.h"
  33. // Data.
  34. #include "dstrings.h"
  35. #include "sounds.h"
  36. #include "doomstat.h"
  37. #include "r_state.h"
  38. // ?
  39. //#include "doomstat.h"
  40. //#include "r_local.h"
  41. //#include "f_finale.h"
  42. // Stage of animation:
  43. //  0 = text, 1 = art screen, 2 = character cast
  44. int finalestage;
  45. int finalecount;
  46. #define TEXTSPEED 3
  47. #define TEXTWAIT 250
  48. char* e1text = E1TEXT;
  49. char* e2text = E2TEXT;
  50. char* e3text = E3TEXT;
  51. char* e4text = E4TEXT;
  52. char* c1text = C1TEXT;
  53. char* c2text = C2TEXT;
  54. char* c3text = C3TEXT;
  55. char* c4text = C4TEXT;
  56. char* c5text = C5TEXT;
  57. char* c6text = C6TEXT;
  58. char* p1text = P1TEXT;
  59. char* p2text = P2TEXT;
  60. char* p3text = P3TEXT;
  61. char* p4text = P4TEXT;
  62. char* p5text = P5TEXT;
  63. char* p6text = P6TEXT;
  64. char* t1text = T1TEXT;
  65. char* t2text = T2TEXT;
  66. char* t3text = T3TEXT;
  67. char* t4text = T4TEXT;
  68. char* t5text = T5TEXT;
  69. char* t6text = T6TEXT;
  70. char* finaletext;
  71. char* finaleflat;
  72. void F_StartCast (void);
  73. void F_CastTicker (void);
  74. boolean F_CastResponder (event_t *ev);
  75. void F_CastDrawer (void);
  76. extern boolean plutonia, tnt;
  77. void WriteDebug(char *);
  78. //
  79. // F_StartFinale
  80. //
  81. void F_StartFinale (void)
  82. {
  83.     gameaction = ga_nothing;
  84.     gamestate = GS_FINALE;
  85.     viewactive = false;
  86.     automapactive = false;
  87.     // Okay - IWAD dependend stuff.
  88.     // This has been changed severly, and
  89.     //  some stuff might have changed in the process.
  90.     switch ( gamemode )
  91.     {
  92.       // DOOM 1 - E1, E3 or E4, but each nine missions
  93.       case shareware:
  94.       case registered:
  95.       case retail:
  96.       {
  97. S_ChangeMusic(mus_victor, true);
  98. switch (gameepisode)
  99. {
  100.   case 1:
  101.     finaleflat = "FLOOR4_8";
  102.     finaletext = e1text;
  103.     break;
  104.   case 2:
  105.     finaleflat = "SFLR6_1";
  106.     finaletext = e2text;
  107.     break;
  108.   case 3:
  109.     finaleflat = "MFLR8_4";
  110.     finaletext = e3text;
  111.     break;
  112.   case 4:
  113.     finaleflat = "MFLR8_3";
  114.     finaletext = e4text;
  115.     break;
  116.   default:
  117.     // Ouch.
  118.     break;
  119. }
  120. break;
  121.       }
  122.       
  123.       // DOOM II and missions packs with E1, M34
  124.       case commercial:
  125.       {
  126.   S_ChangeMusic(mus_read_m, true);
  127.   switch (gamemap)
  128.   {
  129.     case 6:
  130.       finaleflat = "SLIME16";
  131.           if (tnt == TRUE)
  132.              finaletext = t1text;
  133.           else
  134.           if (plutonia == TRUE)
  135.              finaletext = p1text;
  136.           else
  137.          finaletext = c1text;
  138.       break;
  139.     case 11:
  140.       finaleflat = "RROCK14";
  141.           if (tnt == TRUE)
  142.              finaletext = t2text;
  143.           else
  144.           if (plutonia == TRUE)
  145.              finaletext = p2text;
  146.           else
  147.       finaletext = c2text;
  148.       break;
  149.     case 20:
  150.       finaleflat = "RROCK07";
  151.           if (tnt == TRUE)
  152.              finaletext = t3text;
  153.           else
  154.           if (plutonia == TRUE)
  155.              finaletext = p3text;
  156.           else
  157.       finaletext = c3text;
  158.       break;
  159.     case 30:
  160.       finaleflat = "RROCK17";
  161.           if (tnt == TRUE)
  162.              finaletext = t4text;
  163.           else
  164.           if (plutonia == TRUE)
  165.              finaletext = p4text;
  166.           else
  167.       finaletext = c4text;
  168.       break;
  169.     case 15:
  170.       finaleflat = "RROCK13";
  171.           if (tnt == TRUE)
  172.              finaletext = t5text;
  173.           else
  174.           if (plutonia == TRUE)
  175.              finaletext = p5text;
  176.           else
  177.       finaletext = c5text;
  178.       break;
  179.     case 31:
  180.       finaleflat = "RROCK19";
  181.           if (tnt == TRUE)
  182.              finaletext = t6text;
  183.           else
  184.           if (plutonia == TRUE)
  185.              finaletext = p6text;
  186.           else
  187.       finaletext = c6text;
  188.       break;
  189.     default:
  190.       // Ouch.
  191.       break;
  192.   }
  193.   break;
  194.       }
  195.    
  196.       // Indeterminate.
  197.       default:
  198. S_ChangeMusic(mus_read_m, true);
  199. finaleflat = "F_SKY1"; // Not used anywhere else.
  200. finaletext = c1text;  // FIXME - other text, music?
  201. break;
  202.     }
  203.     
  204.     finalestage = 0;
  205.     finalecount = 0;
  206. }
  207. boolean F_Responder (event_t *event)
  208. {
  209.     if (finalestage == 2)
  210. return F_CastResponder (event);
  211.     return false;
  212. }
  213. //
  214. // F_Ticker
  215. //
  216. void F_Ticker (void)
  217. {
  218.     int i;
  219.     
  220.     // check for skipping
  221.     if ( (gamemode == commercial)
  222.       && ( finalecount > 50) )
  223.     {
  224.       // go on to the next level
  225.       for (i=0 ; i<MAXPLAYERS ; i++)
  226. if (players[i].cmd.buttons)
  227.   break;
  228.       if (i < MAXPLAYERS)
  229.       {
  230. if (gamemap == 30)
  231.   F_StartCast ();
  232. else
  233.   gameaction = ga_worlddone;
  234.       }
  235.     }
  236.     
  237.     // advance animation
  238.     finalecount++;
  239.     if (finalestage == 2)
  240.     {
  241. F_CastTicker ();
  242. return;
  243.     }
  244.     if ( gamemode == commercial)
  245. return;
  246.     if (!finalestage && (unsigned)finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT)
  247.     {
  248. finalecount = 0;
  249. finalestage = 1;
  250. wipegamestate = -1; // force a wipe
  251. if (gameepisode == 3)
  252.     S_StartMusic (mus_bunny);
  253.     }
  254. }
  255. //
  256. // F_TextWrite
  257. //
  258. #include "hu_stuff.h"
  259. extern patch_t *hu_font[HU_FONTSIZE];
  260. void F_TextWrite (void)
  261.    {
  262.     byte* src;
  263.     byte* dest;
  264.     
  265.     int x,y,w;
  266.     int count;
  267.     char* ch;
  268.     int c;
  269.     int cx;
  270.     int cy;
  271.     
  272.     // erase the entire screen to a tiled background
  273.     src = W_CacheLumpName ( finaleflat , PU_CACHE);
  274.     dest = screens[0];
  275.     for (y = 0; y < SCREENHEIGHT; y++)
  276.        {
  277.         for (x = 0; x < SCREENWIDTH/64; x++)
  278.            {
  279.             memcpy (dest, src+((y&63)<<6), 64);
  280.             dest += 64;
  281.            }
  282.        if (SCREENWIDTH&63)
  283.           {
  284.            memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
  285.            dest += (SCREENWIDTH&63);
  286.           }
  287.       }
  288.     V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
  289.     
  290.     // draw some of the text onto the screen
  291.     cx = ((SCREENWIDTH-320)/2)+10;
  292.     cy = ((SCREENHEIGHT-200)/2)+10;
  293.     ch = finaletext;
  294.     count = (finalecount - 10)/TEXTSPEED;
  295.     if (count < 0)
  296.         count = 0;
  297.     for ( ; count ; count-- )
  298.        {
  299.         c = *ch++;
  300.         if (!c)
  301.             break;
  302.         if (c == 'n')
  303.            {
  304.             cx = ((SCREENWIDTH-320)/2)+10;
  305.             cy += 11;
  306.             continue;
  307.            }
  308.         c = toupper(c) - HU_FONTSTART;
  309.         if (c < 0 || c> HU_FONTSIZE)
  310.            {
  311.             cx += 4;
  312.             continue;
  313.            }
  314.         w = SHORT (hu_font[c]->width);
  315.         if (cx+w > SCREENWIDTH)
  316.             break;
  317.         V_DrawPatch(cx, cy, 0, hu_font[c]);
  318.         cx += w;
  319.        }
  320.    }
  321. //
  322. // Final DOOM 2 animation
  323. // Casting by id Software.
  324. //   in order of appearance
  325. //
  326. typedef struct
  327. {
  328.     char *name;
  329.     mobjtype_t type;
  330. } castinfo_t;
  331. castinfo_t castorder[] = {
  332.     {CC_ZOMBIE, MT_POSSESSED},
  333.     {CC_SHOTGUN, MT_SHOTGUY},
  334.     {CC_HEAVY, MT_CHAINGUY},
  335.     {CC_IMP, MT_TROOP},
  336.     {CC_DEMON, MT_SERGEANT},
  337.     {CC_LOST, MT_SKULL},
  338.     {CC_CACO, MT_HEAD},
  339.     {CC_HELL, MT_KNIGHT},
  340.     {CC_BARON, MT_BRUISER},
  341.     {CC_ARACH, MT_BABY},
  342.     {CC_PAIN, MT_PAIN},
  343.     {CC_REVEN, MT_UNDEAD},
  344.     {CC_MANCU, MT_FATSO},
  345.     {CC_ARCH, MT_VILE},
  346.     {CC_SPIDER, MT_SPIDER},
  347.     {CC_CYBER, MT_CYBORG},
  348.     {CC_HERO, MT_PLAYER},
  349.     {NULL,0}
  350. };
  351. int castnum;
  352. int casttics;
  353. state_t* caststate;
  354. boolean castdeath;
  355. int castframes;
  356. int castonmelee;
  357. boolean castattacking;
  358. //
  359. // F_StartCast
  360. //
  361. extern gamestate_t     wipegamestate;
  362. void F_StartCast (void)
  363. {
  364.     wipegamestate = -1; // force a screen wipe
  365.     castnum = 0;
  366.     caststate = &states[mobjinfo[castorder[castnum].type].seestate];
  367.     casttics = caststate->tics;
  368.     castdeath = false;
  369.     finalestage = 2;
  370.     castframes = 0;
  371.     castonmelee = 0;
  372.     castattacking = false;
  373.     S_ChangeMusic(mus_evil, true);
  374. }
  375. //
  376. // F_CastTicker
  377. //
  378. void F_CastTicker (void)
  379. {
  380.     int st;
  381.     int sfx;
  382.     if (--casttics > 0)
  383. return; // not time to change state yet
  384.     if (caststate->tics == -1 || caststate->nextstate == S_NULL)
  385.     {
  386. // switch from deathstate to next monster
  387. castnum++;
  388. castdeath = false;
  389. if (castorder[castnum].name == NULL)
  390.     castnum = 0;
  391. if (mobjinfo[castorder[castnum].type].seesound)
  392.     S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound);
  393. caststate = &states[mobjinfo[castorder[castnum].type].seestate];
  394. castframes = 0;
  395.     }
  396.     else
  397.     {
  398. // just advance to next state in animation
  399. if (caststate == &states[S_PLAY_ATK1])
  400.     goto stopattack; // Oh, gross hack!
  401. st = caststate->nextstate;
  402. caststate = &states[st];
  403. castframes++;
  404. // sound hacks....
  405. switch (st)
  406. {
  407.   case S_PLAY_ATK1: sfx = sfx_dshtgn; break;
  408.   case S_POSS_ATK2: sfx = sfx_pistol; break;
  409.   case S_SPOS_ATK2: sfx = sfx_shotgn; break;
  410.   case S_VILE_ATK2: sfx = sfx_vilatk; break;
  411.   case S_SKEL_FIST2: sfx = sfx_skeswg; break;
  412.   case S_SKEL_FIST4: sfx = sfx_skepch; break;
  413.   case S_SKEL_MISS2: sfx = sfx_skeatk; break;
  414.   case S_FATT_ATK8:
  415.   case S_FATT_ATK5:
  416.   case S_FATT_ATK2: sfx = sfx_firsht; break;
  417.   case S_CPOS_ATK2:
  418.   case S_CPOS_ATK3:
  419.   case S_CPOS_ATK4: sfx = sfx_shotgn; break;
  420.   case S_TROO_ATK3: sfx = sfx_claw; break;
  421.   case S_SARG_ATK2: sfx = sfx_sgtatk; break;
  422.   case S_BOSS_ATK2:
  423.   case S_BOS2_ATK2:
  424.   case S_HEAD_ATK2: sfx = sfx_firsht; break;
  425.   case S_SKULL_ATK2: sfx = sfx_sklatk; break;
  426.   case S_SPID_ATK2:
  427.   case S_SPID_ATK3: sfx = sfx_shotgn; break;
  428.   case S_BSPI_ATK2: sfx = sfx_plasma; break;
  429.   case S_CYBER_ATK2:
  430.   case S_CYBER_ATK4:
  431.   case S_CYBER_ATK6: sfx = sfx_rlaunc; break;
  432.   case S_PAIN_ATK3: sfx = sfx_sklatk; break;
  433.   default: sfx = 0; break;
  434. }
  435. if (sfx)
  436.     S_StartSound (NULL, sfx);
  437.     }
  438.     if (castframes == 12)
  439.     {
  440. // go into attack frame
  441. castattacking = true;
  442. if (castonmelee)
  443.     caststate=&states[mobjinfo[castorder[castnum].type].meleestate];
  444. else
  445.     caststate=&states[mobjinfo[castorder[castnum].type].missilestate];
  446. castonmelee ^= 1;
  447. if (caststate == &states[S_NULL])
  448. {
  449.     if (castonmelee)
  450. caststate=
  451.     &states[mobjinfo[castorder[castnum].type].meleestate];
  452.     else
  453. caststate=
  454.     &states[mobjinfo[castorder[castnum].type].missilestate];
  455. }
  456.     }
  457.     if (castattacking)
  458.     {
  459. if (castframes == 24
  460.     || caststate == &states[mobjinfo[castorder[castnum].type].seestate] )
  461. {
  462.   stopattack:
  463.     castattacking = false;
  464.     castframes = 0;
  465.     caststate = &states[mobjinfo[castorder[castnum].type].seestate];
  466. }
  467.     }
  468.     casttics = caststate->tics;
  469.     if (casttics == -1)
  470. casttics = 15;
  471. }
  472. //
  473. // F_CastResponder
  474. //
  475. boolean F_CastResponder (event_t* ev)
  476. {
  477.     if (ev->type != ev_keydown)
  478. return false;
  479.     if (castdeath)
  480. return true; // already in dying frames
  481.     // go into death frame
  482.     castdeath = true;
  483.     caststate = &states[mobjinfo[castorder[castnum].type].deathstate];
  484.     casttics = caststate->tics;
  485.     castframes = 0;
  486.     castattacking = false;
  487.     if (mobjinfo[castorder[castnum].type].deathsound)
  488. S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound);
  489.     return true;
  490. }
  491. void F_CastPrint (char* text)
  492. {
  493.     char* ch;
  494.     int c;
  495.     int cx;
  496.     int w;
  497.     int width;
  498.     
  499.     // find width
  500.     ch = text;
  501.     width = 0;
  502.     while (ch)
  503.     {
  504. c = *ch++;
  505. if (!c)
  506.     break;
  507. c = toupper(c) - HU_FONTSTART;
  508. if (c < 0 || c> HU_FONTSIZE)
  509. {
  510.     width += 4;
  511.     continue;
  512. }
  513. w = SHORT (hu_font[c]->width);
  514. width += w;
  515.     }
  516.     
  517.     // draw it
  518.     cx = (SCREENWIDTH/2)-width/2;
  519.     ch = text;
  520.     while (ch)
  521.     {
  522. c = *ch++;
  523. if (!c)
  524.     break;
  525. c = toupper(c) - HU_FONTSTART;
  526. if (c < 0 || c> HU_FONTSIZE)
  527. {
  528.     cx += 4;
  529.     continue;
  530. }
  531. w = SHORT (hu_font[c]->width);
  532. V_DrawPatch(cx, ((SCREENHEIGHT-200)/2)+180, 0, hu_font[c]);
  533. cx+=w;
  534.     }
  535. }
  536. //
  537. // F_CastDrawer
  538. //
  539. void V_DrawPatchFlipped (int x, int y, int scrn, patch_t *patch);
  540. void F_CastDrawer (void)
  541. {
  542.     spritedef_t* sprdef;
  543.     spriteframe_t* sprframe;
  544.     int lump;
  545.     boolean flip;
  546.     patch_t* patch;
  547.     
  548.     // erase the entire screen to a background
  549.     V_DrawPatch (((SCREENWIDTH-320)/2)+0,((SCREENHEIGHT-200)/2)+0,0, W_CacheLumpName ("BOSSBACK", PU_CACHE));
  550.     F_CastPrint (castorder[castnum].name);
  551.     
  552.     // draw the current frame in the middle of the screen
  553.     sprdef = &sprites[caststate->sprite];
  554.     sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK];
  555.     lump = sprframe->lump[0];
  556.     flip = (boolean)sprframe->flip[0];
  557.     patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE);
  558.     if (flip)
  559. V_DrawPatchFlipped ((SCREENWIDTH/2),((SCREENHEIGHT-200)/2)+170,0,patch);
  560.     else
  561. V_DrawPatch ((SCREENWIDTH/2),((SCREENHEIGHT-200)/2)+170,0,patch);
  562. }
  563. //
  564. // F_DrawPatchCol
  565. //
  566. void
  567. F_DrawPatchCol
  568. ( int x,
  569.   patch_t* patch,
  570.   int col )
  571. {
  572.     column_t* column;
  573.     byte* source;
  574.     byte* dest;
  575.     byte* desttop;
  576.     int count;
  577.     column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
  578.     desttop = screens[0]+x+(((SCREENHEIGHT-200)/2)*(SCREENWIDTH));
  579.     // step through the posts in a column
  580.     while (column->topdelta != 0xff )
  581.     {
  582. source = (byte *)column + 3;
  583. dest = desttop + column->topdelta*SCREENWIDTH;
  584. count = column->length;
  585. while (count--)
  586. {
  587.     *dest = *source++;
  588.     dest += SCREENWIDTH;
  589. }
  590. column = (column_t *)(  (byte *)column + column->length + 4 );
  591.     }
  592. }
  593. //
  594. // F_BunnyScroll
  595. //
  596. void F_BunnyScroll (void)
  597. {
  598.     int scrolled;
  599.     int x, xx;
  600.     patch_t* p1;
  601.     patch_t* p2;
  602.     char name[10];
  603.     int stage;
  604.     static int laststage;
  605.     WriteDebug("Entering F_BunnyScroll...n");
  606.     p1 = W_CacheLumpName ("PFUB2", PU_LEVEL);
  607.     p2 = W_CacheLumpName ("PFUB1", PU_LEVEL);
  608.     V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
  609.     scrolled = 320 - (finalecount-230)/2;
  610.     if (scrolled > 320)
  611.         scrolled = 320;
  612.     if (scrolled < 0)
  613.         scrolled = 0;
  614.     //for (x = 0; x < SCREENWIDTH ; x++)
  615.     for (x = ((SCREENWIDTH-320)/2), xx = 0; x < ((SCREENWIDTH-320)/2)+320; x++, xx++)
  616.     {
  617. if (xx + scrolled < 320)
  618.     F_DrawPatchCol (x, p1, xx+scrolled);
  619. else
  620.     F_DrawPatchCol (x, p2, xx+scrolled - 320);
  621.     }
  622.     if (finalecount < 1130)
  623. return;
  624.     if (finalecount < 1180)
  625.     {
  626. V_DrawPatch ((SCREENWIDTH-13*8)/2,
  627.      (SCREENHEIGHT-8*8)/2,0, W_CacheLumpName ("END0",PU_CACHE));
  628. laststage = 0;
  629. return;
  630.     }
  631.     stage = (finalecount-1180) / 5;
  632.     if (stage > 6)
  633. stage = 6;
  634.     if (stage > laststage)
  635.     {
  636. S_StartSound (NULL, sfx_pistol);
  637. laststage = stage;
  638.     }
  639.     sprintf (name,"END%i",stage);
  640.     V_DrawPatch ((SCREENWIDTH-13*8)/2, (SCREENHEIGHT-8*8)/2,0, W_CacheLumpName (name,PU_CACHE));
  641. }
  642. //
  643. // F_Drawer
  644. //
  645. void F_Drawer (void)
  646. {
  647.     if (finalestage == 2)
  648.     {
  649. F_CastDrawer ();
  650. return;
  651.     }
  652.     if (!finalestage)
  653. F_TextWrite ();
  654.     else
  655.     {
  656. switch (gameepisode)
  657. {
  658.   case 1:
  659.     if ( gamemode == retail )
  660.       V_DrawPatch (0,0,0,
  661.  W_CacheLumpName("CREDIT",PU_CACHE));
  662.     else
  663.       V_DrawPatch (0,0,0,
  664.  W_CacheLumpName("HELP2",PU_CACHE));
  665.     break;
  666.   case 2:
  667.     V_DrawPatch(0,0,0,
  668. W_CacheLumpName("VICTORY2",PU_CACHE));
  669.     break;
  670.   case 3:
  671.     F_BunnyScroll ();
  672.     break;
  673.   case 4:
  674.     V_DrawPatch (0,0,0,
  675.  W_CacheLumpName("ENDPIC",PU_CACHE));
  676.     break;
  677. }
  678.     }
  679. }