1 /*
2 Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20 #include "rt_def.h"
21 #include "rt_view.h"
22 #include "z_zone.h"
23 #include "w_wad.h"
24 #include "lumpy.h"
25 #include "rt_util.h"
26 #include "rt_vid.h"
27 #include "rt_str.h"
28 #include "rt_menu.h"
29 #include "_rt_msg.h"
30 #include "rt_msg.h"
31 #include "rt_playr.h"
32 #include "isr.h"
33 #include "rt_main.h"
34 #include "rt_net.h"
35 #include "rt_com.h"
36
37 #ifdef DOS
38 #include <mem.h>
39 #endif
40
41 #include <stdlib.h>
42 //MED
43 #include "memcheck.h"
44
45
46 /*
47 =============================================================================
48
49 GLOBALS
50
51 =============================================================================
52 */
53 messagetype Messages[MAXMSGS];
54
55 /*
56 =============================================================================
57
58 LOCAL
59
60 =============================================================================
61 */
62
63 static int UpdateMessageBackground;
64 static int MessageSystemStarted=0;
65 static int LastMessageTime;
66 static boolean EraseMessage[ MAXMSGS ];
67 static int MessageOrder[ MAXMSGS ];
68 static int TotalMessages = 0;
69 static int MsgPos = 0;
70
71 boolean MessagesEnabled = true;
72
StringLength(char * string)73 int StringLength (char *string)
74 {
75 int length=0;
76
77 while ((*string)!=0)
78 {
79 length++;
80 string++;
81 }
82
83 length++;
84
85 return length;
86 }
87
88 /*
89 ====================
90 =
91 = ResetMessageTime
92 =
93 ====================
94 */
95
ResetMessageTime(void)96 void ResetMessageTime ( void )
97 {
98 LastMessageTime=GetTicCount();
99 }
100
101 /*
102 ====================
103 =
104 = InitializeMessages
105 =
106 ====================
107 */
InitializeMessages(void)108 void InitializeMessages
109 (
110 void
111 )
112
113 {
114 int i;
115 boolean start;
116
117 start = false;
118
119 if ( MessageSystemStarted == 0 )
120 {
121 start = true;
122 MessageSystemStarted = 1;
123 memset( Messages, 0, sizeof( Messages ) );
124 }
125
126 for ( i = 0; i < MAXMSGS; i++ )
127 {
128 if ( Messages[ i ].active == 1 )
129 {
130 SafeFree( Messages[ i ].text );
131 Messages[ i ].active = 0;
132 Messages[ i ].tictime = 0;
133 Messages[ i ].flags = 0;
134 Messages[ i ].text = NULL;
135 }
136 }
137
138 MSG.messageon = false;
139
140 LastMessageTime = 0;
141 UpdateMessageBackground = 0;
142 TotalMessages = 0;
143 memset( EraseMessage, 0, sizeof( EraseMessage ) );
144 memset( MessageOrder, -1, sizeof( MessageOrder ) );
145
146 // Only print startup message if it's the first time in
147 if ( start && !quiet )
148 {
149 printf( "RT_MSG: Message System Started\n" );
150 }
151 }
152
153
154 /*
155 ====================
156 =
157 = GetMessageOrder
158 =
159 ====================
160 */
GetMessageOrder(void)161 void GetMessageOrder
162 (
163 void
164 )
165
166 {
167 int i;
168 int lowest;
169 int lowesttime;
170 byte done[ MAXMSGS ];
171 boolean found;
172
173 memset( &done[ 0 ], 0, sizeof( done ) );
174 memset( MessageOrder, -1, sizeof( MessageOrder ) );
175
176 for( TotalMessages = 0; TotalMessages < MAXMSGS; TotalMessages++ )
177 {
178 found = false;
179 lowesttime = 1000;
180 lowest = 0;
181
182 for( i = 0; i < MAXMSGS; i++ )
183 {
184 if ( ( Messages[ i ].active == 1 ) && ( done[ i ] == 0 ) &&
185 ( Messages[ i ].tictime < lowesttime ) )
186 {
187 lowesttime = Messages[ i ].tictime;
188 lowest = i;
189 found = true;
190 }
191 }
192
193 if ( !found )
194 {
195 break;
196 }
197
198 done[ lowest ] = 1;
199 MessageOrder[ TotalMessages ] = lowest;
200 }
201 }
202
203
204 /*
205 ====================
206 =
207 = DeleteMessage
208 =
209 ====================
210 */
DeleteMessage(int num)211 void DeleteMessage
212 (
213 int num
214 )
215
216 {
217 int i;
218 int msg;
219 boolean found;
220
221 found = false;
222 for( i = 0; i < TotalMessages; i++ )
223 {
224 msg = MessageOrder[ i ];
225
226 if ( msg == num )
227 {
228 found = true;
229 }
230
231 if ( found )
232 {
233 UpdateMessageBackground -= EraseMessage[ i ];
234 UpdateMessageBackground += 3;
235 EraseMessage[ i ] = 3;
236 }
237 }
238
239 SafeFree( Messages[ num ].text );
240 memset( &Messages[ num ], 0, sizeof( messagetype ) );
241
242 GetMessageOrder();
243 }
244
245
246 /*
247 ====================
248 =
249 = DeletePriorityMessage
250 =
251 ====================
252 */
DeletePriorityMessage(int flags)253 void DeletePriorityMessage ( int flags )
254 {
255 int i;
256
257 for (i=0;i<MAXMSGS;i++)
258 {
259 if (Messages[i].active==1)
260 {
261 if (Messages[i].flags==flags)
262 DeleteMessage(i);
263 }
264 }
265 }
266
267
268 /*
269 ====================
270 =
271 = GetFreeMessage
272 =
273 ====================
274 */
GetFreeMessage(void)275 int GetFreeMessage
276 (
277 void
278 )
279
280 {
281 int i;
282 int found;
283
284 for( i = 0; i < MAXMSGS; i++ )
285 {
286 if ( Messages[ i ].active == 0 )
287 {
288 return( i );
289 }
290 }
291
292 found = -1;
293
294 for( i = 0; i < MAXMSGS; i++ )
295 {
296 if ( Messages[ i ].tictime >= 0 )
297 {
298 if ( found == -1 )
299 {
300 found = i;
301 }
302 else
303 {
304 if ( Messages[ i ].tictime < Messages[ found ].tictime )
305 {
306 found = i;
307 }
308 }
309 }
310 }
311
312 DeleteMessage( found );
313
314 return( found );
315 }
316
317
318 /*
319 ====================
320 =
321 = SetMessage
322 =
323 ====================
324 */
SetMessage(int num,char * text,int flags)325 void SetMessage
326 (
327 int num,
328 char *text,
329 int flags
330 )
331
332 {
333 int i;
334 int msg;
335 int length;
336 boolean found;
337
338
339 length = StringLength( text );
340
341 Messages[ num ].active = 1;
342 Messages[ num ].flags = flags;
343
344 if ( PERMANENT_MSG( flags ) )
345 {
346 int l;
347
348 l = COM_MAXTEXTSTRINGLENGTH + 1;
349 Messages[ num ].text = SafeMalloc( l );
350 memset( Messages[ num ].text, 0, l );
351
352 // Hack so that we can place menu in certain order
353 Messages[ num ].tictime = -100 + MsgPos;
354 }
355 else
356 {
357 Messages[ num ].text = SafeMalloc( length );
358
359 memset( Messages[ num ].text, 0, length );
360 Messages[ num ].tictime = MESSAGETIME;
361 }
362
363 memcpy( Messages[ num ].text, text, length );
364
365 GetMessageOrder();
366 found = false;
367 for( i = 0; i < TotalMessages; i++ )
368 {
369 msg = MessageOrder[ i ];
370 if ( msg == num )
371 {
372 found = true;
373 }
374 else if ( found )
375 {
376 UpdateMessageBackground -= EraseMessage[ i - 1 ];
377 UpdateMessageBackground += 3;
378 EraseMessage[ i - 1 ] = 3;
379 }
380 }
381 }
382
383
384 /*
385 ====================
386 =
387 = AddMessage
388 =
389 ====================
390 */
AddMessage(char * text,int flags)391 int AddMessage
392 (
393 char *text,
394 int flags
395 )
396
397 {
398 int new;
399
400 if ( MessageSystemStarted == 0 )
401 {
402 Error( "Called AddMessage without starting Message system\n" );
403 }
404
405 if ( !( flags & MSG_NODELETE ) )
406 {
407 DeletePriorityMessage( flags );
408 }
409
410 new = GetFreeMessage();
411 SetMessage( new, text, flags );
412
413 return( new );
414 }
415
416 /*
417 ====================
418 =
419 = UpdateMessages
420 =
421 ====================
422 */
UpdateMessages(void)423 void UpdateMessages
424 (
425 void
426 )
427
428 {
429 int messagetics;
430 int i;
431
432 messagetics = GetTicCount() - LastMessageTime;
433 LastMessageTime = GetTicCount();
434
435 if ( GamePaused == true )
436 {
437 return;
438 }
439
440 for( i = 0; i < MAXMSGS; i++ )
441 {
442 if ( ( Messages[ i ].active == 1 ) &&
443 ( !PERMANENT_MSG( Messages[ i ].flags ) ) )
444 {
445 Messages[ i ].tictime -= messagetics;
446 if ( Messages[ i ].tictime <= 0 )
447 {
448 DeleteMessage( i );
449 }
450 }
451 }
452 }
453
454
455 /*
456 ====================
457 =
458 = DisplayMessage
459 =
460 ====================
461 */
462
DisplayMessage(int num,int position)463 void DisplayMessage
464 (
465 int num,
466 int position
467 )
468
469 {
470 PrintX = 1;
471 PrintY = 2 + ( position * 9 );
472
473 if ( SHOW_TOP_STATUS_BAR() )
474 {
475 PrintY += 16;
476 }
477 if ( !MessagesEnabled )
478 {
479 switch ( Messages[ num ].flags )
480 {
481 case MSG_QUIT:
482 case MSG_MACRO:
483 case MSG_MODEM:
484 case MSG_NAMEMENU:
485 case MSG_MSGSYSTEM:
486 break;
487
488 case MSG_REMOTERIDICULE:
489 case MSG_REMOTE:
490 case MSG_GAME:
491 case MSG_DOOR:
492 case MSG_BONUS:
493 case MSG_BONUS1:
494 case MSG_CHEAT:
495 case MSG_SYSTEM:
496 default :
497 DeleteMessage( num );
498 return;
499 }
500 }
501
502 switch ( Messages[ num ].flags )
503 {
504 case MSG_REMOTERIDICULE:
505 case MSG_REMOTE:
506 fontcolor = egacolor[ WHITE ];
507 break;
508
509 case MSG_MODEM:
510 fontcolor = egacolor[ LIGHTBLUE ];
511 DrawIString( PrintX, PrintY, "Message>", Messages[ num ].flags );
512 PrintX += 8 * 8;
513 fontcolor = egacolor[ LIGHTGRAY ];
514 break;
515
516 case MSG_GAME:
517 case MSG_DOOR:
518 case MSG_BONUS:
519 case MSG_BONUS1:
520 case MSG_NAMEMENU:
521 fontcolor = egacolor[ GREEN ];
522 break;
523
524 case MSG_CHEAT:
525 fontcolor = egacolor[ YELLOW ];
526 break;
527 case MSG_MSGSYSTEM:
528 case MSG_SYSTEM:
529 case MSG_QUIT:
530 case MSG_MACRO:
531 fontcolor = egacolor[ RED ];
532 break;
533
534 default :
535 #if ((DEVELOPMENT == 1))
536 Error( "DisplayMessage called with invalid priority number." );
537 #else
538 fontcolor = egacolor[ LIGHTGREEN ];
539 #endif
540 }
541
542 DrawIString( PrintX, PrintY, Messages[ num ].text, Messages[ num ].flags );
543 }
544
545
546
547 /*
548 ====================
549 =
550 = RestoreMessageBackground
551 =
552 ====================
553 */
RestoreMessageBackground(void)554 void RestoreMessageBackground
555 (
556 void
557 )
558
559 {
560 pic_t *shape;
561 int i;
562 int y;
563
564 if ( UpdateMessageBackground > 0 )
565 {
566 y = 18;
567 for( i = 0; i < MAXMSGS; i++ )
568 {
569 if ( EraseMessage[ i ] )
570 {
571 UpdateMessageBackground--;
572 EraseMessage[ i ]--;
573 if ( viewsize < 15 )
574 {
575 shape = W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
576 DrawTiledRegion( 0, y, 320, 9, 0, y, shape );
577 }
578 if ( viewsize == 0 )
579 {
580 if ( ( y + 9 > YOURCPUSUCKS_Y ) &&
581 ( y < ( YOURCPUSUCKS_Y + YOURCPUSUCKS_HEIGHT ) ) )
582 {
583 DrawCPUJape();
584 }
585 }
586 }
587
588 y += 9;
589 }
590 }
591 }
592
593
594 /*
595 ====================
596 =
597 = DrawMessages
598 =
599 ====================
600 */
DrawMessages(void)601 void DrawMessages
602 (
603 void
604 )
605
606 {
607 int i;
608
609 if ( TotalMessages > 0 )
610 {
611 IFont = ( cfont_t * )W_CacheLumpName( "ifnt", PU_CACHE, Cvt_cfont_t, 1 );
612
613 for( i = 0; i < TotalMessages; i++ )
614 {
615 DisplayMessage( MessageOrder[ i ], i );
616 }
617 }
618 UpdateMessages();
619 }
620
621
622 /*
623 ====================
624 =
625 = UpdateModemMessage
626 =
627 ====================
628 */
UpdateModemMessage(int num,char c)629 void UpdateModemMessage
630 (
631 int num,
632 char c
633 )
634
635 {
636 int i;
637
638 Messages[ num ].text[ MSG.length - 1 ] = ( byte )c;
639 Messages[ num ].text[ MSG.length ] = ( byte )'_';
640 MSG.length++;
641
642 for( i = 0; i < TotalMessages; i++ )
643 {
644 if ( MessageOrder[ i ] == num )
645 {
646 UpdateMessageBackground -= EraseMessage[ i ];
647 UpdateMessageBackground += 3;
648 EraseMessage[ i ] = 3;
649 break;
650 }
651 }
652 }
653
654
655 /*
656 ====================
657 =
658 = ModemMessageDeleteChar
659 =
660 ====================
661 */
ModemMessageDeleteChar(int num)662 void ModemMessageDeleteChar
663 (
664 int num
665 )
666
667 {
668 int i;
669
670 MSG.length--;
671 Messages[ num ].text[ MSG.length ] = ( byte )0;
672 Messages[ num ].text[ MSG.length - 1 ] = ( byte )'_';
673
674 for( i = 0; i < TotalMessages; i++ )
675 {
676 if ( MessageOrder[ i ] == num )
677 {
678 UpdateMessageBackground -= EraseMessage[ i ];
679 UpdateMessageBackground += 3;
680 EraseMessage[ i ] = 3;
681 break;
682 }
683 }
684 }
685
686
687 /*
688 ====================
689 =
690 = DrawPlayerSelectionMenu
691 =
692 ====================
693 */
694
DrawPlayerSelectionMenu(void)695 void DrawPlayerSelectionMenu
696 (
697 void
698 )
699
700 {
701 int i;
702 int p;
703 char str[ 20 ];
704
705 p = 1;
706 MsgPos = 1;
707 AddMessage( "Press a key from 0 to 9 to select", MSG_NAMEMENU );
708 MsgPos++;
709 AddMessage( "who to send your message to:", MSG_NAMEMENU );
710 MsgPos++;
711
712 for( i = 0; i < numplayers; i++ )
713 {
714 if ( i != consoleplayer )
715 {
716 strcpy( str, "0 - " );
717 strcat( str, PLAYERSTATE[ i ].codename );
718 str[ 0 ] = '0' + p;
719 p++;
720 if ( p > 9 )
721 {
722 p = 0;
723 }
724
725 AddMessage( str, MSG_NAMEMENU );
726 MsgPos++;
727 }
728 }
729
730 if ( ( MsgPos < MAXMSGS - 1 ) && ( gamestate.teamplay ) )
731 {
732 AddMessage( "T - All team members", MSG_NAMEMENU );
733 MsgPos++;
734 }
735
736 if ( MsgPos < MAXMSGS - 1 )
737 {
738 AddMessage( "A - All players", MSG_NAMEMENU );
739 }
740
741 MsgPos = 0;
742 }
743
744
745 /*
746 ====================
747 =
748 = FinishModemMessage
749 =
750 ====================
751 */
FinishModemMessage(int num,boolean send)752 void FinishModemMessage
753 (
754 int num,
755 boolean send
756 )
757 {
758 if ( ( !MSG.inmenu ) && ( MSG.length > 0 ) )
759 {
760 Messages[ num ].text[ MSG.length - 1 ] = ( byte )0;
761 MSG.length--;
762 }
763
764 if ( ( send == true ) && ( ( MSG.length > 0 ) ||
765 ( MSG.remoteridicule != -1 ) ) )
766 {
767 if ( ( MSG.directed ) && ( !MSG.inmenu ) )
768 {
769 DrawPlayerSelectionMenu();
770 MSG.messageon = true;
771 MSG.inmenu = true;
772 return;
773 }
774
775 MSG.messageon = false;
776 if ( MSG.remoteridicule != -1 )
777 {
778 AddRemoteRidiculeCommand( consoleplayer, MSG.towho,
779 MSG.remoteridicule );
780 }
781 if ( MSG.length > 0 )
782 {
783 AddTextMessage( Messages[ num ].text, MSG.length, MSG.towho );
784 }
785 }
786
787 if ( MSG.inmenu )
788 {
789 DeletePriorityMessage( MSG_NAMEMENU );
790 }
791
792 DeleteMessage( num );
793 }
794