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