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