hu_stuff.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  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. #include "doomdef.h"
  24. #include "z_zone.h"
  25. #include "m_swap.h"
  26. #include "hu_stuff.h"
  27. #include "hu_lib.h"
  28. #include "w_wad.h"
  29. #include "s_sound.h"
  30. #include "doomstat.h"
  31. // Data.
  32. #include "dstrings.h"
  33. #include "sounds.h"
  34. #include "Main.h"
  35. //
  36. // Locally used constants, shortcuts.
  37. //
  38. extern const char* const temp_chat_macros[];
  39. const char* const temp_chat_macros[] =
  40. {
  41. HUSTR_CHATMACRO0,
  42. HUSTR_CHATMACRO1,
  43. HUSTR_CHATMACRO2,
  44. HUSTR_CHATMACRO3,
  45. HUSTR_CHATMACRO4,
  46. HUSTR_CHATMACRO5,
  47. HUSTR_CHATMACRO6,
  48. HUSTR_CHATMACRO7,
  49. HUSTR_CHATMACRO8,
  50. HUSTR_CHATMACRO9
  51. };
  52. extern const char* const player_names[];
  53. const char* const player_names[] =
  54. {
  55. HUSTR_PLRGREEN,
  56. HUSTR_PLRINDIGO,
  57. HUSTR_PLRBROWN,
  58. HUSTR_PLRRED
  59. };
  60. //
  61. // Builtin map names.
  62. // The actual names can be found in DStrings.h.
  63. //
  64. const char* mapnames[] =
  65. {
  66. HUSTR_E1M1,
  67. HUSTR_E1M2,
  68. HUSTR_E1M3,
  69. HUSTR_E1M4,
  70. HUSTR_E1M5,
  71. HUSTR_E1M6,
  72. HUSTR_E1M7,
  73. HUSTR_E1M8,
  74. HUSTR_E1M9,
  75. HUSTR_E2M1,
  76. HUSTR_E2M2,
  77. HUSTR_E2M3,
  78. HUSTR_E2M4,
  79. HUSTR_E2M5,
  80. HUSTR_E2M6,
  81. HUSTR_E2M7,
  82. HUSTR_E2M8,
  83. HUSTR_E2M9,
  84. HUSTR_E3M1,
  85. HUSTR_E3M2,
  86. HUSTR_E3M3,
  87. HUSTR_E3M4,
  88. HUSTR_E3M5,
  89. HUSTR_E3M6,
  90. HUSTR_E3M7,
  91. HUSTR_E3M8,
  92. HUSTR_E3M9,
  93. HUSTR_E4M1,
  94. HUSTR_E4M2,
  95. HUSTR_E4M3,
  96. HUSTR_E4M4,
  97. HUSTR_E4M5,
  98. HUSTR_E4M6,
  99. HUSTR_E4M7,
  100. HUSTR_E4M8,
  101. HUSTR_E4M9,
  102. "NEWLEVEL",
  103. "NEWLEVEL",
  104. "NEWLEVEL",
  105. "NEWLEVEL",
  106. "NEWLEVEL",
  107. "NEWLEVEL",
  108. "NEWLEVEL",
  109. "NEWLEVEL",
  110. "NEWLEVEL"
  111. };
  112. const char* mapnames2[] =
  113. {
  114. HUSTR_1,
  115. HUSTR_2,
  116. HUSTR_3,
  117. HUSTR_4,
  118. HUSTR_5,
  119. HUSTR_6,
  120. HUSTR_7,
  121. HUSTR_8,
  122. HUSTR_9,
  123. HUSTR_10,
  124. HUSTR_11,
  125. HUSTR_12,
  126. HUSTR_13,
  127. HUSTR_14,
  128. HUSTR_15,
  129. HUSTR_16,
  130. HUSTR_17,
  131. HUSTR_18,
  132. HUSTR_19,
  133. HUSTR_20,
  134. HUSTR_21,
  135. HUSTR_22,
  136. HUSTR_23,
  137. HUSTR_24,
  138. HUSTR_25,
  139. HUSTR_26,
  140. HUSTR_27,
  141. HUSTR_28,
  142. HUSTR_29,
  143. HUSTR_30,
  144. HUSTR_31,
  145. HUSTR_32,
  146. HUSTR_33
  147. };
  148. const char* mapnamesp[] =
  149. {
  150. PHUSTR_1,
  151. PHUSTR_2,
  152. PHUSTR_3,
  153. PHUSTR_4,
  154. PHUSTR_5,
  155. PHUSTR_6,
  156. PHUSTR_7,
  157. PHUSTR_8,
  158. PHUSTR_9,
  159. PHUSTR_10,
  160. PHUSTR_11,
  161. PHUSTR_12,
  162. PHUSTR_13,
  163. PHUSTR_14,
  164. PHUSTR_15,
  165. PHUSTR_16,
  166. PHUSTR_17,
  167. PHUSTR_18,
  168. PHUSTR_19,
  169. PHUSTR_20,
  170. PHUSTR_21,
  171. PHUSTR_22,
  172. PHUSTR_23,
  173. PHUSTR_24,
  174. PHUSTR_25,
  175. PHUSTR_26,
  176. PHUSTR_27,
  177. PHUSTR_28,
  178. PHUSTR_29,
  179. PHUSTR_30,
  180. PHUSTR_31,
  181. PHUSTR_32
  182. };
  183. // TNT WAD map names.
  184. const char *mapnamest[] =
  185. {
  186. THUSTR_1,
  187. THUSTR_2,
  188. THUSTR_3,
  189. THUSTR_4,
  190. THUSTR_5,
  191. THUSTR_6,
  192. THUSTR_7,
  193. THUSTR_8,
  194. THUSTR_9,
  195. THUSTR_10,
  196. THUSTR_11,
  197. THUSTR_12,
  198. THUSTR_13,
  199. THUSTR_14,
  200. THUSTR_15,
  201. THUSTR_16,
  202. THUSTR_17,
  203. THUSTR_18,
  204. THUSTR_19,
  205. THUSTR_20,
  206. THUSTR_21,
  207. THUSTR_22,
  208. THUSTR_23,
  209. THUSTR_24,
  210. THUSTR_25,
  211. THUSTR_26,
  212. THUSTR_27,
  213. THUSTR_28,
  214. THUSTR_29,
  215. THUSTR_30,
  216. THUSTR_31,
  217. THUSTR_32
  218. };
  219. const char* shiftxform;
  220. const char english_shiftxform[] =
  221. {
  222. 0,
  223. 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
  224. 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
  225. 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
  226. 31,
  227. ' ', '!', '"', '#', '$', '%', '&',
  228. '"', // shift-'
  229. '(', ')', '*', '+',
  230. '<', // shift-,
  231. '_', // shift--
  232. '>', // shift-.
  233. '?', // shift-/
  234. ')', // shift-0
  235. '!', // shift-1
  236. '@', // shift-2
  237. '#', // shift-3
  238. '$', // shift-4
  239. '%', // shift-5
  240. '^', // shift-6
  241. '&', // shift-7
  242. '*', // shift-8
  243. '(', // shift-9
  244. ':',
  245. ':', // shift-;
  246. '<',
  247. '+', // shift-=
  248. '>', '?', '@',
  249. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
  250. 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  251. '[', // shift-[
  252. '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
  253. ']', // shift-]
  254. '"', '_',
  255. '\'', // shift-`
  256. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
  257. 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  258. '{', '|', '}', '~', 127
  259. };
  260. char ForeignTranslation(unsigned char ch)
  261. {
  262. return ch;
  263. }
  264. void HU_Init(void)
  265. {
  266. int i;
  267. int j;
  268. char buffer[9];
  269. shiftxform = english_shiftxform;
  270. // load the heads-up font
  271. j = HU_FONTSTART;
  272. for (i=0;i<HU_FONTSIZE;i++)
  273. {
  274. sprintf(buffer, "STCFN%.3d", j++);
  275. ::g->hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC_SHARED);
  276. }
  277. }
  278. void HU_Stop(void)
  279. {
  280. ::g->headsupactive = false;
  281. }
  282. void HU_Start(void)
  283. {
  284. int i;
  285. const char* s;
  286. if (::g->headsupactive)
  287. HU_Stop();
  288. ::g->plr = &::g->players[::g->consoleplayer];
  289. ::g->message_on = false;
  290. ::g->message_dontfuckwithme = false;
  291. ::g->message_nottobefuckedwith = false;
  292. ::g->chat_on = false;
  293. // create the message widget
  294. HUlib_initSText(&::g->w_message,
  295. HU_MSGX, HU_MSGY, HU_MSGHEIGHT,
  296. ::g->hu_font,
  297. HU_FONTSTART, &::g->message_on);
  298. // create the map title widget
  299. HUlib_initTextLine(&::g->w_title,
  300. HU_TITLEX, HU_TITLEY,
  301. ::g->hu_font,
  302. HU_FONTSTART);
  303. switch ( ::g->gamemode )
  304. {
  305. case shareware:
  306. case registered:
  307. case retail:
  308. s = HU_TITLE;
  309. break;
  310. case commercial:
  311. default:
  312. if( DoomLib::expansionSelected == 5 ) {
  313. int map = ::g->gamemap;
  314. if( ::g->gamemap > 9 ) {
  315. map = 0;
  316. }
  317. s = DoomLib::GetCurrentExpansion()->mapNames[ map - 1 ];
  318. } else {
  319. s = DoomLib::GetCurrentExpansion()->mapNames[ ::g->gamemap - 1 ];
  320. }
  321. break;
  322. }
  323. while (*s)
  324. HUlib_addCharToTextLine(&::g->w_title, *(s++));
  325. // create the chat widget
  326. HUlib_initIText(&::g->w_chat,
  327. HU_INPUTX, HU_INPUTY,
  328. ::g->hu_font,
  329. HU_FONTSTART, &::g->chat_on);
  330. // create the inputbuffer widgets
  331. for (i=0 ; i<MAXPLAYERS ; i++)
  332. HUlib_initIText(&::g->w_inputbuffer[i], 0, 0, 0, 0, &::g->always_off);
  333. ::g->headsupactive = true;
  334. }
  335. void HU_Drawer(void)
  336. {
  337. HUlib_drawSText(&::g->w_message);
  338. HUlib_drawIText(&::g->w_chat);
  339. if (::g->automapactive)
  340. HUlib_drawTextLine(&::g->w_title, false);
  341. }
  342. void HU_Erase(void)
  343. {
  344. HUlib_eraseSText(&::g->w_message);
  345. HUlib_eraseIText(&::g->w_chat);
  346. HUlib_eraseTextLine(&::g->w_title);
  347. }
  348. void HU_Ticker(void)
  349. {
  350. // tick down message counter if message is up
  351. if (::g->message_counter && !--::g->message_counter)
  352. {
  353. ::g->message_on = false;
  354. ::g->message_nottobefuckedwith = false;
  355. }
  356. if ( ( m_inDemoMode.GetBool() == false && m_show_messages.GetBool() ) || ::g->message_dontfuckwithme)
  357. {
  358. // display message if necessary
  359. if ((::g->plr->message && !::g->message_nottobefuckedwith)
  360. || (::g->plr->message && ::g->message_dontfuckwithme))
  361. {
  362. HUlib_addMessageToSText(&::g->w_message, 0, ::g->plr->message);
  363. ::g->plr->message = 0;
  364. ::g->message_on = true;
  365. ::g->message_counter = HU_MSGTIMEOUT;
  366. ::g->message_nottobefuckedwith = ::g->message_dontfuckwithme;
  367. ::g->message_dontfuckwithme = 0;
  368. }
  369. } // else ::g->message_on = false;
  370. }
  371. void HU_queueChatChar(char c)
  372. {
  373. if (((::g->head + 1) & (QUEUESIZE-1)) == ::g->tail)
  374. {
  375. ::g->plr->message = HUSTR_MSGU;
  376. }
  377. else
  378. {
  379. ::g->chatchars[::g->head] = c;
  380. ::g->head = (::g->head + 1) & (QUEUESIZE-1);
  381. }
  382. }
  383. char HU_dequeueChatChar(void)
  384. {
  385. char c;
  386. if (::g->head != ::g->tail)
  387. {
  388. c = ::g->chatchars[::g->tail];
  389. ::g->tail = (::g->tail + 1) & (QUEUESIZE-1);
  390. }
  391. else
  392. {
  393. c = 0;
  394. }
  395. return c;
  396. }
  397. qboolean HU_Responder(event_t *ev)
  398. {
  399. const char* macromessage;
  400. qboolean eatkey = false;
  401. unsigned char c;
  402. int i;
  403. int numplayers;
  404. const static char destination_keys[MAXPLAYERS] =
  405. {
  406. HUSTR_KEYGREEN,
  407. HUSTR_KEYINDIGO,
  408. HUSTR_KEYBROWN,
  409. HUSTR_KEYRED
  410. };
  411. numplayers = 0;
  412. for (i=0 ; i<MAXPLAYERS ; i++)
  413. numplayers += ::g->playeringame[i];
  414. if (ev->data1 == KEY_RSHIFT)
  415. {
  416. ::g->shiftdown = ev->type == ev_keydown;
  417. return false;
  418. }
  419. else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT)
  420. {
  421. ::g->altdown = ev->type == ev_keydown;
  422. return false;
  423. }
  424. if (ev->type != ev_keydown)
  425. return false;
  426. if (!::g->chat_on)
  427. {
  428. if (ev->data1 == HU_MSGREFRESH)
  429. {
  430. ::g->message_on = true;
  431. ::g->message_counter = HU_MSGTIMEOUT;
  432. eatkey = true;
  433. }
  434. else if (::g->netgame && ev->data1 == HU_INPUTTOGGLE)
  435. {
  436. eatkey = ::g->chat_on = true;
  437. HUlib_resetIText(&::g->w_chat);
  438. HU_queueChatChar(HU_BROADCAST);
  439. }
  440. else if (::g->netgame && numplayers > 2)
  441. {
  442. for (i=0; i<MAXPLAYERS ; i++)
  443. {
  444. if (ev->data1 == destination_keys[i])
  445. {
  446. if (::g->playeringame[i] && i!=::g->consoleplayer)
  447. {
  448. eatkey = ::g->chat_on = true;
  449. HUlib_resetIText(&::g->w_chat);
  450. HU_queueChatChar(i+1);
  451. break;
  452. }
  453. else if (i == ::g->consoleplayer)
  454. {
  455. ::g->num_nobrainers++;
  456. if (::g->num_nobrainers < 3)
  457. ::g->plr->message = HUSTR_TALKTOSELF1;
  458. else if (::g->num_nobrainers < 6)
  459. ::g->plr->message = HUSTR_TALKTOSELF2;
  460. else if (::g->num_nobrainers < 9)
  461. ::g->plr->message = HUSTR_TALKTOSELF3;
  462. else if (::g->num_nobrainers < 32)
  463. ::g->plr->message = HUSTR_TALKTOSELF4;
  464. else
  465. ::g->plr->message = HUSTR_TALKTOSELF5;
  466. }
  467. }
  468. }
  469. }
  470. }
  471. else
  472. {
  473. c = ev->data1;
  474. // send a macro
  475. if (::g->altdown)
  476. {
  477. c = c - '0';
  478. if (c > 9)
  479. return false;
  480. // I_PrintfE( "got here\n");
  481. macromessage = temp_chat_macros[c];
  482. // kill last message with a '\n'
  483. HU_queueChatChar(KEY_ENTER); // DEBUG!!!
  484. // send the macro message
  485. while (*macromessage)
  486. HU_queueChatChar(*macromessage++);
  487. HU_queueChatChar(KEY_ENTER);
  488. // leave chat mode and notify that it was sent
  489. ::g->chat_on = false;
  490. strcpy(::g->lastmessage, temp_chat_macros[c]);
  491. ::g->plr->message = ::g->lastmessage;
  492. eatkey = true;
  493. }
  494. else
  495. {
  496. if (::g->shiftdown || (c >= 'a' && c <= 'z'))
  497. c = shiftxform[c];
  498. eatkey = HUlib_keyInIText(&::g->w_chat, c);
  499. if (eatkey)
  500. {
  501. // static unsigned char buf[20]; // DEBUG
  502. HU_queueChatChar(c);
  503. // sprintf(buf, "KEY: %d => %d", ev->data1, c);
  504. // ::g->plr->message = buf;
  505. }
  506. if (c == KEY_ENTER)
  507. {
  508. ::g->chat_on = false;
  509. if (::g->w_chat.l.len)
  510. {
  511. strcpy(::g->lastmessage, ::g->w_chat.l.l);
  512. ::g->plr->message = ::g->lastmessage;
  513. }
  514. }
  515. else if (c == KEY_ESCAPE)
  516. ::g->chat_on = false;
  517. }
  518. }
  519. return eatkey;
  520. }