home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #2 / amigaacscoverdisc1998-021998.iso / games / doom / source / linuxdoom-1.10 / f_finale.c < prev    next >
C/C++ Source or Header  |  1997-12-22  |  14KB  |  739 lines

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