]> icculus.org git repositories - btb/d2x.git/blob - main/hud.c
use the orientation parameter of g3_draw_bitmap
[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 "dxxerror.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
243         Modex_hud_msg_count = 2;
244
245         if ( (hud_last < 0) || (hud_last >= HUD_MAX_NUM))
246                 Int3(); // Get Rob!!
247
248         // -- mprintf((0, "message timer: %7.3f\n", f2fl(HUD_message_timer)));
249         message = &HUD_messages[hud_last][0];
250         vsprintf(message,format,args);
251
252
253         /* Produce a colorised version and send it to the console */
254         if (HUD_color == -1)
255                 HUD_color = BM_XRGB(0,28,0);
256         con_printf(CON_NORMAL, "%c%c%s%c%c\n", CC_COLOR, HUD_color, message, CC_COLOR, CON_color);
257
258         // Added by Leighton
259
260    if ((Game_mode & GM_MULTI) && FindArg("-noredundancy"))
261          if (!strnicmp ("You already",message,11))
262                 return 0;
263
264    if ((Game_mode & GM_MULTI) && FindArg("-PlayerMessages") && PlayerMessage==0)
265                 return 0;
266
267         if (HUD_nmessages > 0)  {
268                 if (hud_last==0)
269                         last_message = &HUD_messages[HUD_MAX_NUM-1][0];
270                 else
271                         last_message = &HUD_messages[hud_last-1][0];
272         }
273
274         temp = (hud_last+1) % HUD_MAX_NUM;
275
276         if ( temp==hud_first )  {
277                 // If too many messages, remove oldest message to make room
278                 hud_first = (hud_first+1) % HUD_MAX_NUM;
279                 HUD_nmessages--;
280         }
281
282         if (last_message && (!strcmp(last_message, message))) {
283                 HUD_message_timer = F1_0*3;             // 1 second per 5 characters
284                 return 0;       // ignore since it is the same as the last one
285         }
286
287         hud_last = temp;
288         // Check if memory has been overwritten at this point.
289         if (strlen(message) >= HUD_MESSAGE_LENGTH)
290                 Error( "Your message to HUD is too long.  Limit is %i characters.\n", HUD_MESSAGE_LENGTH);
291         #ifdef NEWDEMO
292         if (Newdemo_state == ND_STATE_RECORDING )
293                 newdemo_record_hud_message( message );
294         #endif
295         HUD_message_timer = F1_0*3;             // 1 second per 5 characters
296         HUD_nmessages++;
297
298         return 1;
299 }
300
301
302 int HUD_init_message(char * format, ... )
303 {
304         int ret;
305         va_list args;
306
307         va_start(args, format);
308         ret = HUD_init_message_va(format, args);
309         va_end(args);
310
311         return ret;
312 }
313
314
315 //@@void player_dead_message(void)
316 //@@{
317 //@@    if (!Arcade_mode && Player_exploded) { //(ConsoleObject->flags & OF_EXPLODING)) {
318 //@@            gr_set_curfont( SMALL_FONT );
319 //@@            if (HUD_color == -1)
320 //@@                    HUD_color = BM_XRGB(0,28,0);
321 //@@            gr_set_fontcolor( HUD_color, -1);
322 //@@
323 //@@            gr_printf(0x8000, grd_curcanv->cv_bitmap.bm_h-8, TXT_PRESS_ANY_KEY);
324 //@@            gr_set_curfont( GAME_FONT );
325 //@@    }
326 //@@
327 //@@}
328
329 void player_dead_message(void)
330 {
331     if (Player_exploded) {
332         if ( Players[Player_num].lives < 2 )    {
333             int x, y, w, h, aw;
334             gr_set_curfont( HUGE_FONT );
335             gr_get_string_size( TXT_GAME_OVER, &w, &h, &aw );
336             w += 20;
337             h += 8;
338             x = (grd_curcanv->cv_w - w ) / 2;
339             y = (grd_curcanv->cv_h - h ) / 2;
340
341             Gr_scanline_darkening_level = 2*7;
342             gr_setcolor( BM_XRGB(0,0,0) );
343             gr_rect( x, y, x+w, y+h );
344             Gr_scanline_darkening_level = GR_FADE_LEVELS;
345
346             gr_string(0x8000, (grd_curcanv->cv_h - grd_curcanv->cv_font->ft_h)/2 + h/8, TXT_GAME_OVER );
347
348 #if 0
349             // Automatically exit death after 10 secs
350             if ( GameTime > Player_time_of_death + F1_0*10 ) {
351                     Function_mode = FMODE_MENU;
352                     Game_mode = GM_GAME_OVER;
353                     longjmp( LeaveGame, 1 );        // Exit out of game loop
354             }
355 #endif
356
357         }
358         gr_set_curfont( GAME_FONT );
359         if (HUD_color == -1)
360             HUD_color = BM_XRGB(0,28,0);
361         gr_set_fontcolor( HUD_color, -1);
362         gr_string(0x8000, grd_curcanv->cv_h-(grd_curcanv->cv_font->ft_h+3), TXT_PRESS_ANY_KEY);
363     }
364 }
365
366 // void say_afterburner_status(void)
367 // {
368 //      if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER)
369 //              HUD_init_message("Afterburner engaged.");
370 //      else
371 //              HUD_init_message("Afterburner disengaged.");
372 // }
373
374 void hud_message(int class, char *format, ...)
375 {
376         va_list vp;
377
378         va_start(vp, format);
379         if ((!MSG_Noredundancy || (class & MSGC_NOREDUNDANCY)) &&
380             (!MSG_Playermessages || !(Game_mode & GM_MULTI) ||
381              (class & MSGC_PLAYERMESSAGES)))
382                 HUD_init_message_va(format, vp);
383         va_end(vp);
384 }
385