This commit was manufactured by cvs2svn to create tag 'd2x-0_1_2'.
[btb/d2x.git] / main / hud.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  * $Source: /cvs/cvsroot/d2x/main/hud.c,v $
16  * $Revision: 1.3 $
17  * $Author: bradleyb $
18  * $Date: 2001-11-04 09:00:25 $
19  *
20  * Routines for displaying HUD messages...
21  *
22  * $Log: not supported by cvs2svn $
23  *
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include <conf.h>
28 #endif
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34
35 #include "hudmsg.h"
36
37 #include "pstypes.h"
38 #include "u_mem.h"
39 #include "strutil.h"
40 #include "console.h"
41 #include "inferno.h"
42 #include "game.h"
43 #include "screens.h"
44 #include "gauges.h"
45 #include "physics.h"
46 #include "error.h"
47
48 #include "menu.h"                       // For the font.
49 #include "mono.h"
50 #include "collide.h"
51 #include "newdemo.h"
52 #include "player.h"
53 #include "gamefont.h"
54
55 #include "wall.h"
56 #include "screens.h"
57 #include "text.h"
58 #include "laser.h"
59 #include "args.h"
60 #include "pa_enabl.h"
61
62 int hud_first = 0;
63 int hud_last = 0;
64
65 int     HUD_nmessages = 0;
66 fix     HUD_message_timer = 0;          // Time, relative to Players[Player_num].time (int.frac seconds.frac), at which to erase gauge message
67 char  HUD_messages[HUD_MAX_NUM][HUD_MESSAGE_LENGTH+5];
68
69 extern void copy_background_rect(int left,int top,int right,int bot);
70 char Displayed_background_message[2][HUD_MESSAGE_LENGTH] = {"",""};
71 int     Last_msg_ycrd = -1;
72 int     Last_msg_height = 6;
73 int     HUD_color = -1;
74
75 int     MSG_Playermessages = 0;
76 int     MSG_Noredundancy = 0;
77
78 int     Modex_hud_msg_count;
79
80 #define LHX(x)          ((x)*(FontHires?2:1))
81 #define LHY(y)          ((y)*(FontHires?2.4:1))
82
83 #ifdef WINDOWS
84 int extra_clear=0;
85 #endif
86
87 //      -----------------------------------------------------------------------------
88 void clear_background_messages(void)
89 {
90         #ifdef WINDOWS
91         if (extra_clear == FrameCount)          //don't do extra clear on same frame
92                 return;
93         #endif
94
95 #ifdef WINDOWS
96         if (((Cockpit_mode == CM_STATUS_BAR) || (Cockpit_mode == CM_FULL_SCREEN)) && (Last_msg_ycrd != -1) && (dd_VR_render_sub_buffer[0].yoff >= 6)) {
97                 dd_grs_canvas *canv_save = dd_grd_curcanv;
98 #else
99         if (((Cockpit_mode == CM_STATUS_BAR) || (Cockpit_mode == CM_FULL_SCREEN)) && (Last_msg_ycrd != -1) && (VR_render_sub_buffer[0].cv_bitmap.bm_y >= 6)) {
100                 grs_canvas      *canv_save = grd_curcanv;
101 #endif    
102
103                 WINDOS( dd_gr_set_current_canvas(get_current_game_screen()),
104                                 gr_set_current_canvas(get_current_game_screen())
105                 );
106
107                 PA_DFX (pa_set_frontbuffer_current());
108                 PA_DFX (copy_background_rect(0, Last_msg_ycrd, grd_curcanv->cv_bitmap.bm_w, Last_msg_ycrd+Last_msg_height-1));
109                 PA_DFX (pa_set_backbuffer_current());
110                 copy_background_rect(0, Last_msg_ycrd, grd_curcanv->cv_bitmap.bm_w, Last_msg_ycrd+Last_msg_height-1);
111           
112                 WINDOS( 
113                         dd_gr_set_current_canvas(canv_save),
114                         gr_set_current_canvas(canv_save)
115                 );
116
117                 #ifdef WINDOWS
118                 if (extra_clear || !GRMODEINFO(modex)) {
119                         extra_clear = 0;
120                         Last_msg_ycrd = -1;
121                 }
122                 else
123                         extra_clear = FrameCount;
124                 #else
125                 Last_msg_ycrd = -1;
126                 #endif
127         }
128
129         Displayed_background_message[VR_current_page][0] = 0;
130
131 }
132
133 void HUD_clear_messages()
134 {
135         int i;
136         HUD_nmessages = 0;
137         hud_first = hud_last = 0;
138         HUD_message_timer = 0;
139         clear_background_messages();
140         for (i = 0; i < HUD_MAX_NUM; i++)
141                 sprintf(HUD_messages[i], "SlagelSlagel!!");
142 }
143
144
145 extern int Guided_in_big_window;
146 extern int max_window_h;
147
148 extern grs_canvas *print_to_canvas(char *s,grs_font *font, int fc, int bc, int double_flag);
149
150 //      -----------------------------------------------------------------------------
151 //      print to buffer, double heights, and blit bitmap to screen
152 void modex_hud_message(int x, int y, char *s, grs_font *font, int color)
153 {
154         grs_canvas *temp_canv;
155
156         temp_canv = print_to_canvas(s, font, color, -1, 1);
157
158         gr_bitmapm(x,y,&temp_canv->cv_bitmap);
159
160         gr_free_canvas(temp_canv);
161 }
162
163 extern int max_window_w;
164
165 //      -----------------------------------------------------------------------------
166 //      Writes a message on the HUD and checks its timer.
167 void HUD_render_message_frame()
168 {
169         int i, y,n;
170         int h,w,aw;
171
172         if (( HUD_nmessages < 0 ) || (HUD_nmessages > HUD_MAX_NUM))
173                 Int3(); // Get Rob!
174
175         if ( (HUD_nmessages < 1 ) && (Modex_hud_msg_count == 0))
176                 return;
177
178         HUD_message_timer -= FrameTime;
179
180         #ifdef WINDOWS
181         if (extra_clear)
182                 clear_background_messages();                    //      If in status bar mode and no messages, then erase.
183         #endif
184
185         if ( HUD_message_timer < 0 )    {
186                 // Timer expired... get rid of oldest message...
187                 if (hud_last!=hud_first)        {
188                         int     temp;
189
190                         //&HUD_messages[hud_first][0] is deing deleted...;
191                         hud_first = (hud_first+1) % HUD_MAX_NUM;
192                         HUD_message_timer = F1_0*2;
193                         HUD_nmessages--;
194                         if (HUD_nmessages == 0)
195                                 Modex_hud_msg_count = 2;
196                         temp = Last_msg_ycrd;
197                         clear_background_messages();                    //      If in status bar mode and no messages, then erase.
198                         if (Modex_hud_msg_count)
199                                 Last_msg_ycrd = temp;
200                 }
201         }
202
203         if (HUD_nmessages > 0 ) {
204
205                 if (HUD_color == -1)
206                         HUD_color = BM_XRGB(0,28,0);
207
208         #ifdef WINDOWS
209                 if ( (VR_render_mode==VR_NONE) && ((Cockpit_mode == CM_STATUS_BAR) || (Cockpit_mode == CM_FULL_SCREEN)) && (dd_VR_render_sub_buffer[0].yoff >= (max_window_h/8))) {
210         #else
211                 if ( (VR_render_mode==VR_NONE) && ((Cockpit_mode == CM_STATUS_BAR) || (Cockpit_mode == CM_FULL_SCREEN)) && (VR_render_sub_buffer[0].cv_bitmap.bm_y >= (max_window_h/8))) {
212         #endif
213                         // Only display the most recent message in this mode
214                         char    *message = HUD_messages[(hud_first+HUD_nmessages-1) % HUD_MAX_NUM];
215
216                         if (strcmp(Displayed_background_message[VR_current_page], message)) {
217                                 int     ycrd;
218                                 WINDOS(
219                                         dd_grs_canvas *canv_save = dd_grd_curcanv,
220                                         grs_canvas      *canv_save = grd_curcanv
221                                 );
222
223                                 #ifdef MACINTOSH
224                                 if (Scanline_double)
225                                         FontHires=1;    // always display hires font outside of display
226                                 #endif
227
228                                 WINDOS(
229                                         ycrd = dd_grd_curcanv->yoff - (SMALL_FONT->ft_h+2),
230                                         ycrd = grd_curcanv->cv_bitmap.bm_y - (SMALL_FONT->ft_h+2)
231                                 );
232
233                                 if (ycrd < 0)
234                                         ycrd = 0;
235
236                                 WINDOS(
237                                         dd_gr_set_current_canvas(get_current_game_screen()),
238                                         gr_set_current_canvas(get_current_game_screen())
239                                 );
240
241                                 gr_set_curfont( SMALL_FONT );
242                                 gr_get_string_size(message, &w, &h, &aw );
243                                 clear_background_messages();
244
245
246                                 if (grd_curcanv->cv_bitmap.bm_type == BM_MODEX) {
247                                         WIN(Int3());                                    // No no no no ....
248                                         ycrd -= h;
249                                         h *= 2;
250                                         modex_hud_message((grd_curcanv->cv_bitmap.bm_w-w)/2, ycrd, message, SMALL_FONT, HUD_color);
251                                         if (Modex_hud_msg_count > 0) {
252                                                 Modex_hud_msg_count--;
253                                                 Displayed_background_message[VR_current_page][0] = '!';
254                                         } else
255                                                 strcpy(Displayed_background_message[VR_current_page], message);
256                                 } else {
257                                 WIN(DDGRLOCK(dd_grd_curcanv));
258                                         gr_set_fontcolor( HUD_color, -1);
259                                         PA_DFX (pa_set_frontbuffer_current());
260                                         PA_DFX (gr_printf((grd_curcanv->cv_bitmap.bm_w-w)/2, ycrd, message ));
261                                         PA_DFX (pa_set_backbuffer_current());
262                                         gr_printf((grd_curcanv->cv_bitmap.bm_w-w)/2, ycrd, message );
263                                         strcpy(Displayed_background_message[VR_current_page], message);
264                                 WIN(DDGRUNLOCK(dd_grd_curcanv));
265                                 }
266
267                         WINDOS(
268                                 dd_gr_set_current_canvas(canv_save),
269                                 gr_set_current_canvas(canv_save)
270                         );
271
272                                 Last_msg_ycrd = ycrd;
273                                 Last_msg_height = h;
274
275                                 #ifdef MACINTOSH
276                                 if (Scanline_double)
277                                         FontHires=0;    // always display hires font outside of display
278                                 #endif
279
280                         }
281                 } else {
282
283                         gr_set_curfont( SMALL_FONT );
284
285                         if ( (Cockpit_mode == CM_FULL_SCREEN) || (Cockpit_mode == CM_LETTERBOX) ) {
286                                 if (Game_window_w == max_window_w)
287                                         y = SMALL_FONT->ft_h/2;
288                                 else
289                                         y= SMALL_FONT->ft_h * 2;
290                         } else
291                                 y = SMALL_FONT->ft_h/2;
292
293                   if (Guided_missile[Player_num] && Guided_missile[Player_num]->type==OBJ_WEAPON && Guided_missile[Player_num]->id==GUIDEDMISS_ID &&
294                       Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num] && Guided_in_big_window)
295                               y+=SMALL_FONT->ft_h+3; 
296
297                 WIN(DDGRLOCK(dd_grd_curcanv));
298                         for (i=0; i<HUD_nmessages; i++ )        {       
299                                 n = (hud_first+i) % HUD_MAX_NUM;
300                                 if ((n < 0) || (n >= HUD_MAX_NUM))
301                                         Int3(); // Get Rob!!
302                                 if (!strcmp(HUD_messages[n], "This is a bug."))
303                                         Int3(); // Get Rob!!
304                                 gr_get_string_size(&HUD_messages[n][0], &w, &h, &aw );
305                                 gr_set_fontcolor( HUD_color, -1);
306                         
307                                 PA_DFX (pa_set_frontbuffer_current());
308                                 PA_DFX(gr_string((grd_curcanv->cv_bitmap.bm_w-w)/2,y, &HUD_messages[n][0] ));
309                                 PA_DFX (pa_set_backbuffer_current());
310                                 gr_string((grd_curcanv->cv_bitmap.bm_w-w)/2,y, &HUD_messages[n][0] );
311                                 y += h+1;
312                         }
313                 WIN(DDGRUNLOCK(dd_grd_curcanv));
314                 }
315         } 
316         #ifndef WINDOWS
317         else if (get_current_game_screen()->cv_bitmap.bm_type == BM_MODEX) {
318                 if (Modex_hud_msg_count) {
319                         int     temp = Last_msg_ycrd;
320                         Modex_hud_msg_count--;
321                         clear_background_messages();                    //      If in status bar mode and no messages, then erase.
322                         Last_msg_ycrd = temp;
323                 }
324         }
325         #endif
326
327         gr_set_curfont( GAME_FONT );    
328 }
329
330 int PlayerMessage=1;
331
332 // Call to flash a message on the HUD.  Returns true if message drawn.
333 //  (message might not be drawn if previous message was same)
334 int HUD_init_message(char * format, ... )
335 {
336         va_list args;
337         int temp, temp2;
338         char *message = NULL;
339         char *last_message=NULL;
340         char *cleanmessage;
341
342         Modex_hud_msg_count = 2;
343
344         if ( (hud_last < 0) || (hud_last >= HUD_MAX_NUM))
345                 Int3(); // Get Rob!!
346
347         // -- mprintf((0, "message timer: %7.3f\n", f2fl(HUD_message_timer)));
348         va_start(args, format );
349         message = &HUD_messages[hud_last][0];
350         vsprintf(message,format,args);
351         va_end(args);
352         
353         /* Produce a sanitised version and send it to the console */
354         cleanmessage = d_strdup(message);
355         for (temp=0,temp2=0; message[temp]!=0; temp++)
356         {
357                 if (isprint(message[temp])) cleanmessage[temp2++] = message[temp];
358                 else temp++; /* Skip next character as well */
359         }
360         cleanmessage[temp2] = 0;
361         con_printf(CON_NORMAL, "%s\n", message);
362         d_free(cleanmessage);
363
364         // Added by Leighton 
365    
366    if ((Game_mode & GM_MULTI) && FindArg("-noredundancy"))
367          if (!strnicmp ("You already",message,11))
368                 return 0;
369
370    if ((Game_mode & GM_MULTI) && FindArg("-PlayerMessages") && PlayerMessage==0)
371                 return 0;
372   
373         if (HUD_nmessages > 0)  {
374                 if (hud_last==0)
375                         last_message = &HUD_messages[HUD_MAX_NUM-1][0];
376                 else
377                         last_message = &HUD_messages[hud_last-1][0];
378         }
379
380         temp = (hud_last+1) % HUD_MAX_NUM;
381
382         if ( temp==hud_first )  {
383                 // If too many messages, remove oldest message to make room
384                 hud_first = (hud_first+1) % HUD_MAX_NUM;
385                 HUD_nmessages--;
386         }
387
388         if (last_message && (!strcmp(last_message, message))) {
389                 HUD_message_timer = F1_0*3;             // 1 second per 5 characters
390                 return 0;       // ignore since it is the same as the last one
391         }
392
393         hud_last = temp;
394         // Check if memory has been overwritten at this point.
395         if (strlen(message) >= HUD_MESSAGE_LENGTH)
396                 Error( "Your message to HUD is too long.  Limit is %i characters.\n", HUD_MESSAGE_LENGTH);
397         #ifdef NEWDEMO
398         if (Newdemo_state == ND_STATE_RECORDING )
399                 newdemo_record_hud_message( message );
400         #endif
401         HUD_message_timer = F1_0*3;             // 1 second per 5 characters
402         HUD_nmessages++;
403
404         return 1;
405 }
406
407
408 //@@void player_dead_message(void)
409 //@@{
410 //@@    if (!Arcade_mode && Player_exploded) { //(ConsoleObject->flags & OF_EXPLODING)) {
411 //@@            gr_set_curfont( SMALL_FONT );    
412 //@@            if (HUD_color == -1)
413 //@@                    HUD_color = BM_XRGB(0,28,0);
414 //@@            gr_set_fontcolor( HUD_color, -1);
415 //@@
416 //@@            gr_printf(0x8000, grd_curcanv->cv_bitmap.bm_h-8, TXT_PRESS_ANY_KEY);
417 //@@            gr_set_curfont( GAME_FONT );    
418 //@@    }
419 //@@
420 //@@}
421
422 void player_dead_message(void)
423 {
424     if (Player_exploded) {      
425         if ( Players[Player_num].lives < 2 )    {
426             int x, y, w, h, aw;
427             gr_set_curfont( HUGE_FONT );    
428             gr_get_string_size( TXT_GAME_OVER, &w, &h, &aw );
429             w += 20;
430             h += 8;
431             x = (grd_curcanv->cv_w - w ) / 2;
432             y = (grd_curcanv->cv_h - h ) / 2;
433             
434             NO_DFX (Gr_scanline_darkening_level = 2*7);
435             NO_DFX (gr_setcolor( BM_XRGB(0,0,0) ));
436             NO_DFX (gr_rect( x, y, x+w, y+h ));
437             Gr_scanline_darkening_level = GR_FADE_LEVELS;
438
439             gr_string(0x8000, (grd_curcanv->cv_h - grd_curcanv->cv_font->ft_h)/2 + h/8, TXT_GAME_OVER );
440
441 #if 0
442             // Automatically exit death after 10 secs
443             if ( GameTime > Player_time_of_death + F1_0*10 ) {
444                     Function_mode = FMODE_MENU;
445                     Game_mode = GM_GAME_OVER;
446                     longjmp( LeaveGame, 1 );        // Exit out of game loop
447             }
448 #endif
449
450         } 
451         gr_set_curfont( GAME_FONT );    
452         if (HUD_color == -1)
453             HUD_color = BM_XRGB(0,28,0);
454         gr_set_fontcolor( HUD_color, -1);
455         gr_string(0x8000, grd_curcanv->cv_h-(grd_curcanv->cv_font->ft_h+3), TXT_PRESS_ANY_KEY);
456     }
457 }
458
459 // void say_afterburner_status(void)
460 // {
461 //      if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER)
462 //              HUD_init_message("Afterburner engaged.");
463 //      else
464 //              HUD_init_message("Afterburner disengaged.");
465 // }
466
467 void hud_message(int class, char *format, ...)
468 {
469  va_list vp;
470  va_start(vp, format);
471   if ((!MSG_Noredundancy || (class & MSGC_NOREDUNDANCY)) &&
472       (!MSG_Playermessages || !(Game_mode & GM_MULTI) ||
473       (class & MSGC_PLAYERMESSAGES)))
474    HUD_init_message(format, vp);
475  va_end(vp);
476 }
477