f_finale.cpp 18 KB

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