Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 760 lines (656 sloc) 14.705 kb
4eb368a @tbradshaw The DOOM sources as originally released on December 23, 1997
tbradshaw authored
1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id:$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
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.
11 //
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
15 // for more details.
16 //
17 // $Log:$
18 //
19 // DESCRIPTION: Heads-up displays
20 //
21 //-----------------------------------------------------------------------------
22
23 static const char
24 rcsid[] = "$Id: hu_stuff.c,v 1.4 1997/02/03 16:47:52 b1 Exp $";
25
26 #include <ctype.h>
27
28 #include "doomdef.h"
29
30 #include "z_zone.h"
31
32 #include "m_swap.h"
33
34 #include "hu_stuff.h"
35 #include "hu_lib.h"
36 #include "w_wad.h"
37
38 #include "s_sound.h"
39
40 #include "doomstat.h"
41
42 // Data.
43 #include "dstrings.h"
44 #include "sounds.h"
45
46 //
47 // Locally used constants, shortcuts.
48 //
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
54 #define HU_TITLEX 0
55 #define HU_TITLEY (167 - SHORT(hu_font[0]->height))
56
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
62
63
64
65 char* chat_macros[] =
66 {
67 HUSTR_CHATMACRO0,
68 HUSTR_CHATMACRO1,
69 HUSTR_CHATMACRO2,
70 HUSTR_CHATMACRO3,
71 HUSTR_CHATMACRO4,
72 HUSTR_CHATMACRO5,
73 HUSTR_CHATMACRO6,
74 HUSTR_CHATMACRO7,
75 HUSTR_CHATMACRO8,
76 HUSTR_CHATMACRO9
77 };
78
79 char* player_names[] =
80 {
81 HUSTR_PLRGREEN,
82 HUSTR_PLRINDIGO,
83 HUSTR_PLRBROWN,
84 HUSTR_PLRRED
85 };
86
87
88 char chat_char; // remove later.
89 static player_t* plr;
90 patch_t* hu_font[HU_FONTSIZE];
91 static hu_textline_t w_title;
92 boolean chat_on;
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];
97
98 static boolean message_on;
99 boolean message_dontfuckwithme;
100 static boolean message_nottobefuckedwith;
101
102 static hu_stext_t w_message;
103 static int message_counter;
104
105 extern int showMessages;
106 extern boolean automapactive;
107
108 static boolean headsupactive = false;
109
110 //
111 // Builtin map names.
112 // The actual names can be found in DStrings.h.
113 //
114
115 char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
116 {
117
118 HUSTR_E1M1,
119 HUSTR_E1M2,
120 HUSTR_E1M3,
121 HUSTR_E1M4,
122 HUSTR_E1M5,
123 HUSTR_E1M6,
124 HUSTR_E1M7,
125 HUSTR_E1M8,
126 HUSTR_E1M9,
127
128 HUSTR_E2M1,
129 HUSTR_E2M2,
130 HUSTR_E2M3,
131 HUSTR_E2M4,
132 HUSTR_E2M5,
133 HUSTR_E2M6,
134 HUSTR_E2M7,
135 HUSTR_E2M8,
136 HUSTR_E2M9,
137
138 HUSTR_E3M1,
139 HUSTR_E3M2,
140 HUSTR_E3M3,
141 HUSTR_E3M4,
142 HUSTR_E3M5,
143 HUSTR_E3M6,
144 HUSTR_E3M7,
145 HUSTR_E3M8,
146 HUSTR_E3M9,
147
148 HUSTR_E4M1,
149 HUSTR_E4M2,
150 HUSTR_E4M3,
151 HUSTR_E4M4,
152 HUSTR_E4M5,
153 HUSTR_E4M6,
154 HUSTR_E4M7,
155 HUSTR_E4M8,
156 HUSTR_E4M9,
157
158 "NEWLEVEL",
159 "NEWLEVEL",
160 "NEWLEVEL",
161 "NEWLEVEL",
162 "NEWLEVEL",
163 "NEWLEVEL",
164 "NEWLEVEL",
165 "NEWLEVEL",
166 "NEWLEVEL"
167 };
168
169 char* mapnames2[] = // DOOM 2 map names.
170 {
171 HUSTR_1,
172 HUSTR_2,
173 HUSTR_3,
174 HUSTR_4,
175 HUSTR_5,
176 HUSTR_6,
177 HUSTR_7,
178 HUSTR_8,
179 HUSTR_9,
180 HUSTR_10,
181 HUSTR_11,
182
183 HUSTR_12,
184 HUSTR_13,
185 HUSTR_14,
186 HUSTR_15,
187 HUSTR_16,
188 HUSTR_17,
189 HUSTR_18,
190 HUSTR_19,
191 HUSTR_20,
192
193 HUSTR_21,
194 HUSTR_22,
195 HUSTR_23,
196 HUSTR_24,
197 HUSTR_25,
198 HUSTR_26,
199 HUSTR_27,
200 HUSTR_28,
201 HUSTR_29,
202 HUSTR_30,
203 HUSTR_31,
204 HUSTR_32
205 };
206
207
208 char* mapnamesp[] = // Plutonia WAD map names.
209 {
210 PHUSTR_1,
211 PHUSTR_2,
212 PHUSTR_3,
213 PHUSTR_4,
214 PHUSTR_5,
215 PHUSTR_6,
216 PHUSTR_7,
217 PHUSTR_8,
218 PHUSTR_9,
219 PHUSTR_10,
220 PHUSTR_11,
221
222 PHUSTR_12,
223 PHUSTR_13,
224 PHUSTR_14,
225 PHUSTR_15,
226 PHUSTR_16,
227 PHUSTR_17,
228 PHUSTR_18,
229 PHUSTR_19,
230 PHUSTR_20,
231
232 PHUSTR_21,
233 PHUSTR_22,
234 PHUSTR_23,
235 PHUSTR_24,
236 PHUSTR_25,
237 PHUSTR_26,
238 PHUSTR_27,
239 PHUSTR_28,
240 PHUSTR_29,
241 PHUSTR_30,
242 PHUSTR_31,
243 PHUSTR_32
244 };
245
246
247 char *mapnamest[] = // TNT WAD map names.
248 {
249 THUSTR_1,
250 THUSTR_2,
251 THUSTR_3,
252 THUSTR_4,
253 THUSTR_5,
254 THUSTR_6,
255 THUSTR_7,
256 THUSTR_8,
257 THUSTR_9,
258 THUSTR_10,
259 THUSTR_11,
260
261 THUSTR_12,
262 THUSTR_13,
263 THUSTR_14,
264 THUSTR_15,
265 THUSTR_16,
266 THUSTR_17,
267 THUSTR_18,
268 THUSTR_19,
269 THUSTR_20,
270
271 THUSTR_21,
272 THUSTR_22,
273 THUSTR_23,
274 THUSTR_24,
275 THUSTR_25,
276 THUSTR_26,
277 THUSTR_27,
278 THUSTR_28,
279 THUSTR_29,
280 THUSTR_30,
281 THUSTR_31,
282 THUSTR_32
283 };
284
285
286 const char* shiftxform;
287
288 const char french_shiftxform[] =
289 {
290 0,
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,
294 31,
295 ' ', '!', '"', '#', '$', '%', '&',
296 '"', // shift-'
297 '(', ')', '*', '+',
298 '?', // shift-,
299 '_', // shift--
300 '>', // shift-.
301 '?', // shift-/
302 '0', // shift-0
303 '1', // shift-1
304 '2', // shift-2
305 '3', // shift-3
306 '4', // shift-4
307 '5', // shift-5
308 '6', // shift-6
309 '7', // shift-7
310 '8', // shift-8
311 '9', // shift-9
312 '/',
313 '.', // shift-;
314 '<',
315 '+', // shift-=
316 '>', '?', '@',
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',
319 '[', // shift-[
320 '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
321 ']', // shift-]
322 '"', '_',
323 '\'', // shift-`
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
327
328 };
329
330 const char english_shiftxform[] =
331 {
332
333 0,
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,
337 31,
338 ' ', '!', '"', '#', '$', '%', '&',
339 '"', // shift-'
340 '(', ')', '*', '+',
341 '<', // shift-,
342 '_', // shift--
343 '>', // shift-.
344 '?', // shift-/
345 ')', // shift-0
346 '!', // shift-1
347 '@', // shift-2
348 '#', // shift-3
349 '$', // shift-4
350 '%', // shift-5
351 '^', // shift-6
352 '&', // shift-7
353 '*', // shift-8
354 '(', // shift-9
355 ':',
356 ':', // shift-;
357 '<',
358 '+', // shift-=
359 '>', '?', '@',
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',
362 '[', // shift-[
363 '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
364 ']', // shift-]
365 '"', '_',
366 '\'', // shift-`
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
370 };
371
372 char frenchKeyMap[128]=
373 {
374 0,
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,
378 31,
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
385 };
386
387 char ForeignTranslation(unsigned char ch)
388 {
389 return ch < 128 ? frenchKeyMap[ch] : ch;
390 }
391
392 void HU_Init(void)
393 {
394
395 int i;
396 int j;
397 char buffer[9];
398
399 if (french)
400 shiftxform = french_shiftxform;
401 else
402 shiftxform = english_shiftxform;
403
404 // load the heads-up font
405 j = HU_FONTSTART;
406 for (i=0;i<HU_FONTSIZE;i++)
407 {
408 sprintf(buffer, "STCFN%.3d", j++);
409 hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC);
410 }
411
412 }
413
414 void HU_Stop(void)
415 {
416 headsupactive = false;
417 }
418
419 void HU_Start(void)
420 {
421
422 int i;
423 char* s;
424
425 if (headsupactive)
426 HU_Stop();
427
428 plr = &players[consoleplayer];
429 message_on = false;
430 message_dontfuckwithme = false;
431 message_nottobefuckedwith = false;
432 chat_on = false;
433
434 // create the message widget
435 HUlib_initSText(&w_message,
436 HU_MSGX, HU_MSGY, HU_MSGHEIGHT,
437 hu_font,
438 HU_FONTSTART, &message_on);
439
440 // create the map title widget
441 HUlib_initTextLine(&w_title,
442 HU_TITLEX, HU_TITLEY,
443 hu_font,
444 HU_FONTSTART);
445
446 switch ( gamemode )
447 {
448 case shareware:
449 case registered:
450 case retail:
451 s = HU_TITLE;
452 break;
453
454 /* FIXME
455 case pack_plut:
456 s = HU_TITLEP;
457 break;
458 case pack_tnt:
459 s = HU_TITLET;
460 break;
461 */
462
463 case commercial:
464 default:
465 s = HU_TITLE2;
466 break;
467 }
468
469 while (*s)
470 HUlib_addCharToTextLine(&w_title, *(s++));
471
472 // create the chat widget
473 HUlib_initIText(&w_chat,
474 HU_INPUTX, HU_INPUTY,
475 hu_font,
476 HU_FONTSTART, &chat_on);
477
478 // create the inputbuffer widgets
479 for (i=0 ; i<MAXPLAYERS ; i++)
480 HUlib_initIText(&w_inputbuffer[i], 0, 0, 0, 0, &always_off);
481
482 headsupactive = true;
483
484 }
485
486 void HU_Drawer(void)
487 {
488
489 HUlib_drawSText(&w_message);
490 HUlib_drawIText(&w_chat);
491 if (automapactive)
492 HUlib_drawTextLine(&w_title, false);
493
494 }
495
496 void HU_Erase(void)
497 {
498
499 HUlib_eraseSText(&w_message);
500 HUlib_eraseIText(&w_chat);
501 HUlib_eraseTextLine(&w_title);
502
503 }
504
505 void HU_Ticker(void)
506 {
507
508 int i, rc;
509 char c;
510
511 // tick down message counter if message is up
512 if (message_counter && !--message_counter)
513 {
514 message_on = false;
515 message_nottobefuckedwith = false;
516 }
517
518 if (showMessages || message_dontfuckwithme)
519 {
520
521 // display message if necessary
522 if ((plr->message && !message_nottobefuckedwith)
523 || (plr->message && message_dontfuckwithme))
524 {
525 HUlib_addMessageToSText(&w_message, 0, plr->message);
526 plr->message = 0;
527 message_on = true;
528 message_counter = HU_MSGTIMEOUT;
529 message_nottobefuckedwith = message_dontfuckwithme;
530 message_dontfuckwithme = 0;
531 }
532
533 } // else message_on = false;
534
535 // check for incoming chat characters
536 if (netgame)
537 {
538 for (i=0 ; i<MAXPLAYERS; i++)
539 {
540 if (!playeringame[i])
541 continue;
542 if (i != consoleplayer
543 && (c = players[i].cmd.chatchar))
544 {
545 if (c <= HU_BROADCAST)
546 chat_dest[i] = c;
547 else
548 {
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)
553 {
554 if (w_inputbuffer[i].l.len
555 && (chat_dest[i] == consoleplayer+1
556 || chat_dest[i] == HU_BROADCAST))
557 {
558 HUlib_addMessageToSText(&w_message,
559 player_names[i],
560 w_inputbuffer[i].l.l);
561
562 message_nottobefuckedwith = true;
563 message_on = true;
564 message_counter = HU_MSGTIMEOUT;
565 if ( gamemode == commercial )
566 S_StartSound(0, sfx_radio);
567 else
568 S_StartSound(0, sfx_tink);
569 }
570 HUlib_resetIText(&w_inputbuffer[i]);
571 }
572 }
573 players[i].cmd.chatchar = 0;
574 }
575 }
576 }
577
578 }
579
580 #define QUEUESIZE 128
581
582 static char chatchars[QUEUESIZE];
583 static int head = 0;
584 static int tail = 0;
585
586
587 void HU_queueChatChar(char c)
588 {
589 if (((head + 1) & (QUEUESIZE-1)) == tail)
590 {
591 plr->message = HUSTR_MSGU;
592 }
593 else
594 {
595 chatchars[head] = c;
596 head = (head + 1) & (QUEUESIZE-1);
597 }
598 }
599
600 char HU_dequeueChatChar(void)
601 {
602 char c;
603
604 if (head != tail)
605 {
606 c = chatchars[tail];
607 tail = (tail + 1) & (QUEUESIZE-1);
608 }
609 else
610 {
611 c = 0;
612 }
613
614 return c;
615 }
616
617 boolean HU_Responder(event_t *ev)
618 {
619
620 static char lastmessage[HU_MAXLINELENGTH+1];
621 char* macromessage;
622 boolean eatkey = false;
623 static boolean shiftdown = false;
624 static boolean altdown = false;
625 unsigned char c;
626 int i;
627 int numplayers;
628
629 static char destination_keys[MAXPLAYERS] =
630 {
631 HUSTR_KEYGREEN,
632 HUSTR_KEYINDIGO,
633 HUSTR_KEYBROWN,
634 HUSTR_KEYRED
635 };
636
637 static int num_nobrainers = 0;
638
639 numplayers = 0;
640 for (i=0 ; i<MAXPLAYERS ; i++)
641 numplayers += playeringame[i];
642
643 if (ev->data1 == KEY_RSHIFT)
644 {
645 shiftdown = ev->type == ev_keydown;
646 return false;
647 }
648 else if (ev->data1 == KEY_RALT || ev->data1 == KEY_LALT)
649 {
650 altdown = ev->type == ev_keydown;
651 return false;
652 }
653
654 if (ev->type != ev_keydown)
655 return false;
656
657 if (!chat_on)
658 {
659 if (ev->data1 == HU_MSGREFRESH)
660 {
661 message_on = true;
662 message_counter = HU_MSGTIMEOUT;
663 eatkey = true;
664 }
665 else if (netgame && ev->data1 == HU_INPUTTOGGLE)
666 {
667 eatkey = chat_on = true;
668 HUlib_resetIText(&w_chat);
669 HU_queueChatChar(HU_BROADCAST);
670 }
671 else if (netgame && numplayers > 2)
672 {
673 for (i=0; i<MAXPLAYERS ; i++)
674 {
675 if (ev->data1 == destination_keys[i])
676 {
677 if (playeringame[i] && i!=consoleplayer)
678 {
679 eatkey = chat_on = true;
680 HUlib_resetIText(&w_chat);
681 HU_queueChatChar(i+1);
682 break;
683 }
684 else if (i == consoleplayer)
685 {
686 num_nobrainers++;
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;
695 else
696 plr->message = HUSTR_TALKTOSELF5;
697 }
698 }
699 }
700 }
701 }
702 else
703 {
704 c = ev->data1;
705 // send a macro
706 if (altdown)
707 {
708 c = c - '0';
709 if (c > 9)
710 return false;
711 // fprintf(stderr, "got here\n");
712 macromessage = chat_macros[c];
713
714 // kill last message with a '\n'
715 HU_queueChatChar(KEY_ENTER); // DEBUG!!!
716
717 // send the macro message
718 while (*macromessage)
719 HU_queueChatChar(*macromessage++);
720 HU_queueChatChar(KEY_ENTER);
721
722 // leave chat mode and notify that it was sent
723 chat_on = false;
724 strcpy(lastmessage, chat_macros[c]);
725 plr->message = lastmessage;
726 eatkey = true;
727 }
728 else
729 {
730 if (french)
731 c = ForeignTranslation(c);
732 if (shiftdown || (c >= 'a' && c <= 'z'))
733 c = shiftxform[c];
734 eatkey = HUlib_keyInIText(&w_chat, c);
735 if (eatkey)
736 {
737 // static unsigned char buf[20]; // DEBUG
738 HU_queueChatChar(c);
739
740 // sprintf(buf, "KEY: %d => %d", ev->data1, c);
741 // plr->message = buf;
742 }
743 if (c == KEY_ENTER)
744 {
745 chat_on = false;
746 if (w_chat.l.len)
747 {
748 strcpy(lastmessage, w_chat.l.l);
749 plr->message = lastmessage;
750 }
751 }
752 else if (c == KEY_ESCAPE)
753 chat_on = false;
754 }
755 }
756
757 return eatkey;
758
759 }
Something went wrong with that request. Please try again.