IN_LUDE.C 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. //**************************************************************************
  2. //**
  3. //** in_lude.c : Heretic 2 : Raven Software, Corp.
  4. //**
  5. //** $RCSfile: in_lude.c,v $
  6. //** $Revision: 1.19 $
  7. //** $Date: 96/01/05 23:33:19 $
  8. //** $Author: bgokey $
  9. //**
  10. //**************************************************************************
  11. #include "h2def.h"
  12. #include <ctype.h>
  13. // MACROS ------------------------------------------------------------------
  14. #define TEXTSPEED 3
  15. #define TEXTWAIT 140
  16. // TYPES -------------------------------------------------------------------
  17. typedef enum
  18. {
  19. SINGLE,
  20. COOPERATIVE,
  21. DEATHMATCH
  22. } gametype_t;
  23. // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
  24. // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
  25. void IN_Start(void);
  26. void IN_Ticker(void);
  27. void IN_Drawer(void);
  28. // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
  29. static void WaitStop(void);
  30. static void Stop(void);
  31. static void LoadPics(void);
  32. static void UnloadPics(void);
  33. static void CheckForSkip(void);
  34. static void InitStats(void);
  35. static void DrDeathTally(void);
  36. static void DrNumber(int val, int x, int y, int wrapThresh);
  37. static void DrNumberBold(int val, int x, int y, int wrapThresh);
  38. static void DrawHubText(void);
  39. // EXTERNAL DATA DECLARATIONS ----------------------------------------------
  40. // PUBLIC DATA DECLARATIONS ------------------------------------------------
  41. boolean intermission;
  42. char ClusterMessage[MAX_INTRMSN_MESSAGE_SIZE];
  43. // PRIVATE DATA DEFINITIONS ------------------------------------------------
  44. static boolean skipintermission;
  45. static int interstate = 0;
  46. static int intertime = -1;
  47. static gametype_t gametype;
  48. static int cnt;
  49. static int slaughterboy; // in DM, the player with the most kills
  50. static patch_t *patchINTERPIC;
  51. static patch_t *FontBNumbers[10];
  52. static patch_t *FontBNegative;
  53. static patch_t *FontBSlash;
  54. static patch_t *FontBPercent;
  55. static int FontABaseLump;
  56. static int FontBLump;
  57. static int FontBLumpBase;
  58. static signed int totalFrags[MAXPLAYERS];
  59. static int HubCount;
  60. static char *HubText;
  61. // CODE --------------------------------------------------------------------
  62. //========================================================================
  63. //
  64. // IN_Start
  65. //
  66. //========================================================================
  67. extern void AM_Stop (void);
  68. void IN_Start(void)
  69. {
  70. int i;
  71. I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
  72. InitStats();
  73. LoadPics();
  74. intermission = true;
  75. interstate = 0;
  76. skipintermission = false;
  77. intertime = 0;
  78. AM_Stop();
  79. for(i = 0; i < MAXPLAYERS; i++)
  80. {
  81. players[i].messageTics = 0;
  82. players[i].message[0] = 0;
  83. }
  84. SN_StopAllSequences();
  85. }
  86. //========================================================================
  87. //
  88. // WaitStop
  89. //
  90. //========================================================================
  91. void WaitStop(void)
  92. {
  93. if(!--cnt)
  94. {
  95. Stop();
  96. // gamestate = GS_LEVEL;
  97. // G_DoLoadLevel();
  98. gameaction = ga_leavemap;
  99. // G_WorldDone();
  100. }
  101. }
  102. //========================================================================
  103. //
  104. // Stop
  105. //
  106. //========================================================================
  107. static void Stop(void)
  108. {
  109. intermission = false;
  110. UnloadPics();
  111. SB_state = -1;
  112. BorderNeedRefresh = true;
  113. }
  114. //========================================================================
  115. //
  116. // InitStats
  117. //
  118. // Initializes the stats for single player mode
  119. //========================================================================
  120. static char *ClusMsgLumpNames[] =
  121. {
  122. "clus1msg",
  123. "clus2msg",
  124. "clus3msg",
  125. "clus4msg",
  126. "clus5msg"
  127. };
  128. static void InitStats(void)
  129. {
  130. int i;
  131. int j;
  132. int oldCluster;
  133. signed int slaughterfrags;
  134. int posnum;
  135. int slaughtercount;
  136. int playercount;
  137. char *msgLumpName;
  138. int msgSize;
  139. int msgLump;
  140. extern int LeaveMap;
  141. if(!deathmatch)
  142. {
  143. gametype = SINGLE;
  144. HubCount = 0;
  145. oldCluster = P_GetMapCluster(gamemap);
  146. if(oldCluster != P_GetMapCluster(LeaveMap))
  147. {
  148. if(oldCluster >= 1 && oldCluster <= 5)
  149. {
  150. msgLumpName = ClusMsgLumpNames[oldCluster-1];
  151. msgLump = W_GetNumForName(msgLumpName);
  152. msgSize = W_LumpLength(msgLump);
  153. if(msgSize >= MAX_INTRMSN_MESSAGE_SIZE)
  154. {
  155. I_Error("Cluster message too long (%s)", msgLumpName);
  156. }
  157. W_ReadLump(msgLump, ClusterMessage);
  158. ClusterMessage[msgSize] = 0; // Append terminator
  159. HubText = ClusterMessage;
  160. HubCount = strlen(HubText)*TEXTSPEED+TEXTWAIT;
  161. S_StartSongName("hub", true);
  162. }
  163. }
  164. }
  165. else
  166. {
  167. gametype = DEATHMATCH;
  168. slaughterboy = 0;
  169. slaughterfrags = -9999;
  170. posnum = 0;
  171. playercount = 0;
  172. slaughtercount = 0;
  173. for(i=0; i<MAXPLAYERS; i++)
  174. {
  175. totalFrags[i] = 0;
  176. if(playeringame[i])
  177. {
  178. playercount++;
  179. for(j=0; j<MAXPLAYERS; j++)
  180. {
  181. if(playeringame[j])
  182. {
  183. totalFrags[i] += players[i].frags[j];
  184. }
  185. }
  186. posnum++;
  187. }
  188. if(totalFrags[i] > slaughterfrags)
  189. {
  190. slaughterboy = 1<<i;
  191. slaughterfrags = totalFrags[i];
  192. slaughtercount = 1;
  193. }
  194. else if(totalFrags[i] == slaughterfrags)
  195. {
  196. slaughterboy |= 1<<i;
  197. slaughtercount++;
  198. }
  199. }
  200. if(playercount == slaughtercount)
  201. { // don't do the slaughter stuff if everyone is equal
  202. slaughterboy = 0;
  203. }
  204. S_StartSongName("hub", true);
  205. }
  206. }
  207. //========================================================================
  208. //
  209. // LoadPics
  210. //
  211. //========================================================================
  212. static void LoadPics(void)
  213. {
  214. int i;
  215. if(HubCount || gametype == DEATHMATCH)
  216. {
  217. patchINTERPIC = W_CacheLumpName("INTERPIC", PU_STATIC);
  218. FontBLumpBase = W_GetNumForName("FONTB16");
  219. for(i=0; i<10; i++)
  220. {
  221. FontBNumbers[i] = W_CacheLumpNum(FontBLumpBase+i, PU_STATIC);
  222. }
  223. FontBLump = W_GetNumForName("FONTB_S")+1;
  224. FontBNegative = W_CacheLumpName("FONTB13", PU_STATIC);
  225. FontABaseLump = W_GetNumForName("FONTA_S")+1;
  226. FontBSlash = W_CacheLumpName("FONTB15", PU_STATIC);
  227. FontBPercent = W_CacheLumpName("FONTB05", PU_STATIC);
  228. }
  229. }
  230. //========================================================================
  231. //
  232. // UnloadPics
  233. //
  234. //========================================================================
  235. static void UnloadPics(void)
  236. {
  237. int i;
  238. if(HubCount || gametype == DEATHMATCH)
  239. {
  240. Z_ChangeTag(patchINTERPIC, PU_CACHE);
  241. for(i=0; i<10; i++)
  242. {
  243. Z_ChangeTag(FontBNumbers[i], PU_CACHE);
  244. }
  245. Z_ChangeTag(FontBNegative, PU_CACHE);
  246. Z_ChangeTag(FontBSlash, PU_CACHE);
  247. Z_ChangeTag(FontBPercent, PU_CACHE);
  248. }
  249. }
  250. //========================================================================
  251. //
  252. // IN_Ticker
  253. //
  254. //========================================================================
  255. void IN_Ticker(void)
  256. {
  257. if(!intermission)
  258. {
  259. return;
  260. }
  261. if(interstate)
  262. {
  263. WaitStop();
  264. return;
  265. }
  266. skipintermission = false;
  267. CheckForSkip();
  268. intertime++;
  269. if(skipintermission || (gametype == SINGLE && !HubCount))
  270. {
  271. interstate = 1;
  272. cnt = 10;
  273. skipintermission = false;
  274. //S_StartSound(NULL, sfx_dorcls);
  275. }
  276. }
  277. //========================================================================
  278. //
  279. // CheckForSkip
  280. //
  281. // Check to see if any player hit a key
  282. //========================================================================
  283. static void CheckForSkip(void)
  284. {
  285. int i;
  286. player_t *player;
  287. static boolean triedToSkip;
  288. for(i = 0, player = players; i < MAXPLAYERS; i++, player++)
  289. {
  290. if(playeringame[i])
  291. {
  292. if(player->cmd.buttons&BT_ATTACK)
  293. {
  294. if(!player->attackdown)
  295. {
  296. skipintermission = 1;
  297. }
  298. player->attackdown = true;
  299. }
  300. else
  301. {
  302. player->attackdown = false;
  303. }
  304. if(player->cmd.buttons&BT_USE)
  305. {
  306. if(!player->usedown)
  307. {
  308. skipintermission = 1;
  309. }
  310. player->usedown = true;
  311. }
  312. else
  313. {
  314. player->usedown = false;
  315. }
  316. }
  317. }
  318. if(deathmatch && intertime < 140)
  319. { // wait for 4 seconds before allowing a skip
  320. if(skipintermission == 1)
  321. {
  322. triedToSkip = true;
  323. skipintermission = 0;
  324. }
  325. }
  326. else
  327. {
  328. if(triedToSkip)
  329. {
  330. skipintermission = 1;
  331. triedToSkip = false;
  332. }
  333. }
  334. }
  335. //========================================================================
  336. //
  337. // IN_Drawer
  338. //
  339. //========================================================================
  340. void IN_Drawer(void)
  341. {
  342. if(!intermission)
  343. {
  344. return;
  345. }
  346. if(interstate)
  347. {
  348. return;
  349. }
  350. UpdateState |= I_FULLSCRN;
  351. memcpy(screen, (byte *)patchINTERPIC, SCREENWIDTH*SCREENHEIGHT);
  352. if(gametype == SINGLE)
  353. {
  354. if(HubCount)
  355. {
  356. DrawHubText();
  357. }
  358. }
  359. else
  360. {
  361. DrDeathTally();
  362. }
  363. }
  364. //========================================================================
  365. //
  366. // DrDeathTally
  367. //
  368. //========================================================================
  369. #define TALLY_EFFECT_TICKS 20
  370. #define TALLY_FINAL_X_DELTA (23*FRACUNIT)
  371. #define TALLY_FINAL_Y_DELTA (13*FRACUNIT)
  372. #define TALLY_START_XPOS (178*FRACUNIT)
  373. #define TALLY_STOP_XPOS (90*FRACUNIT)
  374. #define TALLY_START_YPOS (132*FRACUNIT)
  375. #define TALLY_STOP_YPOS (83*FRACUNIT)
  376. #define TALLY_TOP_X 85
  377. #define TALLY_TOP_Y 9
  378. #define TALLY_LEFT_X 7
  379. #define TALLY_LEFT_Y 71
  380. #define TALLY_TOTALS_X 291
  381. static void DrDeathTally(void)
  382. {
  383. int i, j;
  384. fixed_t xPos, yPos;
  385. fixed_t xDelta, yDelta;
  386. fixed_t xStart, scale;
  387. int x, y;
  388. boolean bold;
  389. static boolean showTotals;
  390. int temp;
  391. V_DrawPatch(TALLY_TOP_X, TALLY_TOP_Y,
  392. W_CacheLumpName("tallytop", PU_CACHE));
  393. V_DrawPatch(TALLY_LEFT_X, TALLY_LEFT_Y,
  394. W_CacheLumpName("tallylft", PU_CACHE));
  395. if(intertime < TALLY_EFFECT_TICKS)
  396. {
  397. showTotals = false;
  398. scale = (intertime*FRACUNIT)/TALLY_EFFECT_TICKS;
  399. xDelta = FixedMul(scale, TALLY_FINAL_X_DELTA);
  400. yDelta = FixedMul(scale, TALLY_FINAL_Y_DELTA);
  401. xStart = TALLY_START_XPOS-FixedMul(scale,
  402. TALLY_START_XPOS-TALLY_STOP_XPOS);
  403. yPos = TALLY_START_YPOS-FixedMul(scale,
  404. TALLY_START_YPOS-TALLY_STOP_YPOS);
  405. }
  406. else
  407. {
  408. xDelta = TALLY_FINAL_X_DELTA;
  409. yDelta = TALLY_FINAL_Y_DELTA;
  410. xStart = TALLY_STOP_XPOS;
  411. yPos = TALLY_STOP_YPOS;
  412. }
  413. if(intertime >= TALLY_EFFECT_TICKS && showTotals == false)
  414. {
  415. showTotals = true;
  416. S_StartSound(NULL, SFX_PLATFORM_STOP);
  417. }
  418. y = yPos>>FRACBITS;
  419. for(i = 0; i < MAXPLAYERS; i++)
  420. {
  421. xPos = xStart;
  422. for(j = 0; j < MAXPLAYERS; j++, xPos += xDelta)
  423. {
  424. x = xPos>>FRACBITS;
  425. bold = (i == consoleplayer || j == consoleplayer);
  426. if(playeringame[i] && playeringame[j])
  427. {
  428. if(bold)
  429. {
  430. DrNumberBold(players[i].frags[j], x, y, 100);
  431. }
  432. else
  433. {
  434. DrNumber(players[i].frags[j], x, y, 100);
  435. }
  436. }
  437. else
  438. {
  439. temp = MN_TextAWidth("--")/2;
  440. if(bold)
  441. {
  442. MN_DrTextAYellow("--", x-temp, y);
  443. }
  444. else
  445. {
  446. MN_DrTextA("--", x-temp, y);
  447. }
  448. }
  449. }
  450. if(showTotals && playeringame[i]
  451. && !((slaughterboy&(1<<i)) && !(intertime&16)))
  452. {
  453. DrNumber(totalFrags[i], TALLY_TOTALS_X, y, 1000);
  454. }
  455. yPos += yDelta;
  456. y = yPos>>FRACBITS;
  457. }
  458. }
  459. //==========================================================================
  460. //
  461. // DrNumber
  462. //
  463. //==========================================================================
  464. static void DrNumber(int val, int x, int y, int wrapThresh)
  465. {
  466. char buff[8] = "XX";
  467. if(!(val < -9 && wrapThresh < 1000))
  468. {
  469. sprintf(buff, "%d", val >= wrapThresh ? val%wrapThresh : val);
  470. }
  471. MN_DrTextA(buff, x-MN_TextAWidth(buff)/2, y);
  472. }
  473. //==========================================================================
  474. //
  475. // DrNumberBold
  476. //
  477. //==========================================================================
  478. static void DrNumberBold(int val, int x, int y, int wrapThresh)
  479. {
  480. char buff[8] = "XX";
  481. if(!(val < -9 && wrapThresh < 1000))
  482. {
  483. sprintf(buff, "%d", val >= wrapThresh ? val%wrapThresh : val);
  484. }
  485. MN_DrTextAYellow(buff, x-MN_TextAWidth(buff)/2, y);
  486. }
  487. //===========================================================================
  488. //
  489. // DrawHubText
  490. //
  491. //===========================================================================
  492. static void DrawHubText(void)
  493. {
  494. int count;
  495. char *ch;
  496. int c;
  497. int cx, cy;
  498. patch_t *w;
  499. cy = 5;
  500. cx = 10;
  501. ch = HubText;
  502. count = (intertime-10)/TEXTSPEED;
  503. if (count < 0)
  504. {
  505. count = 0;
  506. }
  507. for(; count; count--)
  508. {
  509. c = *ch++;
  510. if(!c)
  511. {
  512. break;
  513. }
  514. if(c == '\n')
  515. {
  516. cx = 10;
  517. cy += 9;
  518. continue;
  519. }
  520. if(c < 32)
  521. {
  522. continue;
  523. }
  524. c = toupper(c);
  525. if(c == 32)
  526. {
  527. cx += 5;
  528. continue;
  529. }
  530. w = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
  531. if(cx+w->width > SCREENWIDTH)
  532. {
  533. break;
  534. }
  535. V_DrawPatch(cx, cy, w);
  536. cx += w->width;
  537. }
  538. }