]> icculus.org git repositories - taylor/freespace2.git/blob - src/gamehelp/contexthelp.cpp
replace setjmp with try-catch
[taylor/freespace2.git] / src / gamehelp / contexthelp.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/GameHelp/ContextHelp.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Functions to drive the context-sensitive help 
16  *
17  * $Log$
18  * Revision 1.8  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
24  *
25  * Revision 1.7  2004/09/20 01:31:44  theoddone33
26  * GCC 3.4 fixes.
27  *
28  * Revision 1.6  2003/06/11 18:30:32  taylor
29  * plug memory leaks
30  *
31  * Revision 1.5  2003/05/25 02:30:42  taylor
32  * Freespace 1 support
33  *
34  * Revision 1.4  2002/06/17 06:33:09  relnev
35  * ryan's struct patch for gcc 2.95
36  *
37  * Revision 1.3  2002/06/09 04:41:17  relnev
38  * added copyright header
39  *
40  * Revision 1.2  2002/05/07 03:16:44  theoddone33
41  * The Great Newline Fix
42  *
43  * Revision 1.1.1.1  2002/05/03 03:28:09  root
44  * Initial import.
45  *
46  * 
47  * 16    8/22/99 4:22p Jefff
48  * removed 2nd tech room overlay stuff
49  * 
50  * 15    8/09/99 5:54p Jefff
51  * tech room overlay changes
52  * 
53  * 14    7/27/99 7:18p Jefff
54  * fixed a debug function for adjsuting overlays in-game
55  * 
56  * 13    7/20/99 1:49p Dave
57  * Peter Drake build. Fixed some release build warnings.
58  * 
59  * 12    7/16/99 10:07a Jefff
60  * Removed legacy bitmap overlay code
61  * 
62  * 11    7/16/99 10:04a Jefff
63  * 
64  * 10    7/15/99 9:20a Andsager
65  * FS2_DEMO initial checkin
66  * 
67  * 9     7/11/99 6:40p Jefff
68  * 
69  * 8     7/08/99 6:25p Jefff
70  * got new help system working
71  * 
72  * 7     6/03/99 10:15p Dave
73  * Put in temporary main hall screen.
74  * 
75  * 6     3/25/99 8:32p Neilk
76  * temporary barracks help removal
77  * 
78  * 5     2/15/99 9:37a Dave
79  * Removed infinite loop from context help parse code.
80  * 
81  * 4     2/11/99 4:05p Neilk
82  * Temporary checkin
83  * 
84  * 3     1/29/99 2:37p Neilk
85  * foundation for a new help system
86  * 
87  * 2     10/07/98 10:52a Dave
88  * Initial checkin.
89  * 
90  * 1     10/07/98 10:48a Dave
91  * 
92  * 92    5/06/98 11:49p Lawrance
93  * Add help overlay for command brief
94  * 
95  * 91    5/05/98 1:49a Lawrance
96  * Add in missing help overlays
97  * 
98  * 90    4/25/98 2:00p Dave
99  * Installed a bunch of multiplayer context help screens. Reworked ingame
100  * join ship select screen. Fix places where network timestamps get hosed.
101  * 
102  * 89    4/20/98 12:03a Lawrance
103  * make gray help shader lighter
104  * 
105  * 88    4/11/98 7:59p Lawrance
106  * Add support for help overlays
107  * 
108  * 87    3/12/98 5:36p John
109  * Took out any unused shaders.  Made shader code take rgbc instead of
110  * matrix and vector since noone used it like a matrix and it would have
111  * been impossible to do in hardware.   Made Glide implement a basic
112  * shader for online help.  
113  * 
114  * 86    3/09/98 9:55p Lawrance
115  * split off gameplay help, rip out obsolete code
116  * 
117  * 85    3/05/98 11:15p Hoffoss
118  * Changed non-game key checking to use game_check_key() instead of
119  * game_poll().
120  * 
121  * 84    2/28/98 9:47p Lawrance
122  * Fix couple of typos
123  * 
124  * 83    2/28/98 7:02p Lawrance
125  * overhaul on-line help
126  * 
127 */
128 #include <string.h>
129
130 #include "contexthelp.h"
131 #include "gamesequence.h"
132 #include "freespace.h"
133 #include "mainhallmenu.h"
134 #include "key.h"
135 #include "bmpman.h"
136 #include "2d.h"
137 #include "timer.h"
138 #include "math.h"
139 #include "mouse.h"
140 #include "controlsconfig.h"
141 #include "techmenu.h"
142 #include "parselo.h"
143 #include "localize.h"
144 #include "alphacolors.h"
145
146
147 ////////////////////////////////////////////////////////////////////
148 // private function prototypes / structs
149 ////////////////////////////////////////////////////////////////////
150 void parse_helptbl();
151 void help_overlay_blit(int overlay_id);
152 void help_overlay_init();
153
154
155 typedef struct {
156         int x_begin, y_begin, x_end, y_end;
157 } help_line;
158
159 typedef struct {
160         vector vtx[HELP_MAX_PLINE_VERTICES];
161         vector *pvtx[HELP_MAX_PLINE_VERTICES];
162         int vtxcount;
163 } help_pline;
164
165 typedef struct {
166         int x_coord, y_coord;
167         char* string;
168 } help_text;
169
170 typedef struct {
171         int x_coord, y_coord;
172 } help_left_bracket;
173
174 typedef struct {
175         int x_coord, y_coord;
176 } help_right_bracket;
177
178 typedef struct {
179         help_pline                              plinelist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
180         help_text                               textlist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
181         help_left_bracket               lbracketlist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
182         help_right_bracket      rbracketlist[GR_NUM_RESOLUTIONS][HELP_MAX_ITEM];
183         int plinecount;
184         int textcount;
185         int lbracketcount;
186         int rbracketcount;
187 } help_overlay;
188
189 // Added for FS1
190 const char *Help_overlays[MAX_HELP_OVERLAYS] = {
191         "ship_help_over",
192         "weapon_help_over",
193 #ifndef FS1_DEMO
194         "brief_help_over",
195         "main_help_overlay",
196 #else
197         "Briefing_Help_Overlay_Demo",
198         "main_help_overlay_demo",
199 #endif
200         "barracks_help",
201         "control_help",
202         "debrief_help",
203         "multicreate_help",
204         "multistart_help",
205         "multijoin_help",
206         "main_help_overlay2",
207         "hotkey_help",
208         "campaign_help",
209         "simulator_help",
210         "tech_help",
211 //      "tech_help2",
212         "command_help"
213 };
214
215 // new help.tbl file way
216 const char *help_overlay_section_names[MAX_HELP_OVERLAYS] = {
217         "$ship",                                        // ship_help
218         "$weapon",                              // weapon_help
219         "$briefing",                    // briefing
220         "$main",                                        //      main help overlay
221         "$barracks",                    // barracks
222         "$control",                             // control help
223         "$debrief",                             // debrief help
224         "$multicreate",         // multicreate help
225         "$multistart",                  // multistart help
226         "$multijoin",                   // multijoin help
227         "$main2",                               // main help overlay2
228         "$hotkey",                              // hotkey help
229         "$campaign",                    // campaign help
230         "$simulator",                   //      simulator help
231         "$tech",                                        // tech help
232         "$command"                              // command help
233 };
234
235 ////////////////////////////////////////////////////////////////////
236 // Game-wide globals
237 ////////////////////////////////////////////////////////////////////
238 shader Grey_shader;
239
240 ////////////////////////////////////////////////////////////////////
241 // Module globals
242 ////////////////////////////////////////////////////////////////////
243 #ifndef MAKE_FS1
244 static int help_left_bracket_bitmap;
245 static int help_right_bracket_bitmap;
246 #endif
247 static help_overlay help_overlaylist[MAX_HELP_OVERLAYS];
248
249 static int current_helpid = -1;         // the currently active overlay_id, only really used for the debug console funxions
250 int Help_overlay_flags;
251 static int Source_game_state;                   // state from where F1 was pressed
252
253 #ifdef MAKE_FS1
254 static int Overlay = -1;
255 #endif
256
257 ////////////////////////////////////////////////////////////////////
258 // Public Functions
259 ////////////////////////////////////////////////////////////////////
260
261
262 // query whether a help overlay is active (ie being displayed)
263 int help_overlay_active(int overlay_id)
264 {
265         SDL_assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
266         return Help_overlay_flags & (1<<overlay_id);
267 }
268
269 // stop displaying a help overlay
270 void help_overlay_set_state(int overlay_id, int state)
271 {
272         SDL_assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
273
274         if ( state > 0 ) {
275                 Help_overlay_flags |= (1<<overlay_id);
276                 current_helpid = overlay_id;
277         } else {
278                 Help_overlay_flags &= ~(1<<overlay_id);
279                 //current_helpid = -1;
280         }
281
282 }
283
284 // load in the bitmap for a help overlay
285 // FIXME - leftover from the old bitmap overlay days - prune this out sometime
286 void help_overlay_load(int overlay_id)
287 {
288         return;
289
290
291 // unload a bitmap of a help overlay
292 // FIXME - leftover from the old bitmap overlay days - prune this out sometime
293 void help_overlay_unload(int overlay_id)
294 {
295 #ifdef MAKE_FS1
296         if (Overlay >= 0) {
297                 bm_unload(Overlay);
298         }
299 #else
300         return; 
301 #endif
302 }
303
304 // maybe blit a bitmap of a help overlay to the screen
305 void help_overlay_maybe_blit(int overlay_id)
306 {
307         SDL_assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
308
309         if ( Help_overlay_flags & (1<<overlay_id) ) {
310                 context_help_grey_screen();
311                 help_overlay_blit(overlay_id);                          
312         }
313 }
314
315 // reset the flags for the help overlays
316 void help_overlay_reset_all()
317 {
318         Help_overlay_flags = 0;
319 }
320
321 // Set up Grey_shader, which is used game-wide to grey out background when using help overlays
322 void create_grey_shader()
323 {
324         float tmp,c;
325
326         tmp = 0.4f/3.0f;
327
328         // The c matrix brightens everything a bit.
329 //      c = 0.125f;
330         c = 0.110f;
331
332         gr_create_shader( &Grey_shader, tmp, tmp, tmp, c );
333 }
334
335 // called at game startup to init all help related data
336 void context_help_init() 
337 {
338         create_grey_shader();
339         help_overlay_reset_all();
340         help_overlay_init();
341 }
342
343 // called in game_shutdown() to clean up help stuff
344 void context_help_close()
345 {
346 #ifndef MAKE_FS1
347         int i, j;
348
349         for (i=0; i<MAX_HELP_OVERLAYS; i++) {
350                 for (j=0; j<HELP_MAX_ITEM; j++) {
351                         if (help_overlaylist[i].textlist[GR_640][j].string != NULL) {
352                                 free(help_overlaylist[i].textlist[GR_640][j].string);
353                                 help_overlaylist[i].textlist[GR_640][j].string = NULL;
354                         }
355                 }
356         }
357 #endif
358 }
359
360 void context_help_grey_screen()
361 {
362         gr_set_shader(&Grey_shader);
363         gr_shade(0,0,gr_screen.clip_width, gr_screen.clip_height);
364 }
365
366 // launch_context_help() will switch to a context sensitive help state
367 void launch_context_help()
368 {
369         // look at the state the game was in when F1 was pressed
370         Source_game_state = gameseq_get_state();
371
372         switch (Source_game_state) {
373
374                 case GS_STATE_MAIN_MENU:
375 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
376                         int main_hall_num;
377                         main_hall_num = (main_hall_id() == 0) ? MH_OVERLAY : MH2_OVERLAY;
378                         if ( !help_overlay_active(main_hall_num) ) {
379                                 help_overlay_set_state(main_hall_num, 1);
380                         }
381                         else {
382                                 help_overlay_set_state(main_hall_num, 0);
383                         }
384 #endif
385                         break;
386
387                 case GS_STATE_GAME_PLAY:
388                 case GS_STATE_GAME_PAUSED:
389                 case GS_STATE_TRAINING_PAUSED:
390                         gameseq_post_event(GS_EVENT_GAMEPLAY_HELP);
391                         break;
392
393                 case GS_STATE_BRIEFING:
394                         if ( !help_overlay_active(BR_OVERLAY) ) {
395                                 help_overlay_set_state(BR_OVERLAY, 1);
396                         }
397                         else {
398                                 help_overlay_set_state(BR_OVERLAY, 0);
399                         }
400                         break;
401
402                 case GS_STATE_SHIP_SELECT:
403                         if ( !help_overlay_active(SS_OVERLAY) ) {
404                                 help_overlay_set_state(SS_OVERLAY, 1);
405                         }
406                         else {
407                                 help_overlay_set_state(SS_OVERLAY, 0);
408                         }
409                         break;
410
411                 case GS_STATE_WEAPON_SELECT:
412                         if ( !help_overlay_active(WL_OVERLAY) ) {
413                                 help_overlay_set_state(WL_OVERLAY, 1);
414                         }
415                         else {
416                                 help_overlay_set_state(WL_OVERLAY, 0);
417                         }
418                         break;
419
420                 case GS_STATE_BARRACKS_MENU:
421                         if ( !help_overlay_active(BARRACKS_OVERLAY) ) {
422                                 help_overlay_set_state(BARRACKS_OVERLAY, 1);
423                         }
424                         else {
425                                 help_overlay_set_state(BARRACKS_OVERLAY, 0);
426                         }
427                         break;
428
429                 case GS_STATE_CONTROL_CONFIG:
430                         if ( !help_overlay_active(CONTROL_CONFIG_OVERLAY) ) {
431                                 help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 1);
432                         }
433                         else {
434                                 help_overlay_set_state(CONTROL_CONFIG_OVERLAY, 0);
435                         }
436                         break;
437
438                 case GS_STATE_DEBRIEF:
439                         if ( !help_overlay_active(DEBRIEFING_OVERLAY) ) {
440                                 help_overlay_set_state(DEBRIEFING_OVERLAY, 1);
441                         }
442                         else {
443                                 help_overlay_set_state(DEBRIEFING_OVERLAY, 0);
444                         }
445                         break;
446
447                 case GS_STATE_MULTI_HOST_SETUP:
448                         if ( !help_overlay_active(MULTI_CREATE_OVERLAY) ) {
449                                 help_overlay_set_state(MULTI_CREATE_OVERLAY, 1);
450                         }
451                         else {
452                                 help_overlay_set_state(MULTI_CREATE_OVERLAY, 0);
453                         }
454                         break;
455
456                 case GS_STATE_MULTI_START_GAME:
457                         if ( !help_overlay_active(MULTI_START_OVERLAY) ) {
458                                 help_overlay_set_state(MULTI_START_OVERLAY, 1);
459                         }
460                         else {
461                                 help_overlay_set_state(MULTI_START_OVERLAY, 0);
462                         }
463                         break;
464
465                 case GS_STATE_MULTI_JOIN_GAME:
466                         if ( !help_overlay_active(MULTI_JOIN_OVERLAY) ) {
467                                 help_overlay_set_state(MULTI_JOIN_OVERLAY, 1);
468                         }
469                         else {
470                                 help_overlay_set_state(MULTI_JOIN_OVERLAY, 0);
471                         }
472                         break;
473
474                 case GS_STATE_HOTKEY_SCREEN:
475                         if ( !help_overlay_active(HOTKEY_OVERLAY) ) {
476                                 help_overlay_set_state(HOTKEY_OVERLAY, 1);
477                         }
478                         else {
479                                 help_overlay_set_state(HOTKEY_OVERLAY, 0);
480                         }
481                         break;
482
483                 case GS_STATE_CAMPAIGN_ROOM:
484                         if ( !help_overlay_active(CAMPAIGN_ROOM_OVERLAY) ) {
485                                 help_overlay_set_state(CAMPAIGN_ROOM_OVERLAY, 1);
486                         }
487                         else {
488                                 help_overlay_set_state(CAMPAIGN_ROOM_OVERLAY, 0);
489                         }
490                         break;
491
492                 case GS_STATE_SIMULATOR_ROOM:
493                         if ( !help_overlay_active(SIM_ROOM_OVERLAY) ) {
494                                 help_overlay_set_state(SIM_ROOM_OVERLAY, 1);
495                         }
496                         else {
497                                 help_overlay_set_state(SIM_ROOM_OVERLAY, 0);
498                         }
499                         break;
500
501                 case GS_STATE_TECH_MENU: {                              
502                         if ( !help_overlay_active(TECH_ROOM_OVERLAY) ) {
503                                 help_overlay_set_state(TECH_ROOM_OVERLAY, 1);
504                         }
505                         else {
506                                 help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
507                         }
508                         break;
509                 }
510
511                 case GS_STATE_CMD_BRIEF:
512                         if ( !help_overlay_active(CMD_BRIEF_OVERLAY) ) {
513                                 help_overlay_set_state(CMD_BRIEF_OVERLAY, 1);
514                         }
515                         else {
516                                 help_overlay_set_state(CMD_BRIEF_OVERLAY, 0);
517                         }
518                         break;
519
520                 default:
521                         nprintf(("Warning","WARNING ==> There is no context help available for state %s\n", GS_state_text[Source_game_state-1]));
522                         break;
523
524         } // end switch
525 }
526
527
528 // Called once at the beginning of the game to load help bitmaps & data
529 void help_overlay_init() 
530 {
531 #ifndef MAKE_FS1
532         // load right_bracket bitmap
533         help_right_bracket_bitmap = bm_load("right_bracket");
534         if(help_right_bracket_bitmap < 0){
535                 // we failed to load the bitmap - this is very bad
536                 Int3();
537         }
538
539         // load left_bracket bitmap
540         help_left_bracket_bitmap = bm_load("left_bracket");
541         if(help_left_bracket_bitmap < 0){
542                 // we failed to load the bitmap - this is very bad
543                 Int3();
544         }
545
546         // parse help.tbl
547         parse_helptbl();
548 #endif
549 }
550
551
552 // parses help.tbl and populates help_overlaylist[]
553 void parse_helptbl()
554 {
555 #ifndef MAKE_FS1
556         int overlay_id, currcount;
557         char buf[HELP_MAX_STRING_LENGTH + 1];
558         int i;
559
560         // open localization
561         lcl_ext_open();
562
563         try {
564                 read_file_text(HELP_OVERLAY_FILENAME);
565
566                 // for each overlay...
567                 for (overlay_id=0; overlay_id<MAX_HELP_OVERLAYS; overlay_id++) {
568
569                         reset_parse();
570                         skip_to_string(help_overlay_section_names[overlay_id]);
571
572                         // clear out counters in the overlay struct
573                         help_overlaylist[overlay_id].plinecount = 0;
574                         help_overlaylist[overlay_id].textcount = 0;
575                         help_overlaylist[overlay_id].rbracketcount = 0;
576                         help_overlaylist[overlay_id].lbracketcount = 0;
577
578                         // read in all elements for this overlay
579                         while (!(check_for_string("$end")))  {
580
581                                 if (optional_string("+pline")) {
582
583                                         currcount = help_overlaylist[overlay_id].plinecount;
584                                         int a, b;               // temp vars to read in int before cast to float;
585
586                                         if (currcount < HELP_MAX_ITEM) {
587                                                 // read number of pline vertices
588                                                 stuff_int(&help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount);         // note that it is read into GR_640
589                                                 // help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtxcount = help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount;                    // set equal to 1024 version vertex count to prevent bugs
590                                                 SDL_assert(help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount <= HELP_MAX_PLINE_VERTICES);
591                                                 // get 640x480 vertex coordinates
592                                                 for (i=0; i<help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount; i++) {
593                                                         stuff_int(&a);
594                                                         stuff_int(&b);
595                                                         help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i].xyz.x = (float)a;
596                                                         help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i].xyz.y = (float)b;
597                                                         help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i].xyz.z = 0.0f;
598                                                         help_overlaylist[overlay_id].plinelist[GR_640][currcount].pvtx[i] = &help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[i];
599                                                 }
600                                                 // get 1024x768 vertex coordinates
601                                                 for (i=0; i<help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtxcount; i++) {
602                                                         stuff_int(&a);
603                                                         stuff_int(&b);
604                                                         help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i].xyz.x = (float)a;
605                                                         help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i].xyz.y = (float)b;
606                                                         help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i].xyz.z = 0.0f;
607                                                         help_overlaylist[overlay_id].plinelist[GR_1024][currcount].pvtx[i] = &help_overlaylist[overlay_id].plinelist[GR_1024][currcount].vtx[i];
608                                                 }
609                                         }
610
611                                         //mprintf(("Found pline - start location (%f,%f), end location (%f,%f)\n", help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[0].x, help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[0].y, help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[2].x, help_overlaylist[overlay_id].plinelist[GR_640][currcount].vtx[2].y));
612                                         help_overlaylist[overlay_id].plinecount++;
613
614                                 } else if (optional_string("+text")) {
615
616                                         currcount = help_overlaylist[overlay_id].textcount;
617
618                                         if (currcount < HELP_MAX_ITEM) {
619                                                 // get 640x480 coordinates
620                                                 stuff_int(&(help_overlaylist[overlay_id].textlist[GR_640][currcount].x_coord));
621                                                 stuff_int(&(help_overlaylist[overlay_id].textlist[GR_640][currcount].y_coord));
622                                                 // get 1024x768 coordinates
623                                                 stuff_int(&(help_overlaylist[overlay_id].textlist[GR_1024][currcount].x_coord));
624                                                 stuff_int(&(help_overlaylist[overlay_id].textlist[GR_1024][currcount].y_coord));
625
626                                                 // get string (always use the GR_640 one)
627                                                 stuff_string(buf, F_MESSAGE, NULL);
628                                                 help_overlaylist[overlay_id].textlist[GR_640][currcount].string = strdup(buf);
629
630                                                 //mprintf(("Found text %d on overlay %d - location (%d,%d) @ 640x480 :: location (%d,%d) @ 1024x768\n", currcount, overlay_id, help_overlaylist[overlay_id].textlist[GR_640][currcount].x_coord, help_overlaylist[overlay_id].textlist[GR_640][currcount].y_coord, help_overlaylist[overlay_id].textlist[GR_1024][currcount].x_coord, help_overlaylist[overlay_id].textlist[GR_1024][currcount].x_coord));
631                                                 help_overlaylist[overlay_id].textcount++;
632                                         }
633
634                                 } else if (optional_string("+right_bracket")) {
635
636                                         currcount = help_overlaylist[overlay_id].rbracketcount;
637
638                                         if (currcount < HELP_MAX_ITEM) {
639                                                 // get 640x480 coordinates
640                                                 stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].x_coord));
641                                                 stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].y_coord));
642                                                 // get 1024x768 coordinates
643                                                 stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].x_coord));
644                                                 stuff_int(&(help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].y_coord));
645
646                                                 //mprintf(("Found rbracket %d on overlay %d - location (%d,%d) @ 640x480 :: location (%d,%d) @ 1024x768\n", currcount, overlay_id, help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].x_coord, help_overlaylist[overlay_id].rbracketlist[GR_640][currcount].y_coord, help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].x_coord, help_overlaylist[overlay_id].rbracketlist[GR_1024][currcount].y_coord));
647                                                 help_overlaylist[overlay_id].rbracketcount++;
648                                         }
649
650                                 } else if (optional_string("+left_bracket")) {
651
652                                         currcount = help_overlaylist[overlay_id].lbracketcount;
653
654                                         if (currcount < HELP_MAX_ITEM) {
655                                                 // get 640x480 coordinates
656                                                 stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].x_coord));
657                                                 stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].y_coord));
658                                                 // get 1024x768 coordinates
659                                                 stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].x_coord));
660                                                 stuff_int(&(help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].y_coord));
661
662                                                 //mprintf(("Found lbracket %d on overlay %d - location (%d,%d) @ 640x480 :: location (%d,%d) @ 1024x768\n", currcount, overlay_id, help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].x_coord, help_overlaylist[overlay_id].lbracketlist[GR_640][currcount].y_coord, help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].x_coord, help_overlaylist[overlay_id].lbracketlist[GR_1024][currcount].y_coord));
663                                                 help_overlaylist[overlay_id].lbracketcount++;
664                                         }
665
666                                 } else {
667                                         // help.tbl is corrupt
668                                         SDL_assert(0);
669
670                                 }               // end if
671
672                         }               // end while
673                 }               // end for
674         } catch (parse_error_t rval) {
675                 Error(LOCATION, "Unable to parse %s!  Code = %i.\n", HELP_OVERLAY_FILENAME, (int)rval);
676         }
677
678         // close localization
679         lcl_ext_close();
680 #endif
681 }
682
683
684
685 // draw overlay on the screen
686 void help_overlay_blit(int overlay_id) 
687 {
688 #ifdef MAKE_FS1
689         Overlay = bm_load(Help_overlays[overlay_id]);
690         if (Overlay < 0){
691                 Int3();
692         }
693
694         if (Overlay >= 0){
695                 gr_set_bitmap(Overlay, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
696                 gr_bitmap(0, 0);
697         }
698 #else
699         int idx, width, height;
700         int plinecount = help_overlaylist[overlay_id].plinecount;
701         int textcount = help_overlaylist[overlay_id].textcount;
702         int rbracketcount = help_overlaylist[overlay_id].rbracketcount;
703         int lbracketcount = help_overlaylist[overlay_id].lbracketcount;
704
705         SDL_assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);
706
707         // this draws each line of help text with white on black text (use the GR_640 index for the string)
708         for (idx = 0; idx < textcount; idx++) {
709                 gr_set_color_fast(&Color_black);
710                 gr_get_string_size(&width, &height, help_overlaylist[overlay_id].textlist[GR_640][idx].string, strlen(help_overlaylist[overlay_id].textlist[GR_640][idx].string));
711                 gr_rect(help_overlaylist[overlay_id].textlist[gr_screen.res][idx].x_coord-2*HELP_PADDING, help_overlaylist[overlay_id].textlist[gr_screen.res][idx].y_coord-3*HELP_PADDING, width+4*HELP_PADDING, height+4*HELP_PADDING);
712                 gr_set_color_fast(&Color_bright_white);
713                 gr_printf(help_overlaylist[overlay_id].textlist[gr_screen.res][idx].x_coord, help_overlaylist[overlay_id].textlist[gr_screen.res][idx].y_coord, help_overlaylist[overlay_id].textlist[GR_640][idx].string);
714         }
715
716         // this draws each right bracket
717         for (idx = 0; idx < rbracketcount; idx++) {
718                 gr_set_bitmap(help_right_bracket_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
719                 gr_bitmap(help_overlaylist[overlay_id].rbracketlist[gr_screen.res][idx].x_coord, help_overlaylist[overlay_id].rbracketlist[gr_screen.res][idx].y_coord);
720         }
721
722         // this draws each left bracket
723         for (idx = 0; idx < lbracketcount; idx++) {
724                 gr_set_bitmap(help_left_bracket_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
725                 gr_bitmap(help_overlaylist[overlay_id].lbracketlist[gr_screen.res][idx].x_coord, help_overlaylist[overlay_id].lbracketlist[gr_screen.res][idx].y_coord);
726         }       
727
728         // this draws each 2d line for the help screen
729         //gr_set_color_fast(&Color_yellow);
730         gr_set_color(255, 255, 0);
731         for (idx = 0; idx<plinecount; idx++) {
732                 gr_pline_special(help_overlaylist[overlay_id].plinelist[gr_screen.res][idx].pvtx        , help_overlaylist[overlay_id].plinelist[GR_640][idx].vtxcount, HELP_PLINE_THICKNESS);
733         }
734 #endif  // MAKE_FS1
735 }
736
737
738 // --------------------------------------------------
739 // DEBUGGING STUFF
740 // --------------------------------------------------
741
742 DCF(help_reload, "Reloads help overlay data from help.tbl")
743 {
744         if (Dc_command) {
745                 parse_helptbl();
746         }
747
748         if (Dc_help)    {
749                 dc_printf( "Usage: sample\nCrashes your machine.\n" );
750         }
751
752         if (Dc_status)  {
753                 dc_printf( "Yes, my master." );
754         }
755 }
756
757 int h_textnum=0, h_amt=0, h_vtx = 0;
758
759 void nudgetext_x(int textnum, int amount)
760 {
761         help_overlaylist[current_helpid].textlist[gr_screen.res][textnum].x_coord += amount;
762 }
763 void nudgetext_y(int textnum, int amount)
764 {
765         help_overlaylist[current_helpid].textlist[gr_screen.res][textnum].y_coord += amount;
766 }
767 void nudgepline_x(int plinenum, int plinevert, int amount)
768 {
769         help_overlaylist[current_helpid].plinelist[gr_screen.res][plinenum].vtx[plinevert].xyz.x += amount;
770 }
771 void nudgepline_y(int plinenum, int plinevert, int amount)
772 {
773         help_overlaylist[current_helpid].plinelist[gr_screen.res][plinenum].vtx[plinevert].xyz.y += amount;
774 }
775 void nudgerbracket_x(int num, int amount)
776 {
777         help_overlaylist[current_helpid].rbracketlist[gr_screen.res][num].x_coord += amount;
778 }
779 void nudgerbracket_y(int num, int amount)
780 {
781         help_overlaylist[current_helpid].rbracketlist[gr_screen.res][num].y_coord += amount;
782 }
783 void nudgelbracket_x(int num, int amount)
784 {
785         help_overlaylist[current_helpid].lbracketlist[gr_screen.res][num].x_coord += amount;
786 }
787 void nudgelbracket_y(int num, int amount)
788 {
789         help_overlaylist[current_helpid].lbracketlist[gr_screen.res][num].y_coord += amount;
790 }
791 void showtextpos(int textnum)
792 {
793         dc_printf("text %d is now located at (%d, %d)", textnum, help_overlaylist[current_helpid].textlist[gr_screen.res][textnum].x_coord, help_overlaylist[current_helpid].textlist[gr_screen.res][textnum].y_coord );
794 }
795 void showrbracketpos(int num)
796 {
797         dc_printf("rbracket %d is now located at (%d, %d)", num, help_overlaylist[current_helpid].rbracketlist[gr_screen.res][num].x_coord, help_overlaylist[current_helpid].rbracketlist[gr_screen.res][num].y_coord );
798 }
799 void showlbracketpos(int num)
800 {
801         dc_printf("lbracket %d on overlay %d is now located at (%d, %d)", num, current_helpid, help_overlaylist[current_helpid].lbracketlist[gr_screen.res][num].x_coord, help_overlaylist[current_helpid].lbracketlist[gr_screen.res][num].y_coord );
802 }
803 void showplinepos(int plinenum)
804 {
805         int i;
806         dc_printf("pline %d on overlay %d vertices are now ", plinenum, current_helpid, help_overlaylist[current_helpid].textlist[gr_screen.res][plinenum].y_coord );
807         for (i=0; i<help_overlaylist[current_helpid].plinelist[GR_640][plinenum].vtxcount; i++)
808         {
809                 dc_printf("(%3.0f %3.0f) ", help_overlaylist[current_helpid].plinelist[gr_screen.res][plinenum].vtx[i].xyz.x, help_overlaylist[current_helpid].plinelist[gr_screen.res][plinenum].vtx[i].xyz.y);
810         }
811 }
812
813 DCF(help_nudgetext_x, "Use to visually position overlay text.")
814 {
815         if (Dc_command) {
816                 dc_get_arg(ARG_INT);
817                 if(Dc_arg_type & ARG_INT){
818                          h_textnum = Dc_arg_int;                
819                 }
820                 dc_get_arg(ARG_INT);
821                 if(Dc_arg_type & ARG_INT){
822                          h_amt = Dc_arg_int;            
823                 }
824                 nudgetext_x(h_textnum, h_amt);
825         }
826
827         if (Dc_help)    {
828                 dc_printf( "Usage: sample\nCrashes your machine.\n" );
829         }
830
831         if (Dc_status)  {
832                 showtextpos(h_textnum);
833         }
834 }
835
836 DCF(help_nudgetext_y, "Use to visually position overlay text.")
837 {
838         if (Dc_command) {
839                 dc_get_arg(ARG_INT);
840                 if(Dc_arg_type & ARG_INT){
841                          h_textnum = Dc_arg_int;                
842                 }
843                 dc_get_arg(ARG_INT);
844                 if(Dc_arg_type & ARG_INT){
845                          h_amt = Dc_arg_int;            
846                 }
847                 nudgetext_y(h_textnum, h_amt);
848         }
849
850         if (Dc_help)    {
851                 dc_printf( "Usage: sample\nCrashes your machine.\n" );
852         }
853
854         if (Dc_status)  {
855                 showtextpos(h_textnum);
856         }
857 }
858
859 DCF(help_nudgepline_x, "Use to visually position overlay polylines.")
860 {
861         if (Dc_command) {
862                 dc_get_arg(ARG_INT);
863                 if(Dc_arg_type & ARG_INT){
864                          h_textnum = Dc_arg_int;                
865                 }
866                 dc_get_arg(ARG_INT);
867                 if(Dc_arg_type & ARG_INT){
868                          h_vtx = Dc_arg_int;            
869                 }
870                 dc_get_arg(ARG_INT);
871                 if(Dc_arg_type & ARG_INT){
872                          h_amt = Dc_arg_int;            
873                 }
874                 nudgepline_x(h_textnum, h_vtx, h_amt);
875         }
876
877         if (Dc_help)    {
878                 dc_printf( "Usage: help_nudgepline [pline_number] [vertex_number] [distance]\n" );
879         }
880
881         if (Dc_status)  {
882                 showplinepos(h_textnum);
883         }
884 }
885
886
887 DCF(help_nudgepline_y, "Use to visually position overlay polylines.")
888 {
889         if (Dc_command) {
890                 dc_get_arg(ARG_INT);
891                 if(Dc_arg_type & ARG_INT){
892                          h_textnum = Dc_arg_int;                
893                 }
894                 dc_get_arg(ARG_INT);
895                 if(Dc_arg_type & ARG_INT){
896                          h_vtx = Dc_arg_int;            
897                 }
898                 dc_get_arg(ARG_INT);
899                 if(Dc_arg_type & ARG_INT){
900                          h_amt = Dc_arg_int;            
901                 }
902                 nudgepline_y(h_textnum, h_vtx, h_amt);
903         }
904
905         if (Dc_help)    {
906                 dc_printf( "Usage: help_nudgepline [pline_number] [vertex_number] [distance]\n" );
907         }
908
909         if (Dc_status)  {
910                 showplinepos(h_textnum);
911         }
912 }
913
914
915 DCF(help_nudgerbracket_x, "Use to visually position overlay right bracket.")
916 {
917         if (Dc_command) {
918                 dc_get_arg(ARG_INT);
919                 if(Dc_arg_type & ARG_INT){
920                          h_textnum = Dc_arg_int;                
921                 }
922                 dc_get_arg(ARG_INT);
923                 if(Dc_arg_type & ARG_INT){
924                          h_amt = Dc_arg_int;            
925                 }
926                 nudgerbracket_x(h_textnum, h_amt);
927         }
928
929         if (Dc_help)    {
930                 dc_printf( "Usage: help_nudgerbracket_x [num] [amount]\n" );
931         }
932
933         if (Dc_status)  {
934                 showrbracketpos(h_textnum);
935         }
936 }
937
938 DCF(help_nudgerbracket_y, "Use to visually position overlay right bracket.")
939 {
940         if (Dc_command) {
941                 dc_get_arg(ARG_INT);
942                 if(Dc_arg_type & ARG_INT){
943                          h_textnum = Dc_arg_int;                
944                 }
945                 dc_get_arg(ARG_INT);
946                 if(Dc_arg_type & ARG_INT){
947                          h_amt = Dc_arg_int;            
948                 }
949                 nudgerbracket_y(h_textnum, h_amt);
950         }
951
952         if (Dc_help)    {
953                 dc_printf( "Usage: help_nudgerbracket_y [num] [amount]\n" );
954         }
955
956         if (Dc_status)  {
957                 showrbracketpos(h_textnum);
958         }
959 }
960
961
962
963
964 DCF(help_nudgelbracket_x, "Use to visually position overlay left bracket.")
965 {
966         if (Dc_command) {
967                 dc_get_arg(ARG_INT);
968                 if(Dc_arg_type & ARG_INT){
969                          h_textnum = Dc_arg_int;                
970                 }
971                 dc_get_arg(ARG_INT);
972                 if(Dc_arg_type & ARG_INT){
973                          h_amt = Dc_arg_int;            
974                 }
975                 nudgelbracket_x(h_textnum, h_amt);
976         }
977
978         if (Dc_help)    {
979                 dc_printf( "Usage: help_nudgelbracket_x [num] [amount]\n" );
980         }
981
982         if (Dc_status)  {
983                 showlbracketpos(h_textnum);
984         }
985 }
986
987 DCF(help_nudgelbracket_y, "Use to visually position overlay left bracket.")
988 {
989         if (Dc_command) {
990                 dc_get_arg(ARG_INT);
991                 if(Dc_arg_type & ARG_INT){
992                          h_textnum = Dc_arg_int;                
993                 }
994                 dc_get_arg(ARG_INT);
995                 if(Dc_arg_type & ARG_INT){
996                          h_amt = Dc_arg_int;            
997                 }
998                 nudgelbracket_y(h_textnum, h_amt);
999         }
1000
1001         if (Dc_help)    {
1002                 dc_printf( "Usage: help_nudgelbracket_y [num] [amount]\n" );
1003         }
1004
1005         if (Dc_status)  {
1006                 showlbracketpos(h_textnum);
1007         }
1008 }