Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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 "m_swap.h"
  32. #include "i_system.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.