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