f_finale.c 14 KB

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