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