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