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