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