1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
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.
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
19 // DESCRIPTION: Heads-up displays
21 //-----------------------------------------------------------------------------
24 rcsid[] = "$Id: hu_stuff.c,v 1.4 1997/02/03 16:47:52 b1 Exp $";
47 // Locally used constants, shortcuts.
49 #define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1])
50 #define HU_TITLE2 (mapnames2[gamemap-1])
51 #define HU_TITLEP (mapnamesp[gamemap-1])
52 #define HU_TITLET (mapnamest[gamemap-1])
53 #define HU_TITLEHEIGHT 1
55 #define HU_TITLEY (167 - SHORT(hu_font[0]->height))
57 #define HU_INPUTTOGGLE 't'
58 #define HU_INPUTX HU_MSGX
59 #define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0]->height) +1))
60 #define HU_INPUTWIDTH 64
61 #define HU_INPUTHEIGHT 1
79 char* player_names[] =
88 char chat_char; // remove later.
90 patch_t* hu_font[HU_FONTSIZE];
91 static hu_textline_t w_title;
93 static hu_itext_t w_chat;
94 static boolean always_off = false;
95 static char chat_dest[MAXPLAYERS];
96 static hu_itext_t w_inputbuffer[MAXPLAYERS];
98 static boolean message_on;
99 boolean message_dontfuckwithme;
100 static boolean message_nottobefuckedwith;
102 static hu_stext_t w_message;
103 static int message_counter;
105 extern int showMessages;
106 extern boolean automapactive;
108 static boolean headsupactive = false;
111 // Builtin map names.
112 // The actual names can be found in DStrings.h.
115 char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
169 char* mapnames2[] = // DOOM 2 map names.
208 char* mapnamesp[] = // Plutonia WAD map names.
247 char *mapnamest[] = // TNT WAD map names.
286 const char* shiftxform;
288 const char french_shiftxform[] =
291 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
292 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
293 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
295 ' ', '!', '"', '#', '$', '%', '&',
317 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
318 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
320 '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
324 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
325 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
326 '{', '|', '}', '~', 127
330 const char english_shiftxform[] =
334 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
335 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
336 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
338 ' ', '!', '"', '#', '$', '%', '&',
360 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
361 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
363 '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
367 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
368 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
369 '{', '|', '}', '~', 127
372 char frenchKeyMap[128]=
375 1,2,3,4,5,6,7,8,9,10,
376 11,12,13,14,15,16,17,18,19,20,
377 21,22,23,24,25,26,27,28,29,30,
379 ' ','!','"','#','$','%','&','%','(',')','*','+',';','-',':','!',
380 '0','1','2','3','4','5','6','7','8','9',':','M','<','=','>','?',
381 '@','Q','B','C','D','E','F','G','H','I','J','K','L',',','N','O',
382 'P','A','R','S','T','U','V','Z','X','Y','W','^','\\','$','^','_',
383 '@','Q','B','C','D','E','F','G','H','I','J','K','L',',','N','O',
384 'P','A','R','S','T','U','V','Z','X','Y','W','^','\\','$','^',127
387 char ForeignTranslation(unsigned char ch)
389 return ch < 128 ? frenchKeyMap[ch] : ch;
400 shiftxform = french_shiftxform;
402 shiftxform = english_shiftxform;
404 // load the heads-up font
406 for (i=0;i<HU_FONTSIZE;i++)
408 sprintf(buffer, "STCFN%.3d", j++);
409 hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC);
416 headsupactive = false;
428 plr = &players[consoleplayer];
430 message_dontfuckwithme = false;
431 message_nottobefuckedwith = false;
434 // create the message widget
435 HUlib_initSText(&w_message,
436 HU_MSGX, HU_MSGY, HU_MSGHEIGHT,
438 HU_FONTSTART, &message_on);
440 // create the map title widget
441 HUlib_initTextLine(&w_title,
442 HU_TITLEX, HU_TITLEY,
470 HUlib_addCharToTextLine(&w_title, *(s++));
472 // create the chat widget
473 HUlib_initIText(&w_chat,
474 HU_INPUTX, HU_INPUTY,
476 HU_FONTSTART, &chat_on);
478 // create the inputbuffer widgets
479 for (i=0 ; i<MAXPLAYERS ; i++)
480 HUlib_initIText(&w_inputbuffer[i], 0, 0, 0, 0, &always_off);
482 headsupactive = true;
489 HUlib_drawSText(&w_message);
490 HUlib_drawIText(&w_chat);
492 HUlib_drawTextLine(&w_title, false);
499 HUlib_eraseSText(&w_message);
500 HUlib_eraseIText(&w_chat);
501 HUlib_eraseTextLine(&w_title);
511 // tick down message counter if message is up
512 if (message_counter && !--message_counter)
515 message_nottobefuckedwith = false;
518 if (showMessages || message_dontfuckwithme)
521 // display message if necessary
522 if ((plr->message && !message_nottobefuckedwith)
523 || (plr->message && message_dontfuckwithme))
525 HUlib_addMessageToSText(&w_message, 0, plr->message);
528 message_counter = HU_MSGTIMEOUT;
529 message_nottobefuckedwith = message_dontfuckwithme;
530 message_dontfuckwithme = 0;
533 } // else message_on = false;
535 // check for incoming chat characters
538 for (i=0 ; i<MAXPLAYERS; i++)
540 if (!playeringame[i])
542 if (i != consoleplayer
543 && (c = players[i].cmd.chatchar))
545 if (c <= HU_BROADCAST)
549 if (c >= 'a' && c <= 'z')
550 c = (char) shiftxform[(unsigned char) c];
551 rc = HUlib_keyInIText(&w_inputbuffer[i], c);
552 if (rc && c == KEY_ENTER)
554 if (w_inputbuffer[i].l.len
555 && (chat_dest[i] == consoleplayer+1
556 || chat_dest[i] == HU_BROADCAST))
558 HUlib_addMessageToSText(&w_message,
560 w_inputbuffer[i].l.l);
562 message_nottobefuckedwith = true;
564 message_counter = HU_MSGTIMEOUT;
565 if ( gamemode == commercial )
566 S_StartSound(0, sfx_radio);
568 S_StartSound(0, sfx_tink);
570 HUlib_resetIText(&w_inputbuffer[i]);
573 players[i].cmd.chatchar = 0;
580 #define QUEUESIZE 128
582 static char chatchars[QUEUESIZE];
587 void HU_queueChatChar(char c)
589 if (((head + 1) & (QUEUESIZE-1)) == tail)
591 plr->message = HUSTR_MSGU;
596 head = (head + 1) & (QUEUESIZE-1);
600 char HU_dequeueChatChar(void)
607 tail = (tail + 1) & (QUEUESIZE-1);
617 boolean HU_Responder(event_t *ev)
620 static char lastmessage[HU_MAXLINELENGTH+1];
622 boolean eatkey = false;
623 static boolean shiftdown = false;
624 static boolean altdown = false;
629 static char destination_keys[MAXPLAYERS] =
637 static int num_nobrainers = 0;
640 for (i=0 ; i<MAXPLAYERS ; i++)
641 numplayers += playeringame[i];
643 if (ev->data1 == KEY_RSHIFT)
645 shiftdown = ev->type == ev_keydown;
648 else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT)
650 altdown = ev->type == ev_keydown;
654 if (ev->type != ev_keydown)
659 if (ev->data1 == HU_MSGREFRESH)
662 message_counter = HU_MSGTIMEOUT;
665 else if (netgame && ev->data1 == HU_INPUTTOGGLE)
667 eatkey = chat_on = true;
668 HUlib_resetIText(&w_chat);
669 HU_queueChatChar(HU_BROADCAST);
671 else if (netgame && numplayers > 2)
673 for (i=0; i<MAXPLAYERS ; i++)
675 if (ev->data1 == destination_keys[i])
677 if (playeringame[i] && i!=consoleplayer)
679 eatkey = chat_on = true;
680 HUlib_resetIText(&w_chat);
681 HU_queueChatChar(i+1);
684 else if (i == consoleplayer)
687 if (num_nobrainers < 3)
688 plr->message = HUSTR_TALKTOSELF1;
689 else if (num_nobrainers < 6)
690 plr->message = HUSTR_TALKTOSELF2;
691 else if (num_nobrainers < 9)
692 plr->message = HUSTR_TALKTOSELF3;
693 else if (num_nobrainers < 32)
694 plr->message = HUSTR_TALKTOSELF4;
696 plr->message = HUSTR_TALKTOSELF5;
711 // fprintf(stderr, "got here\n");
712 macromessage = chat_macros[c];
714 // kill last message with a '\n'
715 HU_queueChatChar(KEY_ENTER); // DEBUG!!!
717 // send the macro message
718 while (*macromessage)
719 HU_queueChatChar(*macromessage++);
720 HU_queueChatChar(KEY_ENTER);
722 // leave chat mode and notify that it was sent
724 strcpy(lastmessage, chat_macros[c]);
725 plr->message = lastmessage;
731 c = ForeignTranslation(c);
732 if (shiftdown || (c >= 'a' && c <= 'z'))
734 eatkey = HUlib_keyInIText(&w_chat, c);
737 // static unsigned char buf[20]; // DEBUG
740 // sprintf(buf, "KEY: %d => %d", ev->data1, c);
741 // plr->message = buf;
748 strcpy(lastmessage, w_chat.l.l);
749 plr->message = lastmessage;
752 else if (c == KEY_ESCAPE)