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