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