2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Hud/HUDmessage.cpp $
15 * C module that controls and manages the message window on the HUD
18 * Revision 1.9 2005/03/29 02:18:47 taylor
19 * Various 64-bit platform fixes
20 * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
21 * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
22 * Streaming audio support (big thanks to Pierre Willenbrock!!)
23 * Removed dependance on strings.tbl for FS1 since we don't actually need it now
25 * Revision 1.8 2004/09/20 01:31:44 theoddone33
28 * Revision 1.7 2003/05/25 02:30:42 taylor
31 * Revision 1.6 2002/07/28 05:05:08 relnev
32 * removed some old stuff
34 * Revision 1.5 2002/07/13 06:46:48 theoddone33
37 * Revision 1.4 2002/06/09 04:41:21 relnev
38 * added copyright header
40 * Revision 1.3 2002/06/02 04:26:34 relnev
43 * Revision 1.2 2002/05/03 13:34:33 theoddone33
46 * Revision 1.1.1.1 2002/05/03 03:28:09 root
50 * 23 9/08/99 5:38p Jefff
52 * 22 9/08/99 2:38p Jefff
53 * sound pausing going to menu from game
55 * 21 9/07/99 9:42p Jefff
57 * 20 9/02/99 11:47a Jefff
58 * yet another hud message length adjustment. yeesh.
60 * 19 8/25/99 10:08a Jefff
61 * fixed another messge cut-off bug
63 * 18 8/23/99 11:12a Jefff
64 * fixed 1024 message cut-off bug
66 * 17 8/20/99 2:26p Jefff
67 * hud message text wrapping problem in hires fixed
69 * 16 8/03/99 7:27p Jefff
70 * hud messages go completely across screnn in high res now
72 * 15 8/03/99 6:21p Jefff
73 * fixed stupid bug with objectives screen key
75 * 14 8/01/99 12:39p Dave
76 * Added HUD contrast control key (for nebula).
78 * 13 7/29/99 2:58p Jefff
79 * Ingame objective screen icon key now uses normal objective icons and
80 * text is drawn in code.
82 * 12 6/16/99 5:26p Dave
83 * Fixed some bitmap and coordinate problems on the mission scrollback
86 * 11 6/10/99 3:43p Dave
87 * Do a better job of syncing text colors to HUD gauges.
89 * 10 2/02/99 10:13a Neilk
92 * 9 2/01/99 5:55p Dave
93 * Removed the idea of explicit bitmaps for buttons. Fixed text
94 * highlighting for disabled gadgets.
96 * 8 1/30/99 5:08p Dave
97 * More new hi-res stuff.Support for nice D3D textures.
99 * 7 1/30/99 3:09p Neilk
100 * More mission log coord fixes
102 * 6 1/30/99 2:59p Neilk
103 * Fixed more mission log coords
105 * 5 1/29/99 7:57p Neilk
106 * Added support for multiresolutions
108 * 4 1/06/99 2:24p Dave
109 * Stubs and release build fixes.
111 * 3 10/13/98 9:28a Dave
112 * Started neatening up freespace.h. Many variables renamed and
113 * reorganized. Added AlphaColors.[h,cpp]
115 * 2 10/07/98 10:53a Dave
118 * 1 10/07/98 10:49a Dave
120 * 89 6/09/98 5:17p Lawrance
121 * French/German localization
123 * 88 6/09/98 10:31a Hoffoss
124 * Created index numbers for all xstr() references. Any new xstr() stuff
125 * added from here on out should be added to the end if the list. The
126 * current list count can be found in FreeSpace.cpp (search for
129 * 87 5/19/98 8:36p Andsager
130 * Fix bug where last line of message log would not show if more than one
133 * 86 4/27/98 8:49p Allender
134 * make terran command display in white (with correct code anyway).
136 * 85 4/25/98 11:49p Lawrance
139 * 84 4/25/98 9:10p Hoffoss
140 * Fixed bug with scrollback origin.
142 * 83 4/25/98 5:22p Hoffoss
143 * Fixed some problems with scrolling and positioning, and added code to
144 * support pageup/pagedown.
146 * 82 4/14/98 5:06p Dave
147 * Don't load or send invalid pilot pics. Fixed chatbox graphic errors.
148 * Made chatbox display team icons in a team vs. team game. Fixed up pause
149 * and endgame sequencing issues.
151 * 81 4/14/98 2:44p Hoffoss
152 * Made arrow keys do what tab does.
154 * 80 4/08/98 4:10p John
155 * Removed all remaining traces of the evil gr_init_font_ex.
157 * 79 4/07/98 11:33a Hoffoss
158 * Fixed bug where scroll offset was wrong when first entering the F4
161 * 78 4/05/98 3:30p Dave
162 * Print netplayer messages in brighter green on the hud, with
163 * accompanying sound. Echo netplayer messages on sending machine. Fixed
164 * standalone sequencing bug where host never get the "enter mission"
167 * 77 3/27/98 11:57a Dave
168 * Put in expression checking for text messages.
170 * 76 3/17/98 4:01p Hoffoss
171 * Added HUD_SOURCE_TERRAN_CMD and changed code to utilize it when a
172 * message is being sent from Terran Command.
174 * 75 3/16/98 5:55p Lawrance
175 * Increase width of HUD message line, don't draw lines while comm menu is
178 * 74 3/12/98 4:03p Hoffoss
179 * Changed formatting used in hug scrollbacl log.
181 * 73 3/09/98 4:47p Hoffoss
182 * Changed F4 screen to start in objectives mode rather than HUD messages
185 * 72 3/09/98 2:50p Hoffoss
186 * Changed to use different palette file, and fixed bug with text
187 * overrunning the right edge of screen.
189 * 71 3/02/98 5:42p John
190 * Removed WinAVI stuff from Freespace. Made all HUD gauges wriggle from
191 * afterburner. Made gr_set_clip work good with negative x &y. Made
192 * model_caching be on by default. Made each cached model have it's own
193 * bitmap id. Made asteroids not rotate when model_caching is on.
195 * 70 2/27/98 4:55p Hoffoss
196 * Fixed some alignment problems.
198 * 69 2/27/98 4:37p Hoffoss
199 * Combined Objectives screen into Mission Log screen.
201 * 68 2/22/98 4:17p John
202 * More string externalization classification... 190 left to go!
204 * 67 2/22/98 12:19p John
205 * Externalized some strings
207 * 66 2/06/98 2:58p Hoffoss
208 * Fixed bug where mission log scrolls twice when using the arrow keys.
210 * 65 1/29/98 10:26a Hoffoss
211 * Made changes so arrow buttons repeat scrolling when held down.
213 * 64 1/20/98 4:39p Hoffoss
214 * Added mission time display to scrollback log screen.
216 * 63 1/18/98 5:09p Lawrance
217 * Added support for TEAM_TRAITOR
219 * 62 1/12/98 11:16p Lawrance
220 * Wonderful HUD config.
222 * 61 1/08/98 1:33p Hoffoss
223 * Made scroll offset reset to bottom of list instead of top.
225 * 60 1/05/98 2:59p Hoffoss
226 * Fixed bug with messages drawing outside of limits.
228 * 59 1/02/98 9:10p Lawrance
229 * Big changes to how colors get set on the HUD.
231 * 58 1/02/98 10:23a Hoffoss
232 * Fixed incorrect scrolling directions in message scrollback log.
234 * 57 12/11/97 10:17p Dave
235 * Put in some checks to make sure HUD_printfs aren't
236 * done in certain multiplayer situations.
238 * 56 12/05/97 2:16p Hoffoss
239 * Made hidden hud messages actually not show up in scrollback.
241 * 55 12/03/97 6:07p Dave
242 * Added assert that hud scrollback initialized before adding messages to
245 * 54 12/03/97 4:16p Hoffoss
246 * Changed sound stuff used in interface screens for interface purposes.
248 * 53 12/03/97 11:35a Hoffoss
249 * Made changes to HUD messages send throughout the game.
251 * 52 12/02/97 5:57p Hoffoss
252 * Changed Hud messaging code to align text to right after sending ship's
255 * 51 12/01/97 4:30p Hoffoss
256 * Changed code to list hud messages in scrollback from top down.
258 * 50 11/25/97 10:01a Jasen
259 * Remoced excess buttons from MessageLog screen.
261 * 49 11/24/97 10:03p Jasen
262 * Dang... had to make an entirely new revision of the last button. :)
264 * 48 11/24/97 9:44p Jasen
265 * Changed button name and coords to new exit button.
267 * 47 11/20/97 12:02p Lawrance
268 * change Error to nprintf at warning level
270 * 46 11/17/97 6:37p Lawrance
271 * new gauges: extended target view, new lock triangles, support ship view
273 * 45 11/14/97 2:46p Lawrance
274 * decrease width of HUD message line to 435, so it doesn overlap with
277 * 44 11/13/97 10:16p Hoffoss
278 * Added icons to mission log scrollback.
280 * 43 11/13/97 4:05p Hoffoss
281 * Added hiding code for mission log entries.
283 * 42 11/12/97 6:00p Hoffoss
284 * Added training messages to hud scrollback log.
286 * 41 11/11/97 11:16a Hoffoss
287 * Changed hud scrollback to color entire lines.
289 * 40 11/06/97 5:42p Hoffoss
290 * Added support for fixed size timstamp rendering.
292 * 39 11/05/97 7:11p Hoffoss
293 * Made changed to the hud message system. Hud messages can now have
294 * sources so they can be color coded.
296 * 38 11/04/97 4:56p Jasen
297 * Updated coordinates for buttons
299 * 37 11/03/97 10:12p Hoffoss
300 * Finished up work on the hud message/mission log scrollback screen.
302 * 36 11/03/97 5:38p Dave
303 * Cleaned up more multiplayer sequencing. Added OBJ_OBSERVER module/type.
304 * Restructured HUD_config structs/flags.
306 * 35 10/25/97 4:02p Lawrance
307 * took out unused hud_message struct members
309 * 34 10/02/97 9:53p Hoffoss
310 * Added event evaluation analysis debug screen so we can determine the
311 * state of events and their sexp trees to track down logic problems and
314 * 33 9/17/97 5:12p John
315 * Restructured collision routines. Probably broke a lot of stuff.
317 * 32 9/08/97 12:01p Lawrance
318 * when re-using HUD scrollback entries, ensure memory gets free'ed
321 * 31 8/31/97 6:38p Lawrance
322 * pass in frametime to do_frame loop
324 * 30 8/22/97 10:03a Lawrance
325 * fix exception that occurred when hud scrollback was selected from the
328 * 29 6/23/97 12:03p Lawrance
329 * move split_str() to Parselo
331 * 28 6/17/97 12:25p Lawrance
332 * HUD message lines are split into multiple lines when they exceed
335 * 27 6/12/97 10:23a John
336 * added new colors to freespace. made most menus display the background
337 * bitmap rather than dull black screen.
339 * 26 6/11/97 1:12p John
340 * Started fixing all the text colors in the game.
342 * 25 4/22/97 3:14p Lawrance
343 * only free HUD scrollback messages if they exist
345 * 24 4/15/97 1:26p Lawrance
346 * using a static array of nodes to store hud scrollback messages, storage
347 * for text is dynamic
349 * 23 4/14/97 9:55a Mike
350 * Fixed HUD message system.
351 * Better game sequencing.
353 * 22 1/28/97 5:33p Lawrance
354 * saving number of msg window lines in save game and player file
356 * 21 1/28/97 4:59p Lawrance
357 * allowing number of lines on hud message bar to be configured
359 * 20 1/24/97 9:47a Lawrance
360 * made number of message lines in HUD message area confiurable
362 * 19 1/22/97 10:56a Lawrance
363 * added check for NULL after malloc()
365 * 18 1/07/97 5:36p Lawrance
366 * Enabled save/restore for old/present/pending hud messages
368 * 17 12/10/96 12:28p Lawrance
369 * adding new offscreen target indicator
371 * 16 12/08/96 1:54a Lawrance
372 * integrating hud configuration
374 * 15 11/29/96 6:12p Lawrance
375 * took out duplicate include of timer.h
377 * 14 11/29/96 11:17a Lawrance
378 * added comments, put check in for zero-length HUD messages in the
381 * 13 11/28/96 6:27p Lawrance
382 * added some additional comments
384 * 12 11/27/96 3:20p Lawrance
385 * added scroll-back message code
387 * 11 11/22/96 1:00p Lawrance
388 * fixed bug when a key held down and created tons of messages
390 * 10 11/22/96 12:35p Lawrance
392 * 9 11/20/96 11:51a Lawrance
393 * trying out losing the HUD message shaded area
395 * 8 11/19/96 4:46p Lawrance
396 * fixed problem when too many messages were to be displayed at once
398 * 7 11/19/96 3:55p Lawrance
399 * modifed HUD message details (scroll speed, fade time etc)
401 * 6 11/19/96 10:16a Lawrance
402 * changing to new use of color scheme
404 * 5 11/17/96 5:28p Lawrance
405 * using HUD color globals instead of hard-coded numbers
407 * 4 11/15/96 11:46a Lawrance
408 * tweaked size of HUD message bar to prevent clipping of g's etc on the
411 * 3 11/15/96 11:39a Lawrance
412 * got HUD messages scrolling
414 * 2 11/15/96 12:11a Lawrance
415 * HUD message bar working
425 #include "hudmessage.h"
426 #include "hudtarget.h"
427 #include "freespace.h"
428 #include "gamesequence.h"
435 #include "linklist.h"
436 #include "missionlog.h"
438 #include "missionscreencommon.h"
443 #include "missiongoals.h"
444 #include "alphacolors.h"
446 #include "audiostr.h"
448 /* replaced with those static ints that follow
450 #define LIST_X2 108 // second column x start position
452 #define LIST_W 558 // total width including both columns
453 #define LIST_W2 (LIST_W + LIST_X - LIST_X2) // width of second column
455 #define LIST_H_O 275 // applies only to objectives mode
458 // 1st column, width includes both columns
459 static int Hud_mission_log_list_coords[GR_NUM_RESOLUTIONS][4] = {
461 46,60,558,269 // GR_640
464 74,96,558,297 // GR_1024
468 // 2nd column, width is just of second column
469 static int Hud_mission_log_list2_coords[GR_NUM_RESOLUTIONS][4] = {
471 108, 60, 496, 297 // GR_640
474 136, 96, 496, 436 // GR_1024
478 static int Hud_mission_log_list_objective_x_coord[GR_NUM_RESOLUTIONS] = {
483 static int Hud_mission_log_time_coords[GR_NUM_RESOLUTIONS][2] = {
492 static int Hud_mission_log_time2_coords[GR_NUM_RESOLUTIONS][2] = {
502 #define SCROLLBACK_MODE_MSGS_LOG 0
503 #define SCROLLBACK_MODE_EVENT_LOG 1
504 #define SCROLLBACK_MODE_OBJECTIVES 2
506 #define NUM_BUTTONS 6
508 #define SCROLL_UP_BUTTON 0
509 #define SCROLL_DOWN_BUTTON 1
510 #define SHOW_MSGS_BUTTON 2
511 #define SHOW_EVENTS_BUTTON 3
512 #define SHOW_OBJS_BUTTON 4
513 #define ACCEPT_BUTTON 5
515 #define HUD_MESSAGE_TOTAL_LIFE 14000 // total time a HUD message is alive (in milliseconds)
517 #define HUD_MSG_LENGTH_MAX 2048
518 //#define HUD_MSG_MAX_PIXEL_W 439 // maximum number of pixels wide message display area is
519 //#define HUD_MSG_MAX_PIXEL_W 619 // maximum number of pixels wide message display area is
522 // No Longer Used - DDOI
523 static int Hud_mission_log_status_coords[GR_NUM_RESOLUTIONS][2] = {
533 struct scrollback_buttons {
534 const char *filename;
538 UI_BUTTON button; // because we have a class inside this struct, we need the constructor below..
540 scrollback_buttons(const char *name, int x1, int y1, int x2, int y2, int h) : filename(name), x(x1), y(y1), xt(x2), yt(y2), hotspot(h) {}
545 int MSG_WINDOW_X_START = 5;
546 int MSG_WINDOW_Y_START = 5;
547 int MSG_WINDOW_WIDTH; // initialed in hud_init_msg_window()
548 int MSG_WINDOW_HEIGHT;
549 int MSG_WINDOW_FONT_HEIGHT;
550 int ACTIVE_BUFFER_LINES = 4; // number of HUD messages that can be shown at one time + 1
551 int OLD_ACTIVE_BUFFER_LINES;
553 int Hud_list_start; // points to the next msg to be printed in the queue
554 int Hud_list_end; // points to the last msg in the queue
558 int Scroll_in_progress=0;
560 HUD_message_data HUD_pending[SCROLL_BUFFER_LINES];
561 Hud_display_info HUD_active_msgs_list[MAX_ACTIVE_BUFFER_LINES];
563 int HUD_msg_inited = FALSE;
565 // There is a maximum number of lines that will be stored in the message scrollback. Oldest
566 // messages are deleted to make way for newest messages.
567 #define MAX_MSG_SCROLLBACK_LINES 100
568 line_node Msg_scrollback_lines[MAX_MSG_SCROLLBACK_LINES];
570 line_node Msg_scrollback_free_list;
571 line_node Msg_scrollback_used_list;
575 typedef struct HUD_ft {
576 int end_time; // Timestamp at which this message will go away.
577 char text[MAX_HUD_LINE_LEN]; // Text to display.
578 int color; // 0rgb color, 8 bit fields.
581 HUD_ft HUD_fixed_text[MAX_HUD_FT];
583 static int Num_obj_lines;
584 static int Scroll_offset;
585 static int Scroll_max;
586 static int Scrollback_mode = SCROLLBACK_MODE_OBJECTIVES;
588 static int Status_bitmap;
590 static int Background_bitmap;
591 static UI_WINDOW Ui_window;
593 static const char* Hud_mission_log_fname[GR_NUM_RESOLUTIONS] = {
594 "MissionLog", // GR_640
595 "2_MissionLog" // GR_1024
599 // No longer used - DDOI
600 static const char* Hud_mission_log_status_fname[GR_NUM_RESOLUTIONS] = {
601 "MLStatus", // GR_640
602 "MLStatus" // GR_1024
606 static const char* Hud_mission_log_mask_fname[GR_NUM_RESOLUTIONS] = {
607 "MissionLog-m", // GR_640
608 "2_MissionLog-m" // GR_1024
611 static scrollback_buttons Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
615 scrollback_buttons("LB_00", 7, 89, -1, -1, 0), // scroll up
616 scrollback_buttons("LB_01", 7, 133, -1, -1, 1), // scroll down
617 scrollback_buttons("LB_02", 294, 362, -1, -1, 2), // messages
618 scrollback_buttons("LB_03", 402, 362, -1, -1, 3), // events
619 scrollback_buttons("LB_04", 193, 362, -1, -1, 4), // objectives
620 scrollback_buttons("LB_05", 554, 411, -1, -1, 5) // continue
622 scrollback_buttons("LB_00", 1, 67, -1, -1, 0),
623 scrollback_buttons("LB_01", 1, 307, -1, -1, 1),
624 scrollback_buttons("LB_02", 111, 376, 108, 413, 2),
625 scrollback_buttons("LB_03", 209, 376, 205, 413, 3),
626 scrollback_buttons("LB_04", 12, 376, 7, 413, 4),
627 scrollback_buttons("CB_05a", 571, 425, 564, 413, 5)
633 scrollback_buttons("2_LB_00", 1, 108, -1, -1, 0),
634 scrollback_buttons("2_LB_01", 1, 492, -1, -1, 1),
635 scrollback_buttons("2_LB_02", 177, 602, 173, 661, 2),
636 scrollback_buttons("2_LB_03", 335, 602, 335, 661, 3),
637 scrollback_buttons("2_LB_04", 20, 602, 11, 661, 4),
638 scrollback_buttons("2_CB_05a",914, 681, 946, 661, 5)
644 // ----------------------------------------------------------------------
645 // HUD_init_fixed_text()
647 void HUD_init_fixed_text()
651 for (i=0; i<MAX_HUD_FT; i++)
652 HUD_fixed_text[i].end_time = timestamp(0);
655 // ----------------------------------------------------------------------
656 // hud_init_msg_window()
658 // Called from HUD_init(), which is called from game_level_init()
660 void hud_init_msg_window()
664 MSG_WINDOW_WIDTH = gr_screen.clip_width - 20;
669 for (i=0; i<SCROLL_BUFFER_LINES; i++)
670 HUD_pending[i].text[0] = HUD_pending[i].text[MAX_HUD_LINE_LEN - 1] = 0;
672 for ( i=0; i < MAX_ACTIVE_BUFFER_LINES; i++ ) {
673 HUD_active_msgs_list[i].total_life = 1;
678 // determine the height of the msg window, which depends on the font height
680 h = gr_get_font_height();
682 //ACTIVE_BUFFER_LINES = Players[Player_num].HUD_config.num_msg_window_lines;
683 // ACTIVE_BUFFER_LINES = HUD_config.num_msg_window_lines;
684 ACTIVE_BUFFER_LINES = 4;
686 MSG_WINDOW_FONT_HEIGHT = h;
687 MSG_WINDOW_HEIGHT = MSG_WINDOW_FONT_HEIGHT * (ACTIVE_BUFFER_LINES-1);
689 // starting a mission, free the scroll-back buffers, but only if we've been
690 // through this function once already
691 if ( HUD_msg_inited == TRUE ) {
692 hud_free_scrollback_list();
695 list_init( &Msg_scrollback_free_list );
696 list_init( &Msg_scrollback_used_list );
698 // first slot is reserved for dummy node
699 for (i=1; i < MAX_MSG_SCROLLBACK_LINES; i++) {
700 Msg_scrollback_lines[i].text = NULL;
701 list_append(&Msg_scrollback_free_list, &Msg_scrollback_lines[i]);
706 Scroll_in_progress=0;
708 OLD_ACTIVE_BUFFER_LINES = ACTIVE_BUFFER_LINES;
710 HUD_init_fixed_text();
711 HUD_msg_inited = TRUE;
714 // ---------------------------------------------------------------------------------------
715 // hud_show_msg_window() will display the active HUD messages on the HUD. It will scroll
716 // the messages up when a new message arrives.
718 void hud_show_msg_window()
722 hud_set_default_color();
725 HUD_set_clip(MSG_WINDOW_X_START,MSG_WINDOW_Y_START, MSG_WINDOW_WIDTH, MSG_WINDOW_HEIGHT+2);
727 if ( OLD_ACTIVE_BUFFER_LINES != ACTIVE_BUFFER_LINES ) {
728 // the size of the message window has changed, the best thing to do is to put all
729 // the blank out the current hud messages. There is no need to add them to the
730 // scrollback buffer, since they are already there!
732 for ( i=0; i < ACTIVE_BUFFER_LINES; i++ ) {
733 if ( !timestamp_elapsed(HUD_active_msgs_list[i].total_life) ) {
734 HUD_active_msgs_list[i].total_life = 1;
740 OLD_ACTIVE_BUFFER_LINES = ACTIVE_BUFFER_LINES;
742 // check if there is a message to display on the HUD, and if there is room to display it
743 if ( Hud_list_start != Hud_list_end && !Scroll_needed) {
747 // if the pointer exceeds the array size, wrap around to element 1. element 0 is not used.
748 if (Hud_list_start >= SCROLL_BUFFER_LINES)
751 HUD_active_msgs_list[Active_index].msg = HUD_pending[Hud_list_start];
752 HUD_active_msgs_list[Active_index].total_life = timestamp(HUD_MESSAGE_TOTAL_LIFE);
754 for (i=Active_index+1; i < Active_index+ACTIVE_BUFFER_LINES; i++) {
755 index = i % ACTIVE_BUFFER_LINES;
757 // determine if there are any existing messages, if so need to scroll them up
759 if ( !timestamp_elapsed(HUD_active_msgs_list[index].total_life) ) {
760 HUD_active_msgs_list[index].target_y -= MSG_WINDOW_FONT_HEIGHT;
767 HUD_active_msgs_list[Active_index].y = (ACTIVE_BUFFER_LINES-1)*MSG_WINDOW_FONT_HEIGHT;
768 HUD_active_msgs_list[Active_index].target_y = HUD_active_msgs_list[Active_index].y - MSG_WINDOW_FONT_HEIGHT;
771 HUD_active_msgs_list[Active_index].y = (ACTIVE_BUFFER_LINES-2)*MSG_WINDOW_FONT_HEIGHT;
772 HUD_active_msgs_list[Active_index].target_y = HUD_active_msgs_list[Active_index].y;
776 if (Active_index >= ACTIVE_BUFFER_LINES) Active_index = 0;
778 if (Hud_list_end == Hud_list_start) { // just printed the last msg
779 Hud_list_start = Hud_list_end = 0;
783 Scroll_in_progress=0;
786 for ( i=0; i < ACTIVE_BUFFER_LINES; i++ ) {
788 if ( !timestamp_elapsed(HUD_active_msgs_list[i].total_life) ) {
790 if (HUD_active_msgs_list[i].y > HUD_active_msgs_list[i].target_y) {
792 if (timestamp_elapsed(Scroll_time_id) ){
793 HUD_active_msgs_list[i].y -= SCROLL_STEP_SIZE;
794 if (HUD_active_msgs_list[i].y < HUD_active_msgs_list[i].target_y)
795 HUD_active_msgs_list[i].y = HUD_active_msgs_list[i].target_y;
797 Scroll_in_progress=1;
802 if ( hud_gauge_active(HUD_MESSAGE_LINES) ) {
803 if ( !(Player->flags & PLAYER_FLAGS_MSG_MODE) ) {
804 // set the appropriate color
805 if(HUD_active_msgs_list[i].msg.source){
806 hud_set_gauge_color(HUD_MESSAGE_LINES, HUD_C_BRIGHT);
808 hud_set_gauge_color(HUD_MESSAGE_LINES);
811 // print the message out
812 gr_printf(MSG_WINDOW_X_START + HUD_active_msgs_list[i].msg.x - 2, HUD_active_msgs_list[i].y, "%s", HUD_active_msgs_list[i].msg.text);
819 if (Scroll_in_progress)
820 Scroll_time_id = timestamp(SCROLL_TIME);
825 void hud_show_fixed_text()
829 hp = &HUD_fixed_text[0];
831 if (!timestamp_elapsed(hp->end_time)) {
832 //gr_set_color((hp->color >> 16) & 0xff, (hp->color >> 8) & 0xff, hp->color & 0xff);
833 gr_printf(0x8000, MSG_WINDOW_Y_START + MSG_WINDOW_HEIGHT + 8, hp->text);
837 // Similar to HUD printf, but shows only one message at a time, at a fixed location.
838 void HUD_fixed_printf(float duration, const char * format, ...)
841 char tmp[HUD_MSG_LENGTH_MAX];
844 // make sure we only print these messages if we're in the correct state
845 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state != NETGAME_STATE_IN_MISSION)){
846 nprintf(("Network","HUD_fixed_printf bailing because not in multiplayer game play state\n"));
850 va_start(args, format);
851 vsprintf(tmp, format, args);
854 msg_length = strlen(tmp);
855 SDL_assert(msg_length < HUD_MSG_LENGTH_MAX); // If greater than this, probably crashed anyway.
858 nprintf(("Warning", "HUD_fixed_printf ==> attempt to print a 0 length string in msg window\n"));
861 } else if (msg_length > MAX_HUD_LINE_LEN - 1){
862 nprintf(("Warning", "HUD_fixed_printf ==> Following string truncated to %d chars: %s\n",MAX_HUD_LINE_LEN,tmp));
865 if (duration == 0.0f){
866 HUD_fixed_text[0].end_time = timestamp(-1);
868 HUD_fixed_text[0].end_time = timestamp((int) (1000.0f * duration));
871 strncpy(HUD_fixed_text[0].text, tmp, MAX_HUD_LINE_LEN - 1);
872 HUD_fixed_text[0].color = 0xff0000;
875 // Clear all pending text.
876 void HUD_fixed_printf_reset()
878 HUD_init_fixed_text();
882 // --------------------------------------------------------------------------------------
885 // Print a single line of text to the HUD. We know that the text will fit on the screen,
886 // since that was taken care of in HUD_printf();
888 void HUD_printf_line(const char *text, int source, int time = 0, int x = 0)
890 SDL_assert(text != NULL);
892 // if the pointer exceeds the array size, wrap around to element 1. element 0 is not used.
894 if (Hud_list_end >= SCROLL_BUFFER_LINES)
897 if (Hud_list_end == Hud_list_start) {
898 nprintf(("Warning", "HUD ==> Exceeded msg scroll buffer, discarding message %s\n", text));
900 if (Hud_list_end == 0)
901 Hud_list_end = SCROLL_BUFFER_LINES - 1;
905 if ( strlen(text) > MAX_HUD_LINE_LEN - 1 ){
906 nprintf(("Warning", "HUD_printf_line() ==> Following string truncated to %d chars: %s\n", MAX_HUD_LINE_LEN, text));
909 strncpy(HUD_pending[Hud_list_end].text, text, MAX_HUD_LINE_LEN - 1);
910 HUD_pending[Hud_list_end].text[MAX_HUD_LINE_LEN - 1] = 0;
911 HUD_pending[Hud_list_end].source = source;
912 HUD_pending[Hud_list_end].time = time;
913 HUD_pending[Hud_list_end].x = x;
916 // converts a TEAM_* define to a HUD_SOURCE_* define
917 int HUD_get_team_source(int team)
921 return HUD_SOURCE_FRIENDLY;
924 return HUD_SOURCE_HOSTILE;
927 return HUD_SOURCE_NEUTRAL;
930 return HUD_SOURCE_UNKNOWN;
933 return HUD_SOURCE_TRAITOR;
936 nprintf(("warning", "Unknown TEAM_* define used! (%d)", team));
940 void HUD_printf(const char *format, ...)
943 char tmp[HUD_MSG_LENGTH_MAX];
946 // make sure we only print these messages if we're in the correct state
947 if((Game_mode & GM_MULTIPLAYER) && (Net_player->state != NETPLAYER_STATE_IN_MISSION)){
948 nprintf(("Network","HUD_printf bailing because not in multiplayer game play state\n"));
952 va_start(args, format);
953 vsprintf(tmp, format, args);
957 SDL_assert(len < HUD_MSG_LENGTH_MAX); // If greater than this, probably crashed anyway.
958 hud_sourced_print(HUD_SOURCE_COMPUTER, tmp);
961 void HUD_ship_sent_printf(int sh, const char *format, ...)
964 char tmp[HUD_MSG_LENGTH_MAX];
967 sprintf(tmp, NOX("%s: "), Ships[sh].ship_name);
969 SDL_assert(len < HUD_MSG_LENGTH_MAX);
971 va_start(args, format);
972 vsprintf(tmp + len, format, args);
976 SDL_assert(len < HUD_MSG_LENGTH_MAX); // If greater than this, probably crashed anyway.
977 hud_sourced_print(HUD_get_team_source(Ships[sh].team), tmp);
980 // --------------------------------------------------------------------------------------
981 // HUD_sourced_printf()
983 // HUD_sourced_printf() has the same parameters as printf(), but displays the text as a scrolling
984 // message on the HUD. Text is split into multiple lines if width exceeds msg display area
985 // width. 'source' is used to indicate who send the message, and is used to color code text.
987 void HUD_sourced_printf(int source, const char *format, ...)
990 char tmp[HUD_MSG_LENGTH_MAX];
992 // make sure we only print these messages if we're in the correct state
993 if((Game_mode & GM_MULTIPLAYER) && (Net_player->state != NETPLAYER_STATE_IN_MISSION)){
994 nprintf(("Network","HUD_sourced_printf bailing because not in multiplayer game play state\n"));
998 va_start(args, format);
999 vsprintf(tmp, format, args);
1001 SDL_assert(strlen(tmp) < HUD_MSG_LENGTH_MAX); // If greater than this, probably crashed anyway.
1002 hud_sourced_print(source, tmp);
1005 void hud_sourced_print(int source, char *msg)
1008 //char *src_str, *msg_str;
1009 int sw, t, x, offset = 0;
1010 //int fudge = (gr_screen.res == GR_640) ? 15 : 50; // prevents string from running off screen
1012 if ( !strlen(msg) ) {
1013 nprintf(("Warning", "HUD ==> attempt to print a 0 length string in msg window\n"));
1017 // add message to the scrollback log first
1018 hud_add_msg_to_scrollback(msg, source, timestamp());
1020 ptr = strstr(msg, NOX(": ")) + 2;
1022 gr_get_string_size(&sw, NULL, msg, ptr - msg); // get width of the speaker field
1023 //if (sw < MSG_WINDOW_WIDTH - 20)
1030 while ((ptr = split_str_once(str, MSG_WINDOW_WIDTH - x - 7)) != NULL) { // the 7 is a fudge hack
1031 HUD_printf_line(str, source, t, x);
1037 HUD_printf_line(str, source, t, x);
1040 int hud_query_scrollback_size()
1042 int count = 0, y_add = 0;
1043 int font_height = gr_get_font_height();
1046 if (EMPTY(&Msg_scrollback_used_list) || !HUD_msg_inited)
1049 ptr = GET_FIRST(&Msg_scrollback_used_list);
1050 while (ptr != END_OF_LIST(&Msg_scrollback_used_list)) {
1051 if (ptr->source != HUD_SOURCE_HIDDEN) {
1053 count += font_height + ptr->y;
1056 ptr = GET_NEXT(ptr);
1063 // add text directly to the hud scrollback log, without displaying on the hud
1064 void HUD_add_to_scrollback(const char *text, int source)
1066 if (!strlen(text)) {
1067 nprintf(("Warning", "HUD ==> attempt to print a 0 length string in msg window\n"));
1071 hud_add_msg_to_scrollback(text, source, timestamp());
1074 // hud_add_msg_to_scrollback() adds the new_msg to the scroll-back message list. If there
1075 // are no more free slots, the first slot is released to make room for the new message.
1077 void hud_add_line_to_scrollback(const char *text, int source, int t, int x, int y, int underline_width)
1079 line_node *new_line;
1081 SDL_assert(HUD_msg_inited);
1082 if (!text || !strlen(text))
1085 if ( EMPTY(&Msg_scrollback_free_list) ) {
1086 new_line = GET_FIRST(&Msg_scrollback_used_list);
1087 list_remove(&Msg_scrollback_used_list, new_line);
1088 free(new_line->text);
1091 new_line = GET_FIRST(&Msg_scrollback_free_list);
1092 list_remove(&Msg_scrollback_free_list, new_line);
1097 new_line->underline_width = underline_width;
1099 new_line->source = source;
1100 new_line->text = (char *) malloc( strlen(text) + 1 );
1101 strcpy(new_line->text, text);
1102 list_append(&Msg_scrollback_used_list, new_line);
1105 void hud_add_msg_to_scrollback(const char *text, int source, int t)
1107 char buf[HUD_MSG_LENGTH_MAX], *ptr, *str;
1108 int msg_len, w, max_width, x, offset = 0;
1110 max_width = Hud_mission_log_list2_coords[gr_screen.res][2];
1111 msg_len = strlen(text);
1116 SDL_assert(msg_len < HUD_MSG_LENGTH_MAX);
1118 ptr = strstr(buf, NOX(": "));
1120 gr_get_string_size(&w, NULL, buf, ptr - buf);
1124 // gr_get_string_size(&w, NULL, buf, ptr - buf + 2);
1125 // if (w < max_width - 20)
1131 while ((ptr = split_str_once(str, max_width - x)) != NULL) {
1132 hud_add_line_to_scrollback(str, source, t, x, 1, w);
1138 hud_add_line_to_scrollback(str, source, t, x, 3, w);
1141 // hud_free_scrollback_list() will free the memory that was allocated to store the messages
1142 // for the scroll-back list
1144 void hud_free_scrollback_list()
1148 // check if the list has been inited yet. If not, return with doing nothing.
1149 if ( Msg_scrollback_used_list.next == NULL || Msg_scrollback_used_list.prev == NULL )
1152 A = GET_FIRST(&Msg_scrollback_used_list);
1153 while( A !=END_OF_LIST(&Msg_scrollback_used_list) ) {
1154 if ( A->text != NULL ) {
1163 // how many lines to skip
1164 int hud_get_scroll_max_pos()
1166 int max = 0, font_height = gr_get_font_height();
1168 if (Scrollback_mode == SCROLLBACK_MODE_MSGS_LOG) {
1171 // number of pixels in excess of what can be displayed
1172 int excess = Scroll_max - Hud_mission_log_list_coords[gr_screen.res][3];
1174 if (EMPTY(&Msg_scrollback_used_list) || !HUD_msg_inited) {
1178 ptr = GET_FIRST(&Msg_scrollback_used_list);
1179 while (ptr != END_OF_LIST(&Msg_scrollback_used_list)) {
1180 if (ptr->source != HUD_SOURCE_HIDDEN) {
1183 excess -= font_height;
1192 // spacing between lines
1197 ptr = GET_NEXT(ptr);
1202 max = (Scroll_max - Hud_mission_log_list_coords[gr_screen.res][3]) / font_height;
1211 void hud_scroll_reset()
1213 if (Scrollback_mode == SCROLLBACK_MODE_OBJECTIVES) {
1217 Scroll_offset = hud_get_scroll_max_pos();
1221 void hud_scroll_list(int dir)
1224 if (Scroll_offset) {
1226 gamesnd_play_iface(SND_SCROLL);
1229 gamesnd_play_iface(SND_GENERAL_FAIL);
1232 if (Scroll_offset < hud_get_scroll_max_pos()) {
1234 gamesnd_play_iface(SND_SCROLL);
1237 gamesnd_play_iface(SND_GENERAL_FAIL);
1241 void hud_goto_pos(int delta)
1243 int pos=0, font_height = gr_get_font_height();
1245 if (Scrollback_mode == SCROLLBACK_MODE_MSGS_LOG) {
1246 int count = 0, y = 0;
1249 if (EMPTY(&Msg_scrollback_used_list) || !HUD_msg_inited)
1252 ptr = GET_FIRST(&Msg_scrollback_used_list);
1253 while (ptr != END_OF_LIST(&Msg_scrollback_used_list)) {
1254 if (ptr->source != HUD_SOURCE_HIDDEN) {
1255 if (count == Scroll_offset) {
1260 y += font_height + ptr->y;
1264 ptr = GET_NEXT(ptr);
1267 Scroll_offset = count = y = 0;
1268 ptr = GET_FIRST(&Msg_scrollback_used_list);
1269 while (ptr != END_OF_LIST(&Msg_scrollback_used_list)) {
1270 if (ptr->source != HUD_SOURCE_HIDDEN) {
1271 if (y <= pos + delta)
1272 Scroll_offset = count;
1274 y += font_height + ptr->y;
1278 ptr = GET_NEXT(ptr);
1282 pos = Scroll_offset * font_height;
1284 Scroll_offset = pos / font_height;
1288 void hud_page_scroll_list(int dir)
1290 int max = hud_get_scroll_max_pos();
1293 if (Scroll_offset) {
1294 hud_goto_pos(-Hud_mission_log_list_coords[gr_screen.res][3]);
1295 if (Scroll_offset < 0)
1298 gamesnd_play_iface(SND_SCROLL);
1301 gamesnd_play_iface(SND_GENERAL_FAIL);
1304 if (Scroll_offset < max) {
1305 hud_goto_pos(Hud_mission_log_list_coords[gr_screen.res][3]);
1306 if (Scroll_offset > max)
1307 Scroll_offset = max;
1309 gamesnd_play_iface(SND_SCROLL);
1312 gamesnd_play_iface(SND_GENERAL_FAIL);
1316 void hud_scrollback_button_pressed(int n)
1319 case SCROLL_UP_BUTTON:
1323 case SCROLL_DOWN_BUTTON:
1327 case SHOW_MSGS_BUTTON:
1328 Scrollback_mode = SCROLLBACK_MODE_MSGS_LOG;
1329 Scroll_max = hud_query_scrollback_size();
1333 case SHOW_EVENTS_BUTTON:
1334 Scrollback_mode = SCROLLBACK_MODE_EVENT_LOG;
1335 Scroll_max = Num_log_lines * gr_get_font_height();
1339 case SHOW_OBJS_BUTTON:
1340 Scrollback_mode = SCROLLBACK_MODE_OBJECTIVES;
1341 Scroll_max = Num_obj_lines * gr_get_font_height();
1346 hud_scrollback_exit();
1351 void hud_scrollback_init()
1354 scrollback_buttons *b;
1356 // pause all game sounds
1357 beam_pause_sounds();
1358 audiostream_pause_all();
1360 common_set_interface_palette("BriefingPalette"); // set the interface palette
1361 Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1362 Ui_window.set_mask_bmap(Hud_mission_log_mask_fname[gr_screen.res]);
1364 for (i=0; i<NUM_BUTTONS; i++) {
1365 b = &Buttons[gr_screen.res][i];
1367 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, (i < 2), 1);
1368 // set up callback for when a mouse first goes over a button
1369 b->button.set_highlight_action(common_play_highlight_sound);
1370 b->button.set_bmaps(b->filename);
1371 b->button.link_hotspot(b->hotspot);
1376 Ui_window.add_XSTR("Continue", 1069, Buttons[gr_screen.res][ACCEPT_BUTTON].xt, Buttons[gr_screen.res][ACCEPT_BUTTON].yt, &Buttons[gr_screen.res][ACCEPT_BUTTON].button, UI_XSTR_COLOR_PINK);
1377 Ui_window.add_XSTR("Events", 1070, Buttons[gr_screen.res][SHOW_EVENTS_BUTTON].xt, Buttons[gr_screen.res][SHOW_EVENTS_BUTTON].yt, &Buttons[gr_screen.res][SHOW_EVENTS_BUTTON].button, UI_XSTR_COLOR_GREEN);
1378 Ui_window.add_XSTR("Objectives", 1071, Buttons[gr_screen.res][SHOW_OBJS_BUTTON].xt, Buttons[gr_screen.res][SHOW_OBJS_BUTTON].yt, &Buttons[gr_screen.res][SHOW_OBJS_BUTTON].button, UI_XSTR_COLOR_GREEN);
1379 Ui_window.add_XSTR("Messages", 1072, Buttons[gr_screen.res][SHOW_MSGS_BUTTON].xt, Buttons[gr_screen.res][SHOW_MSGS_BUTTON].yt, &Buttons[gr_screen.res][SHOW_MSGS_BUTTON].button, UI_XSTR_COLOR_GREEN);
1382 // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1383 Buttons[gr_screen.res][SCROLL_UP_BUTTON].button.set_hotkey(SDLK_UP);
1384 Buttons[gr_screen.res][SCROLL_DOWN_BUTTON].button.set_hotkey(SDLK_DOWN);
1386 Background_bitmap = bm_load(Hud_mission_log_fname[gr_screen.res]);
1388 Status_bitmap = bm_load(Hud_mission_log_status_fname[gr_screen.res]);
1391 message_log_init_scrollback(Hud_mission_log_list_coords[gr_screen.res][2]);
1392 if (Scrollback_mode == SCROLLBACK_MODE_EVENT_LOG)
1393 Scroll_max = Num_log_lines * gr_get_font_height();
1394 else if (Scrollback_mode == SCROLLBACK_MODE_OBJECTIVES)
1395 Scroll_max = Num_obj_lines * gr_get_font_height();
1397 Scroll_max = hud_query_scrollback_size();
1399 Num_obj_lines = ML_objectives_init(Hud_mission_log_list_coords[gr_screen.res][0], Hud_mission_log_list_coords[gr_screen.res][1], Hud_mission_log_list_coords[gr_screen.res][2], Hud_mission_log_list_objective_x_coord[gr_screen.res]);
1403 void hud_scrollback_close()
1405 ML_objectives_close();
1406 message_log_shutdown_scrollback();
1407 if (Background_bitmap >= 0)
1408 bm_unload(Background_bitmap);
1410 if (Status_bitmap >= 0)
1411 bm_unload(Status_bitmap);
1414 Ui_window.destroy();
1415 common_free_interface_palette(); // restore game palette
1418 // unpause all game sounds
1419 beam_unpause_sounds();
1420 audiostream_unpause_all();
1424 void hud_scrollback_do_frame(float frametime)
1427 int font_height = gr_get_font_height();
1429 k = Ui_window.process();
1433 if (Scrollback_mode == SCROLLBACK_MODE_OBJECTIVES) {
1434 Scrollback_mode = SCROLLBACK_MODE_MSGS_LOG;
1435 Scroll_max = hud_query_scrollback_size();
1438 } else if (Scrollback_mode == SCROLLBACK_MODE_MSGS_LOG) {
1439 Scrollback_mode = SCROLLBACK_MODE_EVENT_LOG;
1440 Scroll_max = Num_log_lines * gr_get_font_height();
1444 Scrollback_mode = SCROLLBACK_MODE_OBJECTIVES;
1445 Scroll_max = Num_obj_lines * gr_get_font_height();
1452 case KEY_SHIFTED | SDLK_TAB:
1453 if (Scrollback_mode == SCROLLBACK_MODE_OBJECTIVES) {
1454 Scrollback_mode = SCROLLBACK_MODE_EVENT_LOG;
1455 Scroll_max = Num_log_lines * gr_get_font_height();
1458 } else if (Scrollback_mode == SCROLLBACK_MODE_MSGS_LOG) {
1459 Scrollback_mode = SCROLLBACK_MODE_OBJECTIVES;
1460 Scroll_max = Num_obj_lines * gr_get_font_height();
1464 Scrollback_mode = SCROLLBACK_MODE_MSGS_LOG;
1465 Scroll_max = hud_query_scrollback_size();
1472 hud_page_scroll_list(1);
1476 hud_page_scroll_list(0);
1480 case KEY_CTRLED | SDLK_RETURN:
1482 hud_scrollback_exit();
1485 case SDLK_F1: // show help overlay
1488 case SDLK_F2: // goto options screen
1489 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1493 for (i=0; i<NUM_BUTTONS; i++){
1494 if (Buttons[gr_screen.res][i].button.pressed()){
1495 hud_scrollback_button_pressed(i);
1499 GR_MAYBE_CLEAR_RES(Background_bitmap);
1500 if (Background_bitmap >= 0) {
1501 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1506 if ((Scrollback_mode == SCROLLBACK_MODE_OBJECTIVES) && (Status_bitmap >= 0)) {
1507 gr_set_bitmap(Status_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1508 gr_bitmap(Hud_mission_log_status_coords[gr_screen.res][0], Hud_mission_log_status_coords[gr_screen.res][1]);
1512 // draw the objectives key at the bottom of the ingame objectives screen
1513 if (Scrollback_mode == SCROLLBACK_MODE_OBJECTIVES) {
1514 ML_render_objectives_key();
1519 if (Scrollback_mode == SCROLLBACK_MODE_EVENT_LOG) {
1520 Buttons[gr_screen.res][SHOW_EVENTS_BUTTON].button.draw_forced(2);
1521 mission_log_scrollback(Scroll_offset, Hud_mission_log_list_coords[gr_screen.res][0], Hud_mission_log_list_coords[gr_screen.res][1], Hud_mission_log_list_coords[gr_screen.res][2], Hud_mission_log_list_coords[gr_screen.res][3]);
1523 } else if (Scrollback_mode == SCROLLBACK_MODE_OBJECTIVES) {
1524 Buttons[gr_screen.res][SHOW_OBJS_BUTTON].button.draw_forced(2);
1525 ML_objectives_do_frame(Scroll_offset);
1528 line_node *node_ptr;
1530 Buttons[gr_screen.res][SHOW_MSGS_BUTTON].button.draw_forced(2);
1531 // y = ((LIST_H / font_height) - 1) * font_height;
1533 if ( !EMPTY(&Msg_scrollback_used_list) && HUD_msg_inited ) {
1534 node_ptr = GET_FIRST(&Msg_scrollback_used_list);
1536 while ( node_ptr != END_OF_LIST(&Msg_scrollback_used_list) ) {
1537 if ((node_ptr->source == HUD_SOURCE_HIDDEN) || (i++ < Scroll_offset)) {
1538 node_ptr = GET_NEXT(node_ptr);
1541 switch (node_ptr->source) {
1542 case HUD_SOURCE_FRIENDLY:
1546 case HUD_SOURCE_HOSTILE:
1550 case HUD_SOURCE_NEUTRAL:
1554 case HUD_SOURCE_UNKNOWN:
1558 case HUD_SOURCE_TRAINING:
1559 gr_set_color_fast(&Color_bright_blue);
1562 case HUD_SOURCE_TERRAN_CMD:
1563 gr_set_color_fast(&Color_bright_white);
1566 case HUD_SOURCE_IMPORTANT:
1567 case HUD_SOURCE_FAILED:
1568 case HUD_SOURCE_SATISFIED:
1569 gr_set_color_fast(&Color_bright_white);
1573 gr_set_color_fast(&Color_text_normal);
1578 gr_print_timestamp(Hud_mission_log_list_coords[gr_screen.res][0], Hud_mission_log_list_coords[gr_screen.res][1] + y, node_ptr->time);
1580 x = Hud_mission_log_list2_coords[gr_screen.res][0] + node_ptr->x;
1581 gr_printf(x, Hud_mission_log_list_coords[gr_screen.res][1] + y, "%s", node_ptr->text);
1582 if (node_ptr->underline_width)
1583 gr_line(x, Hud_mission_log_list_coords[gr_screen.res][1] + y + font_height - 1, x + node_ptr->underline_width, Hud_mission_log_list_coords[gr_screen.res][1] + y + font_height - 1);
1585 if ((node_ptr->source == HUD_SOURCE_FAILED) || (node_ptr->source == HUD_SOURCE_SATISFIED)) {
1587 if (node_ptr->source == HUD_SOURCE_FAILED)
1588 gr_set_color_fast(&Color_bright_red);
1590 gr_set_color_fast(&Color_bright_green);
1592 i = Hud_mission_log_list_coords[gr_screen.res][1] + y + font_height / 2 - 1;
1593 gr_circle(Hud_mission_log_list2_coords[gr_screen.res][0] - 6, i, 5);
1595 gr_set_color_fast(&Color_bright);
1596 gr_line(Hud_mission_log_list2_coords[gr_screen.res][0] - 10, i, Hud_mission_log_list2_coords[gr_screen.res][0] - 8, i);
1597 gr_line(Hud_mission_log_list2_coords[gr_screen.res][0] - 6, i - 4, Hud_mission_log_list2_coords[gr_screen.res][0] - 6, i - 2);
1598 gr_line(Hud_mission_log_list2_coords[gr_screen.res][0] - 4, i, Hud_mission_log_list2_coords[gr_screen.res][0] - 2, i);
1599 gr_line(Hud_mission_log_list2_coords[gr_screen.res][0] - 6, i + 2, Hud_mission_log_list2_coords[gr_screen.res][0] - 6, i + 4);
1602 y += font_height + node_ptr->y;
1603 node_ptr = GET_NEXT(node_ptr);
1604 if (y + font_height > Hud_mission_log_list_coords[gr_screen.res][3])
1611 gr_set_color_fast(&Color_text_heading);
1612 gr_print_timestamp(Hud_mission_log_time_coords[gr_screen.res][0], Hud_mission_log_time_coords[gr_screen.res][1] - font_height, (int) (f2fl(Missiontime) * 1000));
1613 gr_string(Hud_mission_log_time2_coords[gr_screen.res][0], Hud_mission_log_time_coords[gr_screen.res][1] - font_height, XSTR( "Current time", 289));
1617 void hud_scrollback_exit()
1619 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);