]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/techmenu.cpp
ryan's struct patch for gcc 2.95
[taylor/freespace2.git] / src / menuui / techmenu.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/MenuUI/TechMenu.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C module that contains functions to drive the Tech Menu user interface
16  *
17  * $Log$
18  * Revision 1.5  2002/06/17 06:33:09  relnev
19  * ryan's struct patch for gcc 2.95
20  *
21  * Revision 1.4  2002/06/09 04:41:22  relnev
22  * added copyright header
23  *
24  * Revision 1.3  2002/06/02 04:26:34  relnev
25  * warning cleanup
26  *
27  * Revision 1.2  2002/05/07 03:16:46  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  * 43    11/02/99 3:22p Jefff
35  * translate ship names in tech room
36  * 
37  * 42    10/25/99 5:47p Jefff
38  * reassigned some xstr ids
39  * 
40  * 41    10/12/99 4:50p Jefff
41  * 
42  * 40    9/08/99 11:09a Dave
43  * Use stills for intel and weapon stuff in the techroom if animations
44  * aren't avaliable.
45  * 
46  * 39    9/05/99 11:19p Dave
47  * Made d3d texture cache much more safe. Fixed training scoring bug where
48  * it would backout scores without ever having applied them in the first
49  * place.
50  * 
51  * 38    9/03/99 11:19a Jefff
52  * fixed double render of intel descriptions
53  * 
54  * 37    9/03/99 1:32a Dave
55  * CD checking by act. Added support to play 2 cutscenes in a row
56  * seamlessly. Fixed super low level cfile bug related to files in the
57  * root directory of a CD. Added cheat code to set campaign mission # in
58  * main hall.
59  * 
60  * 36    9/01/99 5:12p Jefff
61  * Fixed bad scroll bug
62  * 
63  * 35    8/25/99 3:03p Jefff
64  * 'more' indicator, lotsa coord changes for new background,  disabling of
65  * buttons in trackball mode, list follows selected item when prev/next
66  * buttons used.
67  * 
68  * 34    8/24/99 8:55p Dave
69  * Make sure nondimming pixels work properly in tech menu.
70  * 
71  * 33    8/24/99 10:47a Jefff
72  * tech room weapon anims.  added tech anim field to weapons.tbl
73  * 
74  * 32    8/10/99 5:29p Jefff
75  * use new tech_title field in weapons array
76  * 
77  * 31    8/10/99 3:45p Jefff
78  * Put the smack down on the tech room.  Its all new, but tastefully done.
79  * 
80  * 30    8/09/99 5:53p Jefff
81  * 
82  * 29    8/02/99 10:27a Jefff
83  * removed a warning for the time being
84  * 
85  * 28    8/02/99 10:13a Jefff
86  * started scrubbing, waiting till after demo to continue
87  * 
88  * 27    7/28/99 1:02p Jefff
89  * Changed "Species" to "Intelligence" -- also changed in strings.tbl.
90  * 
91  * 26    7/26/99 4:33p Jordonr
92  * Don't need techroom palette
93  * 
94  * 25    7/20/99 1:49p Dave
95  * Peter Drake build. Fixed some release build warnings.
96  * 
97  * 24    7/19/99 2:13p Dave
98  * Added some new strings for Heiko.
99  * 
100  * 23    7/14/99 9:42a Dave
101  * Put in clear_color debug function. Put in base for 3dnow stuff / P3
102  * stuff
103  * 
104  * 22    6/16/99 4:06p Dave
105  * New pilot info popup. Added new draw-bitmap-as-poly function.
106  * 
107  * 21    5/09/99 8:57p Dave
108  * Final E3 build preparations.
109  * 
110  * 20    5/09/99 6:00p Dave
111  * Lots of cool new effects. E3 build tweaks.
112  * 
113  * 19    4/29/99 2:16p Neilk
114  * added a 2nd callback for slider so its model is not loaded on mouselock
115  * until mouse button is released
116  * 
117  * 18    4/26/99 5:05p Neilk
118  * updated to new artwork, added slider support
119  * 
120  * 17    4/25/99 3:02p Dave
121  * Build defines for the E3 build.
122  * 
123  * 16    4/23/99 12:01p Johnson
124  * Added SIF_HUGE_SHIP
125  * 
126  * 15    4/12/99 10:07p Dave
127  * Made network startup more forgiving. Added checkmarks to dogfight
128  * screen for players who hit commit.
129  * 
130  * 14    4/08/99 2:10a Dave
131  * Numerous bug fixes for the beta. Added builtin mission info for the
132  * beta.
133  * 
134  * 13    2/19/99 11:42a Dave
135  * Put in model rendering autocentering.
136  * 
137  * 12    2/01/99 5:55p Dave
138  * Removed the idea of explicit bitmaps for buttons. Fixed text
139  * highlighting for disabled gadgets.
140  * 
141  * 11    1/30/99 5:08p Dave
142  * More new hi-res stuff.Support for nice D3D textures.
143  * 
144  * 10    1/29/99 3:56p Neilk
145  * Converted tech_infos screens to multiresolution
146  * 
147  * 9     1/29/99 3:54p Neilk
148  * 
149  * 8     1/29/99 12:47a Dave
150  * Put in sounds for beam weapon. A bunch of interface screens (tech
151  * database stuff).
152  * 
153  * 7     11/30/98 1:07p Dave
154  * 16 bit conversion, first run.
155  * 
156  * 6     10/23/98 3:51p Dave
157  * Full support for tstrings.tbl and foreign languages. All that remains
158  * is to make it active in Fred.
159  * 
160  * 5     10/16/98 9:40a Andsager
161  * Remove ".h" files from model.h
162  * 
163  * 4     10/13/98 2:47p Andsager
164  * Remove reference to Tech_shivan_species_avail
165  * 
166  * 3     10/13/98 9:28a Dave
167  * Started neatening up freespace.h. Many variables renamed and
168  * reorganized. Added AlphaColors.[h,cpp]
169  * 
170  * 2     10/07/98 10:53a Dave
171  * Initial checkin.
172  * 
173  * 1     10/07/98 10:49a Dave
174  * 
175  * 67    9/21/98 10:02p Dave
176  * Last minute changes to techroom weapon/ship/species stuff.
177  * 
178  * 66    9/07/98 2:49p Dan
179  * Removed spurious Assert
180  * 
181  * 65    7/06/98 2:42p Hoffoss
182  * Fixed bug with weapons shown in tech database.
183  * 
184  * 64    6/10/98 11:48a Lawrance
185  * fix bug with trying to free NULL anims
186  * 
187  * 63    6/05/98 9:54a Lawrance
188  * OEM changes
189  * 
190  * 62    6/01/98 11:43a John
191  * JAS & MK:  Classified all strings for localization.
192  * 
193  * 61    5/26/98 11:10a Lawrance
194  * Fix bug where window controls get disabled when F1 pressed twice
195  * 
196  * 60    5/23/98 10:38p Lawrance
197  * Avoid doing a cfile refresh when running debug
198  * 
199  * 59    5/23/98 6:49p Lawrance
200  * Fix problems with refreshing the file list when a CD is inserted
201  * 
202  * 58    5/22/98 11:15a Lawrance
203  * Tweak how CD gets asked for
204  * 
205  * 57    5/22/98 1:06a Hoffoss
206  * Made Fred not use OLE.
207  * 
208  * 56    5/21/98 6:57p Lawrance
209  * Only ask for the CD once
210  * 
211  * 55    5/21/98 12:46a Hoffoss
212  * Made text offset reset when new description is loaded.
213  * 
214  * 54    5/20/98 9:46p John
215  * added code so the places in code that change half the palette don't
216  * have to clear the screen.
217  * 
218  * 53    5/20/98 3:28p Sandeep
219  * Fixed bug where in multi only discovered weapons show up, and in single
220  * all weapons showed up (backwards).
221  * 
222  * 52    5/20/98 2:11p Hoffoss
223  * Fixed some species description problems.
224  * 
225  * 51    5/18/98 6:45p Hoffoss
226  * Added species descriptions to species database in techroom.
227  * 
228  * 50    5/17/98 6:13p Hoffoss
229  * Fixed scrolling of info text area. 
230  *
231  * $NoKeywords: $
232  *
233  */
234
235 #include "gamesequence.h"
236 #include "techmenu.h"
237 #include "2d.h"
238 #include "3d.h"
239 #include "snazzyui.h"
240 #include "managepilot.h"
241 #include "key.h"
242 #include "bmpman.h"
243 #include "timer.h"
244 #include "missioncampaign.h"
245 #include "missionshipchoice.h"
246 #include "freespace.h"
247 #include "mainhallmenu.h"
248 #include "missionscreencommon.h"
249 #include "gamesnd.h"
250 #include "font.h"
251 #include "vecmat.h"
252 #include "mouse.h"
253 #include "uidefs.h"
254 #include "contexthelp.h"
255 #include "alphacolors.h"
256 #include "animplay.h"
257 #include "localize.h"
258 #include "lighting.h"
259
260 #define REVOLUTION_RATE 5.2f
261
262 #define NUM_BUTTONS     16
263 #define NUM_TABS                3
264 #define LIST_BUTTONS_MAX        41
265
266 #define SHIPS_DATA_MODE         (1<<0)
267 #define WEAPONS_DATA_MODE       (1<<1)
268 #define SPECIES_DATA_MODE       (1<<2)
269 #define WEAPONS_SPECIES_DATA_MODE       (WEAPONS_DATA_MODE | SPECIES_DATA_MODE)
270
271 #define SHIPS_DATA_TAB                                  0
272 #define WEAPONS_DATA_TAB                                1
273 #define INTEL_DATA_TAB                                  2
274 #define TECH_DATABASE_TAB                               3
275 #define SIMULATOR_TAB                                   4
276 #define CUTSCENES_TAB                                   5
277 #define CREDITS_TAB                                             6
278
279 #define SCROLL_LIST_UP                                  7
280 #define SCROLL_LIST_DOWN                                8
281 #define SCROLL_INFO_UP                                  9
282 #define SCROLL_INFO_DOWN                                10
283
284 #define PREV_ENTRY_BUTTON                               11
285 #define NEXT_ENTRY_BUTTON                               12
286
287 #define HELP_BUTTON                                             13
288 #define OPTIONS_BUTTON                                  14
289 #define EXIT_BUTTON                                             15
290
291 //#define PREV_ENTRY_BUTTON2                            16
292 //#define NEXT_ENTRY_BUTTON2                            17
293
294
295 #define REPEAT                                          (1<<0)
296 #define NO_MOUSE_OVER_SOUND     (1<<1)
297
298 // indicies for coords
299 #define SHIP_X_COORD 0 
300 #define SHIP_Y_COORD 1
301 #define SHIP_W_COORD 2
302 #define SHIP_H_COORD 3
303
304 // background filename for species
305 // note weapon filename is now same as ship filename
306 char *Tech_background_filename[GR_NUM_RESOLUTIONS] = {
307         "TechShipData",
308         "2_TechShipData"
309 };
310 char *Tech_mask_filename[GR_NUM_RESOLUTIONS] = {
311         "TechShipData-M",
312         "2_TechShipData-M"
313 };
314 char *Tech_slider_filename[GR_NUM_RESOLUTIONS] = {
315         "slider",
316         "2_slider"
317 };
318
319 int Tech_list_coords[GR_NUM_RESOLUTIONS][4] = {
320         { // GR_640
321                 27, 98, 161, 234
322         },
323         { // GR_1024
324                 43, 157, 253, 374
325         }
326 };
327
328 int Tech_ship_display_coords[GR_NUM_RESOLUTIONS][4] = {
329         { // GR_640
330                 239, 98, 393, 222
331         },
332         { // GR_1024
333                 382, 158, 629, 355
334         }
335 };
336
337 int Tech_desc_coords[GR_NUM_RESOLUTIONS][4] = {
338         { // GR_640
339                 29, 347, 365, 125
340         },
341         { // GR_1024
342                 47, 555, 584, 200
343         }
344 };
345
346 int Tech_ani_coords[GR_NUM_RESOLUTIONS][2] = {
347         { // GR_640
348                 196, 115
349         },
350         { // GR_1024
351                 449, 245
352         }
353 };
354
355 /*int Tech_desc_coords[GR_NUM_RESOLUTIONS][4] = {
356         { // GR_640
357                 24, 139, 376, 281
358         },
359         { // GR_1024
360                 24, 182, 638, 528
361         }
362 };*/
363
364 int Tech_slider_coords[GR_NUM_RESOLUTIONS][4] = {
365         { // GR_640
366                 2, 118, 20, 194
367         },
368         { // GR_1024
369                 3, 190, 32, 310
370         }
371 };
372
373 // detail backup
374 int Tech_detail_backup;
375 int Tech_texture_backup;
376
377 #define MAX_TEXT_LINES          100
378 #define MAX_TEXT_LINE_LEN       256
379
380 struct techroom_buttons {
381         char *filename;
382         int x, y, xt, yt;
383         int hotspot;
384         int tab;
385         int flags;
386         UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..
387
388         techroom_buttons(char *name, int x1, int y1, int xt1, int yt1, int h, int t, int f = 0) : filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h), tab(t), flags(f) {}
389 };
390
391 static techroom_buttons Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
392         {       // GR_640
393                 techroom_buttons("TDB_04",      406,    384,    447,    393,    4,      -1),                                                                                    // ship data tab
394                 techroom_buttons("TDB_05",      404,    418,    447,    429,    5,      -1),                                                                                    // weapons data tab
395                 techroom_buttons("TDB_06",      404,    447,    447,    461,    6,      -1),                                                                                    // species data tab
396                 techroom_buttons("TDB_00",      7,              3,              37,     7,              0,      -1),                                                                                    // technical database tab
397                 techroom_buttons("TDB_01",      7,              18,     37,     23,     1,      -1),                                                                                    // mission simulator tab
398                 techroom_buttons("TDB_02",      7,              34,     37,     38,     2,      -1),                                                                                    // cutscenes tab
399                 techroom_buttons("TDB_03",      7,              49,     37,     54,     3,      -1),                                                                                    // credits tab
400                 techroom_buttons("TDB_07",      1,              86,     -1,     -1,     7,      SHIPS_DATA_MODE, REPEAT),                               // prev data entry
401                 techroom_buttons("TDB_08",      1,              317,    -1,     -1,     8,      SHIPS_DATA_MODE, REPEAT),                               // next data entry
402                 techroom_buttons("TDB_09",      1,              406,    -1,     -1,     9,      SHIPS_DATA_MODE, REPEAT),                               // prev data entry
403                 techroom_buttons("TDB_10",      1,              447,    -1,     -1,     10,     SHIPS_DATA_MODE, REPEAT),                       // next data entry
404                 //techroom_buttons("TDB_11",    558,    272,    -1,     -1,     11,     WEAPONS_SPECIES_DATA_MODE),             // prev data entry
405                 //techroom_buttons("TDB_12",    606,    272,    -1,     -1,     12,     WEAPONS_SPECIES_DATA_MODE),             // next data entry
406                 techroom_buttons("TDB_11a",559, 323,    -1,     -1,     11,     SHIPS_DATA_MODE, REPEAT),                       // prev data entry
407                 techroom_buttons("TDB_12a",609, 323,    -1,     -1,     12,     SHIPS_DATA_MODE, REPEAT),                       // next data entry
408                 techroom_buttons("TDB_13",      533,    425,    500,    440,    13,     -1),                                                                            // help
409                 techroom_buttons("TDB_14",      533,    455,    479,    464,    14,     -1),                                                                            // options
410                 techroom_buttons("TDB_15a",571, 425,    588,    413,    15,     -1),                                                                            // exit         
411         }, 
412         {       // GR_1024
413                 techroom_buttons("2_TDB_04",    649,    614,    717,    630,    4,      -1),                                                                            // ship data tab
414                 techroom_buttons("2_TDB_05",    646,    669,    717,    687,    5,      -1),                                                                            // weapons data tab
415                 techroom_buttons("2_TDB_06",    646,    716,    717,    739,    6,      -1),                                                                            // species data tab
416                 techroom_buttons("2_TDB_00",    12,     5,              59,     12,     0,      -1),                                                                            // technical database tab
417                 techroom_buttons("2_TDB_01",    12,     31,     59,     37,     1,      -1),                                                                            // mission simulator tab
418                 techroom_buttons("2_TDB_02",    12,     56,     59,     62,     2,      -1),                                                                            // cutscenes tab
419                 techroom_buttons("2_TDB_03",    12,     81,     59,     88,     3,      -1),                                                                            // credits tab
420                 techroom_buttons("2_TDB_07",    1,              138,    -1,     -1,     7,      SHIPS_DATA_MODE, REPEAT),                       // prev data entry
421                 techroom_buttons("2_TDB_08",    1,              507,    -1,     -1,     8,      SHIPS_DATA_MODE, REPEAT),                       // next data entry
422                 techroom_buttons("2_TDB_09",    1,              649,    -1,     -1,     9,      SHIPS_DATA_MODE, REPEAT),                       // prev data entry
423                 techroom_buttons("2_TDB_10",    1,              716,    -1,     -1,     10,     SHIPS_DATA_MODE, REPEAT),               // next data entry
424                 //techroom_buttons("2_TDB_11",  893,    436,    -1,     -1,     11,     WEAPONS_SPECIES_DATA_MODE),     // prev data entry
425                 //techroom_buttons("2_TDB_12",  970,    436,    -1,     -1,     12,     WEAPONS_SPECIES_DATA_MODE),     // next data entry
426                 techroom_buttons("2_TDB_11a",   895,    518,    -1,     -1,     11,     SHIPS_DATA_MODE, REPEAT),               // prev data entry
427                 techroom_buttons("2_TDB_12a",   974,    518,    -1,     -1,     12,     SHIPS_DATA_MODE, REPEAT),               // next data entry
428                 techroom_buttons("2_TDB_13",    854,    681,    800,    704,    13,     -1),                                                                    // help
429                 techroom_buttons("2_TDB_14",    854,    728,    780,    743,    14,     -1),                                                                    // options
430                 techroom_buttons("2_TDB_15a",   914,    681,    930,    660,    15,     -1),                                                                    // exit         
431         }, 
432 };
433
434 static UI_WINDOW Ui_window;
435 static UI_BUTTON View_window;
436 //static int Background_bitmap;
437 static int Tech_background_bitmap;
438 static int Tab = 0;
439 // static int List_size;
440 static int List_offset;
441 static int Select_tease_line;
442 static int Trackball_mode = 1;
443 static int Trackball_active = 0;
444 static matrix Techroom_ship_orient = IDENTITY_MATRIX;
445 // static int Tech_room_ask_for_cd;
446
447 static int Text_size;
448 static int Text_offset;
449 static int Text_line_size[MAX_TEXT_LINES];
450 static char *Text_lines[MAX_TEXT_LINES];
451
452 static int Cur_entry;                           // this is the current entry selected, using entry indexing
453 static int Cur_entry_index;             // this is the current entry selected, using master list indexing
454 static int Techroom_ship_modelnum;
455 static float Techroom_ship_rot;
456 static UI_BUTTON List_buttons[LIST_BUTTONS_MAX];  // buttons for each line of text in list
457 static int Anim_playing_id = -1;
458 static anim_instance *Cur_anim_instance = NULL;
459 static int Palette_bmp;
460 //static int ShipWin01;
461 //static int ShipWin02;
462 //static int ShipWin03;
463 //static int ShipWin04;
464 static ubyte Palette[768];
465 static char Palette_name[128];
466
467 static int Ships_loaded = 0;
468 static int Weapons_loaded = 0;
469 static int Intel_loaded = 0;
470
471 // out entry data struct & vars
472 typedef struct {
473         int     index;          // index into the master table that its in (ie Ship_info[])
474         char* name;                     // ptr to name string
475         char* desc;                     // ptr to description string
476         anim* animation;        // ptr to the animation
477         int     bitmap;         // bitmap handle
478         int     has_anim;       // flag to indicate the presence of an animation for this item
479 } tech_list_entry;
480
481 static tech_list_entry Ship_list[MAX_SHIP_TYPES];
482 static int Ship_list_size = 0;
483 static tech_list_entry Weapon_list[MAX_WEAPON_TYPES];
484 static int Weapon_list_size = 0;
485 static tech_list_entry Intel_list[MAX_INTEL_ENTRIES];
486 static int Intel_list_size = 0;
487 static tech_list_entry *Current_list;                                                           // points to currently valid display list
488 static int Current_list_size = 0;
489
490
491 // slider stuff
492 static UI_SLIDER2 Tech_slider;
493
494 //XSTR:OFF
495 /*
496 static char *Intel_anim_filenames[MAX_INTEL_ENTRIES] = {
497         "tech_tpilot.ani",
498         "tech_vasudan.ani",
499         "tech_shivan.ani",
500 };
501 */
502 //XSTR:ON
503
504 // Intelligence master data structs (these get inited @ game startup from species.tbl)
505 intel_data Intel_info[MAX_INTEL_ENTRIES];
506 int Intel_info_size = 0;
507
508 // some prototypes to make you happy
509 int techroom_load_ani(anim **animpp, char *name);
510 void tech_common_render();
511 void techroom_start_anim();
512 void tech_scroll_list_up();
513 void tech_scroll_list_down();
514
515
516
517
518 ////////////////////////////////////////////////////
519 // like, functions and stuff
520
521 void techroom_init_desc(char *src, int w)
522 {
523         Text_size = Text_offset = 0;
524         if (!src) {
525                 return;
526         }
527
528         Text_size = split_str(src, w, Text_line_size, Text_lines, MAX_TEXT_LINES);
529         Assert(Text_size >= 0 && Text_size < MAX_TEXT_LINES);
530 }
531
532 void techroom_select_new_entry()
533 {
534         Assert(Current_list != NULL);
535         if (Current_list == NULL) return;
536
537         Cur_entry_index = Current_list[Cur_entry].index;
538
539         // if we are in the ships tab, load the ship model
540         if (Tab == SHIPS_DATA_TAB) {
541                 ship_info *sip = &Ship_info[Cur_entry_index];
542
543 #ifdef MULTIPLAYER_BETA_BUILD
544                 // don't load supercaps in the beta
545                 if((sip->flags & SIF_SUPERCAP) || (sip->flags & SIF_DRYDOCK)){
546                         Techroom_ship_modelnum = -1;
547                 } else {
548                         Techroom_ship_modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
549                 }
550
551                 // page in ship textures properly (takes care of nondimming pixels)
552                 model_page_in_textures(Techroom_ship_modelnum, Cur_entry_index);
553 #else
554                 Techroom_ship_modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
555
556                 // page in ship textures properly (takes care of nondimming pixels)
557                 model_page_in_textures(Techroom_ship_modelnum, Cur_entry_index);
558 #endif
559         } else {
560                 Techroom_ship_modelnum = -1;
561                 Trackball_mode = 0;
562         }
563
564 //      Techroom_ship_rot = PI;
565
566         techroom_init_desc(Current_list[Cur_entry].desc, Tech_desc_coords[gr_screen.res][SHIP_W_COORD]);
567         techroom_start_anim();
568 }
569
570 // write out the current description in the bottom window
571 void techroom_render_desc(int xo, int yo, int h)
572 {
573         int y, z, len, font_height;
574         char line[MAX_TEXT_LINE_LEN + 1];
575
576         font_height = gr_get_font_height();
577
578         y = 0;
579         z = Text_offset;
580         while (y + font_height <= h) {
581                 if (z >= Text_size){
582                         break;
583                 }
584
585                 len = Text_line_size[z];
586                 if (len > MAX_TEXT_LINE_LEN){
587                         len = MAX_TEXT_LINE_LEN;
588                 }
589
590                 strncpy(line, Text_lines[z], len);
591                 line[len] = 0;
592                 gr_string(xo, yo + y, line);
593
594                 y += font_height;
595                 z++;
596         }
597
598         // maybe output 'more' indicator
599         if ( z < Text_size ) {
600                 // can be scrolled down
601                 int more_txt_x = Tech_desc_coords[gr_screen.res][0] + (Tech_desc_coords[gr_screen.res][2]/2) - 10;      // FIXME should move these to constants since they dont move
602                 int more_txt_y = Tech_desc_coords[gr_screen.res][1] + Tech_desc_coords[gr_screen.res][3];                               // located below brief text, centered
603                 int w, h;
604                 gr_get_string_size(&w, &h, XSTR("more", 1469), strlen(XSTR("more", 1469)));
605                 gr_set_color_fast(&Color_black);
606                 gr_rect(more_txt_x-2, more_txt_y, w+3, h);
607                 gr_set_color_fast(&Color_red);
608                 gr_string(more_txt_x, more_txt_y, XSTR("more", 1469));  // base location on the input x and y?
609         }
610
611 }
612
613 // new version of weapons
614 void techroom_weapons_render2(float frametime)
615 {
616         // render common stuff
617         tech_common_render();
618
619         // render the animation
620         {
621                 // JAS: This code is hacked to allow the animation to use all 256 colors
622                 extern int Palman_allow_any_color;
623                 Palman_allow_any_color = 1;
624                 anim_render_all(0, frametime);
625                 Palman_allow_any_color = 0;
626         }
627
628         // if our active item has a bitmap instead of an animation, draw it
629         if((Cur_entry > 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
630                 gr_set_bitmap(Current_list[Cur_entry].bitmap);
631                 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
632         }
633 }
634
635 // renders the stuff common to all 3 tech room tabs
636 void tech_common_render()
637 {
638         char buf[256];
639         int y, z, font_height;
640
641         // render description in its box
642         gr_set_color_fast(&Color_text_normal);
643         techroom_render_desc(Tech_desc_coords[gr_screen.res][SHIP_X_COORD], Tech_desc_coords[gr_screen.res][SHIP_Y_COORD], Tech_desc_coords[gr_screen.res][SHIP_H_COORD]);
644
645         font_height = gr_get_font_height();
646
647         // draw the list of entries
648         y = 0;
649         z = List_offset;
650         while (y + font_height <= Tech_list_coords[gr_screen.res][SHIP_H_COORD]) {
651                 if (z >= Current_list_size) {
652                         break;
653                 }
654
655                 if (z == Cur_entry) {
656                         gr_set_color_fast(&Color_text_selected);
657                 } else if (z == Select_tease_line) {
658                         gr_set_color_fast(&Color_text_subselected);
659                 } else {
660                         gr_set_color_fast(&Color_text_normal);
661                 }
662
663                 strcpy(buf, Current_list[z].name);
664                 if (Lcl_gr) {
665                         lcl_translate_ship_name(buf);
666                 }
667
668                 gr_force_fit_string(buf, 255, Tech_list_coords[gr_screen.res][SHIP_W_COORD]);
669                 gr_string(Tech_list_coords[gr_screen.res][SHIP_X_COORD], Tech_list_coords[gr_screen.res][SHIP_Y_COORD] + y, buf);
670
671                 List_buttons[z - List_offset].update_dimensions(Tech_list_coords[gr_screen.res][SHIP_X_COORD], Tech_list_coords[gr_screen.res][SHIP_Y_COORD] + y, Tech_list_coords[gr_screen.res][SHIP_W_COORD], font_height);
672                 List_buttons[z - List_offset].enable(1);
673
674                 y += font_height;
675                 z++;
676         }
677
678         // disable the rest of the list buttons
679         z -= List_offset;
680         while (z < LIST_BUTTONS_MAX) {
681                 List_buttons[z++].disable();
682         }
683 }
684
685 void techroom_ships_render(float frametime)
686 {
687         // render all the common stuff
688         tech_common_render();
689
690         // now render the trackball ship, which is unique to the ships tab
691         float rev_rate;
692         angles rot_angles, view_angles;
693         int z;
694         ship_info *sip = &Ship_info[Cur_entry_index];
695
696         // get correct revolution rate
697         rev_rate = REVOLUTION_RATE;
698         z = sip->flags;
699         if (z & SIF_BIG_SHIP) {
700                 rev_rate *= 1.7f;
701         }
702         if (z & SIF_HUGE_SHIP) {
703                 rev_rate *= 3.0f;
704         }
705
706         // rotate the ship as much as required for this frame
707         Techroom_ship_rot += PI2 * frametime / rev_rate;
708         while (Techroom_ship_rot > PI2){
709                 Techroom_ship_rot -= PI2;       
710         }
711
712         // turn off fogging
713         gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
714
715         //      reorient ship
716         if (Trackball_active) {
717                 int dx, dy;
718                 matrix mat1, mat2;
719
720                 if (Trackball_active) {
721                         mouse_get_delta(&dx, &dy);
722                         if (dx || dy) {
723                                 vm_trackball(-dx, -dy, &mat1);
724                                 vm_matrix_x_matrix(&mat2, &mat1, &Techroom_ship_orient);
725                                 Techroom_ship_orient = mat2;
726                         }
727                 }
728
729         } else {
730                 // setup stuff needed to render the ship
731                 view_angles.p = -0.6f;
732                 view_angles.b = 0.0f;
733                 view_angles.h = 0.0f;
734                 vm_angles_2_matrix(&Techroom_ship_orient, &view_angles);
735
736                 rot_angles.p = 0.0f;
737                 rot_angles.b = 0.0f;
738                 rot_angles.h = Techroom_ship_rot;
739                 vm_rotate_matrix_by_angles(&Techroom_ship_orient, &rot_angles);
740         }
741
742         gr_set_clip(Tech_ship_display_coords[gr_screen.res][SHIP_X_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_Y_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_W_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_H_COORD]);        
743
744         // render the ship
745 #ifdef MULTIPLAYER_BETA_BUILD
746         if((sip->flags & SIF_SUPERCAP) || (sip->flags & SIF_DRYDOCK)) {
747                 gr_set_color_fast(&Color_bright);
748                 gr_string(Tech_ship_display_coords[gr_screen.res][SHIP_X_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_Y_COORD] + 50, NOX("No soup for you!"));
749         } else {
750                 g3_start_frame(1);
751
752                 g3_set_view_matrix(&sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * 1.3f);
753
754                 // lighting for techroom
755                 light_reset();
756                 vector light_dir = vmd_zero_vector;
757                 light_dir.y = 1.0f;     
758                 light_add_directional(&light_dir, 0.85f, 1.0f, 1.0f, 1.0f);
759                 // light_filter_reset();
760                 light_rotate_all();
761                 // lighting for techroom
762
763                 model_clear_instance(Techroom_ship_modelnum);
764                 model_set_detail_level(0);
765                 model_render(Techroom_ship_modelnum, &Techroom_ship_orient, &vmd_zero_vector, MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER);
766
767                 g3_end_frame();
768         }
769 #else
770         g3_start_frame(1);
771
772         g3_set_view_matrix(&sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * 1.3f);
773
774         // lighting for techroom
775         light_reset();
776         vector light_dir = vmd_zero_vector;
777         light_dir.xyz.y = 1.0f;
778         light_add_directional(&light_dir, 0.85f, 1.0f, 1.0f, 1.0f);
779         // light_filter_reset();
780         light_rotate_all();
781         // lighting for techroom
782
783         model_clear_instance(Techroom_ship_modelnum);
784         model_set_detail_level(0);
785         model_render(Techroom_ship_modelnum, &Techroom_ship_orient, &vmd_zero_vector, MR_LOCK_DETAIL | MR_AUTOCENTER);
786
787         g3_end_frame();
788 #endif
789
790         gr_reset_clip();
791 }
792
793 // select previous entry in current list
794 void tech_prev_entry()
795 {
796         Cur_entry--;
797         if (Cur_entry < 0) {
798                 Cur_entry = Current_list_size - 1;
799
800                 // scroll to end of list
801                 List_offset = Cur_entry - Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() + 1;
802                 if (List_offset < 0) {
803                         // this happens when there are not enough items to scroll
804                         List_offset = 0;
805                 }
806                 Tech_slider.force_currentItem(Tech_slider.get_numberItems());
807         } else {
808                 // maybe adjust list position by 1
809                 if (List_offset > Cur_entry) {
810                         tech_scroll_list_up();
811                         Tech_slider.forceUp();
812                 }
813         }
814
815         techroom_select_new_entry();
816         gamesnd_play_iface(SND_SCROLL);
817 }
818
819 // select next entry in current list
820 void tech_next_entry()
821 {
822         Cur_entry++;
823         if (Cur_entry >= Current_list_size) {
824                 Cur_entry = 0;
825
826                 // scroll to beginning of list
827                 List_offset = 0;
828                 Tech_slider.force_currentItem(Cur_entry);
829         } else {
830                 // maybe adjust list position by 1
831                 if (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() <= Cur_entry) {
832                         tech_scroll_list_down();
833                         Tech_slider.forceDown();
834                 }
835         }
836
837         techroom_select_new_entry();
838         gamesnd_play_iface(SND_SCROLL);
839 }
840
841 void tech_scroll_info_up()
842 {
843         if (Text_offset) {
844                 Text_offset--;
845                 gamesnd_play_iface(SND_SCROLL);
846         } else {
847                 gamesnd_play_iface(SND_GENERAL_FAIL);
848         }
849 }
850
851 void tech_scroll_info_down()
852 {
853         int h;
854
855         if (Tab == SHIPS_DATA_TAB){
856                 h = Tech_desc_coords[gr_screen.res][SHIP_H_COORD];
857         } else {
858                 h = Tech_desc_coords[gr_screen.res][3];
859         }
860
861         if (Text_offset + h / gr_get_font_height() < Text_size) {
862                 Text_offset++;
863                 gamesnd_play_iface(SND_SCROLL);
864         } else {
865                 gamesnd_play_iface(SND_GENERAL_FAIL);
866         }
867 }
868
869 void tech_scroll_list_up()
870 {
871         //int last;
872
873         if (List_offset > 0) {
874                 List_offset--;
875                 //last = List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() - 1;
876                 gamesnd_play_iface(SND_SCROLL);
877         } else {
878                 gamesnd_play_iface(SND_GENERAL_FAIL);
879         }
880 }
881
882 void tech_scroll_list_down()
883 {
884         if (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() < Current_list_size) {
885                 List_offset++;
886                 gamesnd_play_iface(SND_SCROLL);
887         } else {
888                 gamesnd_play_iface(SND_GENERAL_FAIL);
889         }
890 }
891
892 // this doesnt do a damn thing...
893 void tech_ship_scroll_capture()
894 {
895         techroom_select_new_entry();
896 }
897
898
899 // this is obsolete - see techroom_weapons_render2(...)
900 void techroom_weapons_render(float frametime)
901 {
902         gr_set_color_fast(&Color_text_normal);
903         techroom_render_desc(Tech_desc_coords[gr_screen.res][0], Tech_desc_coords[gr_screen.res][1], Tech_desc_coords[gr_screen.res][3]);
904
905         {
906                 // JAS: This code is hacked to allow the animation to use all 256 colors
907                 extern int Palman_allow_any_color;
908                 Palman_allow_any_color = 1;
909                 anim_render_all(0, frametime);
910                 Palman_allow_any_color = 0;
911         }
912
913         // if our active item has a bitmap instead of an animation, draw it
914         if((Cur_entry >= 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
915                 gr_set_bitmap(Current_list[Cur_entry].bitmap);
916                 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
917         }
918 }
919
920 void techroom_intel_render(float frametime)
921 {
922         tech_common_render();
923
924         {
925                 // JAS: This code is hacked to allow the animation to use all 256 colors
926                 extern int Palman_allow_any_color;
927                 Palman_allow_any_color = 1;
928                 anim_render_all(0, frametime);
929                 Palman_allow_any_color = 0;
930         }
931
932         // if our active item has a bitmap instead of an animation, draw it
933         if((Cur_entry >= 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
934                 gr_set_bitmap(Current_list[Cur_entry].bitmap);
935                 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
936         }
937 }
938
939 void techroom_stop_anim(int id)
940 {
941         if (Cur_anim_instance && (id != Anim_playing_id)) {
942                 anim_stop_playing(Cur_anim_instance);
943                 Cur_anim_instance = NULL;
944         }
945 }
946
947 void techroom_start_anim()
948 {
949         int id;
950         anim *animp;
951         anim_play_struct aps;
952
953         if (Cur_entry < 0) {
954                 techroom_stop_anim(-1);
955                 Anim_playing_id = -1;
956         }
957
958         if (Tab == WEAPONS_DATA_TAB) {
959                 id = Cur_entry;
960         } else {
961                 id = Cur_entry + 2000;                                          // this offset is arbitrary?
962         }
963
964         techroom_stop_anim(id);
965
966         // if we actually have an animation
967         if(Current_list[Cur_entry].animation != NULL){
968                 animp = Current_list[Cur_entry].animation;      
969
970                 if (id != Anim_playing_id) {
971                         Anim_playing_id = -1;
972                         if (animp) {
973                                 anim_play_init(&aps, animp, Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
974                                 aps.looped = 1;
975                                 Cur_anim_instance = anim_play(&aps);
976                                 Anim_playing_id = id;
977                         }
978
979                         if (animp) {
980                                 memcpy(Palette, animp->palette, 384);
981                                 gr_set_palette(animp->name, Palette, 1);
982                         }
983                 }
984         }
985 }
986
987
988 void techroom_change_tab(int num)
989 {
990         int i, multi = 0, mask, font_height, max_num_entries_viewable;  
991
992         Tab = num;
993         // Assert(Current_list_size >= 0);
994         List_offset = 0;
995         Cur_entry = 0;
996         multi = Player->flags & PLAYER_FLAGS_IS_MULTI;
997
998         for (i=0; i<LIST_BUTTONS_MAX; i++){
999                 List_buttons[i].disable();
1000         }
1001
1002         // disable some stuff in multiplayer
1003         if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
1004                 Buttons[gr_screen.res][SIMULATOR_TAB].button.disable();
1005                 Buttons[gr_screen.res][CUTSCENES_TAB].button.disable();
1006         }
1007
1008         switch (Tab) {
1009                 case SHIPS_DATA_TAB:
1010                         mask = multi ? SIF_IN_TECH_DATABASE_M : SIF_IN_TECH_DATABASE;
1011                         
1012                         // load ship info if necessary
1013                         if (Ships_loaded == 0) {
1014                                 Ship_list_size = 0;
1015                                 for (i=0; i<Num_ship_types; i++) {
1016                                         if (Ship_info[i].flags & mask) {
1017                                                 // this ship should be displayed, fill out the entry struct
1018                                                 Ship_list[Ship_list_size].bitmap = -1;
1019                                                 Ship_list[Ship_list_size].index = i;
1020                                                 Ship_list[Ship_list_size].animation = NULL;                     // no anim for ships
1021                                                 Ship_list[Ship_list_size].has_anim = 0;                         // no anim for ships
1022                                                 Ship_list[Ship_list_size].name = Ship_info[i].name;
1023                                                 Ship_list[Ship_list_size].desc = Ship_info[i].tech_desc;
1024                                                 Ship_list_size++;
1025                                         }                               
1026                                 }
1027                                 Ships_loaded = 1;
1028                         }
1029
1030                         Current_list = Ship_list;
1031                         Current_list_size = Ship_list_size;
1032
1033                         font_height = gr_get_font_height();
1034                         max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1035                         Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1036
1037                         // no anim to start here
1038                         break;
1039
1040                 case WEAPONS_DATA_TAB:
1041                                 
1042                         // load weapon info & anims if necessary
1043                         if (Weapons_loaded == 0) {
1044                                 Weapon_list_size = 0;
1045                                 mask = multi ? WIF_PLAYER_ALLOWED : WIF_IN_TECH_DATABASE;
1046
1047                                 for (i=0; i<MAX_WEAPON_TYPES; i++) {
1048                                         if (Weapon_info[i].wi_flags & mask) { 
1049                                                 // note: hack here to exclude dogfight weapons -- dont put weapon in if it has same description as pvs weapon
1050                                                 if ((Weapon_list_size > 0) && (!strcmp(Weapon_info[i].tech_desc, Weapon_list[Weapon_list_size-1].desc))) {
1051                                                         continue;
1052                                                 }
1053
1054                                                 // we have a weapon that should be in the tech db, so fill out the entry struct
1055                                                 Weapon_list[Weapon_list_size].index = i;
1056                                                 Weapon_list[Weapon_list_size].desc = Weapon_info[i].tech_desc;
1057                                                 Weapon_list[Weapon_list_size].has_anim = 1;
1058                                                 Weapon_list[Weapon_list_size].name = Weapon_info[i].tech_title;
1059                                                 Weapon_list[Weapon_list_size].bitmap = -1;
1060                                                 if (Weapon_list[Weapon_list_size].name[0] == 0) {
1061                                                         Weapon_list[Weapon_list_size].name = Weapon_info[i].name;
1062                                                 }
1063
1064                                                 // load the weapon animation
1065                                                 if(!techroom_load_ani(&Weapon_list[Weapon_list_size].animation, Weapon_info[i].tech_anim_filename)){
1066                                                         Weapon_list[Weapon_list_size].has_anim = 0;
1067                                                         Weapon_list[Weapon_list_size].animation = NULL;
1068
1069                                                         // hmm. try a bitmap instead
1070                                                         Weapon_list[Weapon_list_size].bitmap = bm_load(Weapon_info[i].tech_anim_filename);
1071                                                 }                                               
1072
1073                                                 Weapon_list_size++;
1074                                         }                               
1075                                 }
1076
1077                                 Weapons_loaded = 1;
1078                         }
1079
1080                         Current_list = Weapon_list;
1081                         Current_list_size = Weapon_list_size;
1082
1083                         font_height = gr_get_font_height();
1084                         max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1085                         Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1086
1087                         techroom_start_anim();
1088                         break;
1089
1090                 case INTEL_DATA_TAB:
1091
1092                         // load intel if necessary
1093                         if ( Intel_loaded == 0 ) {
1094                                 // now populate the entry structs
1095                                 Intel_list_size = 0;
1096                                 for (i=0; i<Intel_info_size; i++) {
1097
1098                                         if (Intel_info[i].in_tech_db != 0) {
1099                                                 // leave option for no animation if string == "none"
1100                                                 if (!strcmp(Intel_info[i].anim_filename, "none")) {
1101                                                         Intel_list[Intel_list_size].has_anim = 0;
1102                                                         Intel_list[Intel_list_size].animation = NULL;
1103                                                 } else {
1104                                                         // try and load as an animation
1105                                                         Intel_list[Intel_list_size].has_anim = 0;
1106                                                         Intel_list[Intel_list_size].bitmap = -1;
1107                                                         if(techroom_load_ani(&Intel_list[Intel_list_size].animation, Intel_info[i].anim_filename)){
1108                                                                 Intel_list[Intel_list_size].has_anim = 1;                                                       
1109                                                         } else {
1110                                                                 Intel_list[Intel_list_size].bitmap = bm_load(Intel_info[i].anim_filename);
1111                                                         }
1112                                                 }
1113
1114                                                 Intel_list[Intel_list_size].desc = Intel_info[i].desc;
1115                                                 Intel_list[Intel_list_size].index = i;
1116                                                 Intel_list[Intel_list_size].name = Intel_info[i].name;
1117                                                 Intel_list_size++;
1118                                         }
1119                                 }       
1120                                 Intel_loaded = 1;
1121                         }
1122
1123                         // index lookup on intel is a pretty pointless, but it keeps everything 
1124                         // consistent and doesnt really hurt anything
1125                         Current_list = Intel_list;
1126                         Current_list_size = Intel_list_size;
1127
1128                         font_height = gr_get_font_height();
1129                         max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1130                         Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1131
1132                         techroom_start_anim();
1133                         break;
1134         }
1135
1136         // reset the entry
1137         Cur_entry = 0;
1138         techroom_select_new_entry();
1139
1140 }
1141
1142 int techroom_button_pressed(int num)
1143 {
1144         switch (num) {
1145                 case SHIPS_DATA_TAB:
1146                 case WEAPONS_DATA_TAB:
1147                 case INTEL_DATA_TAB:
1148                         techroom_change_tab(num);
1149                         break;
1150
1151                 case SIMULATOR_TAB:
1152 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1153                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1154                         gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
1155                         return 1;
1156 #else
1157                         return 0;
1158 #endif
1159
1160                 case CUTSCENES_TAB:
1161 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1162                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1163                         gameseq_post_event(GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN);
1164                         return 1;
1165 #else
1166                         return 0;
1167 #endif
1168
1169                 case CREDITS_TAB:
1170 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1171                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1172                         gameseq_post_event(GS_EVENT_CREDITS);
1173                         return 1;
1174 #else 
1175                         return 0;
1176 #endif
1177
1178                 case PREV_ENTRY_BUTTON:
1179                         tech_prev_entry();
1180                         break;
1181
1182                 case NEXT_ENTRY_BUTTON:
1183                         tech_next_entry();
1184                         break;
1185
1186                 case SCROLL_LIST_UP:
1187                         tech_scroll_list_up();
1188                         Tech_slider.forceUp();
1189                         break;
1190
1191                 case SCROLL_LIST_DOWN:
1192                         tech_scroll_list_down();
1193                         Tech_slider.forceDown();
1194                         break;
1195
1196                 case SCROLL_INFO_UP:
1197                         tech_scroll_info_up();
1198                         break;
1199
1200                 case SCROLL_INFO_DOWN:
1201                         tech_scroll_info_down();
1202                         break;
1203
1204                 case HELP_BUTTON:
1205                         launch_context_help();
1206                         gamesnd_play_iface(SND_HELP_PRESSED);
1207                         break;
1208
1209                 case OPTIONS_BUTTON:
1210                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1211                         gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1212                         break;
1213
1214                 case EXIT_BUTTON:
1215                         gamesnd_play_iface(SND_COMMIT_PRESSED);
1216                         gameseq_post_event(GS_EVENT_MAIN_MENU);
1217                         break;
1218         }
1219
1220         return 0;
1221 }
1222
1223 int techroom_load_ani(anim **animpp, char *name)
1224 {
1225         int load_attempts = 0;
1226         char anim_filename[64] = "2_";
1227
1228         // hi-res support
1229         // (i dont think there are any hi-res anims for these tho)
1230         if (gr_screen.res == GR_1024) {
1231                 strcat(anim_filename, name);
1232         } else {
1233                 strcpy(anim_filename, name);
1234         }
1235
1236         while(1) {
1237                 if ( load_attempts++ > 5 ) {
1238                         // Tech_room_ask_for_cd = 0;
1239                         return 0;
1240                 }
1241
1242                 *animpp = anim_load(anim_filename, 1);
1243                 if ( *animpp ) {
1244                         return 1;
1245                 } else if (gr_screen.res == GR_1024) {
1246                         // try to load low-res version if hi-res failed
1247                         *animpp = anim_load(name, 1);
1248                         if (*animpp) {
1249                                 return 1;
1250                         }
1251                 }
1252
1253                 // couldn't load animation, ask user to insert CD (if necessary)
1254                 // if ( Tech_room_ask_for_cd ) {
1255                         // if ( game_do_cd_check() == 0 ) {
1256                                 // Tech_room_ask_for_cd = 0;
1257                                 // break;
1258                         // }
1259                 // }
1260         }
1261
1262         // bogus
1263         return 0;
1264 }
1265
1266
1267 void techroom_intel_init()
1268 {
1269         int rval;
1270         static int inited = 0;
1271
1272         // open localization
1273         lcl_ext_open();
1274
1275         if (!inited) {
1276                 if ((rval = setjmp(parse_abort)) != 0) {
1277                         // close localization
1278                         lcl_ext_close();
1279
1280                         return;
1281                 } else {
1282                         read_file_text("species.tbl");
1283                         reset_parse();
1284
1285                         Intel_info_size = 0;
1286
1287                         while (optional_string("$Entry:")) {
1288                                 Assert(Intel_info_size < MAX_INTEL_ENTRIES);
1289                                 if (Intel_info_size >= MAX_INTEL_ENTRIES) break;
1290
1291                                 required_string("$Name:");
1292                                 stuff_string(Intel_info[Intel_info_size].name, F_NAME, NULL, 32);
1293                                 required_string("$Anim:");
1294                                 stuff_string(Intel_info[Intel_info_size].anim_filename, F_NAME, NULL, 32);
1295                                 required_string("$AlwaysInTechRoom:");
1296                                 stuff_int(&Intel_info[Intel_info_size].in_tech_db);
1297                                 required_string("$Description:");
1298                                 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1299
1300
1301                                 Intel_info_size++;
1302                         }
1303                         inited = 1;
1304                 }
1305         }
1306
1307         // close localization
1308         lcl_ext_close();
1309 }
1310
1311 void techroom_init()
1312 {
1313         int i, idx;
1314         techroom_buttons *b;
1315
1316         gr_reset_clip();
1317         gr_clear();
1318         Mouse_hidden++;
1319         gr_flip();
1320         Mouse_hidden--;
1321
1322         Ships_loaded = 0;
1323         Weapons_loaded = 0;
1324         Intel_loaded = 0;
1325
1326         // Tech_room_ask_for_cd = 1;
1327
1328         // backup and bash detail level stuff
1329         Tech_detail_backup = Detail.detail_distance;
1330         Detail.detail_distance = MAX_DETAIL_LEVEL;
1331         Tech_texture_backup = Detail.hardware_textures;
1332         Detail.hardware_textures = MAX_DETAIL_LEVEL;
1333
1334         /*
1335         Palette_bmp = bm_load("TechDataPalette");
1336         Assert(Palette_bmp);
1337         bm_get_palette(Palette_bmp, Palette, Palette_name);  // get the palette for this bitmap
1338         gr_set_palette(Palette_name, Palette, 1);
1339         */
1340
1341         // unflag fullneb 
1342         The_mission.flags &= ~MISSION_FLAG_FULLNEB;
1343
1344         // set up UI stuff
1345         Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1346         Ui_window.set_mask_bmap(Tech_mask_filename[gr_screen.res]);
1347
1348         Tech_background_bitmap = bm_load(Tech_background_filename[gr_screen.res]);
1349         if (Tech_background_bitmap < 0) {
1350                 // failed to load bitmap, not a good thing
1351                 Int3();
1352         }
1353
1354         for (i=0; i<NUM_BUTTONS; i++) {
1355                 b = &Buttons[gr_screen.res][i];
1356
1357                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1358                 // set up callback for when a mouse first goes over a button
1359                 if (b->filename) {
1360                         b->button.set_bmaps(b->filename);
1361 //                      if ( !(b->flags & NO_MOUSE_OVER_SOUND) ) {
1362                                 b->button.set_highlight_action(common_play_highlight_sound);
1363 //                      }
1364
1365                 } else {
1366                         b->button.hide();
1367                 }
1368
1369                 b->button.link_hotspot(b->hotspot);
1370         }
1371
1372         // common tab button text
1373         Ui_window.add_XSTR("Technical Database", 1055, Buttons[gr_screen.res][TECH_DATABASE_TAB].xt,  Buttons[gr_screen.res][TECH_DATABASE_TAB].yt, &Buttons[gr_screen.res][TECH_DATABASE_TAB].button, UI_XSTR_COLOR_GREEN);
1374         Ui_window.add_XSTR("Mission Simulator", 1056, Buttons[gr_screen.res][SIMULATOR_TAB].xt,  Buttons[gr_screen.res][SIMULATOR_TAB].yt, &Buttons[gr_screen.res][SIMULATOR_TAB].button, UI_XSTR_COLOR_GREEN);
1375         Ui_window.add_XSTR("Cutscenes", 1057, Buttons[gr_screen.res][CUTSCENES_TAB].xt,  Buttons[gr_screen.res][CUTSCENES_TAB].yt, &Buttons[gr_screen.res][CUTSCENES_TAB].button, UI_XSTR_COLOR_GREEN);
1376         Ui_window.add_XSTR("Credits", 1058, Buttons[gr_screen.res][CREDITS_TAB].xt,  Buttons[gr_screen.res][CREDITS_TAB].yt, &Buttons[gr_screen.res][CREDITS_TAB].button, UI_XSTR_COLOR_GREEN);
1377
1378         // common ship/weapon/intel text
1379         Ui_window.add_XSTR("Ships", 293, Buttons[gr_screen.res][SHIPS_DATA_TAB].xt,  Buttons[gr_screen.res][SHIPS_DATA_TAB].yt, &Buttons[gr_screen.res][SHIPS_DATA_TAB].button, UI_XSTR_COLOR_GREEN);
1380         Ui_window.add_XSTR("Weapons", 1553, Buttons[gr_screen.res][WEAPONS_DATA_TAB].xt,  Buttons[gr_screen.res][WEAPONS_DATA_TAB].yt, &Buttons[gr_screen.res][WEAPONS_DATA_TAB].button, UI_XSTR_COLOR_GREEN);
1381         Ui_window.add_XSTR("Intelligence", 1066, Buttons[gr_screen.res][INTEL_DATA_TAB].xt,  Buttons[gr_screen.res][INTEL_DATA_TAB].yt, &Buttons[gr_screen.res][INTEL_DATA_TAB].button, UI_XSTR_COLOR_GREEN);
1382
1383         // common help/options/commit text
1384
1385         // NK: removed these two text labels on Tech screen update 4/26/99
1386 //      Ui_window.add_XSTR("Help", 928, Buttons[gr_screen.res][HELP_BUTTON].xt,  Buttons[gr_screen.res][HELP_BUTTON].yt, &Buttons[gr_screen.res][HELP_BUTTON].button, UI_XSTR_COLOR_GREEN);
1387 //      Ui_window.add_XSTR("Options", 1036, Buttons[gr_screen.res][OPTIONS_BUTTON].xt,  Buttons[gr_screen.res][OPTIONS_BUTTON].yt, &Buttons[gr_screen.res][OPTIONS_BUTTON].button, UI_XSTR_COLOR_GREEN);                
1388         Ui_window.add_XSTR("Exit", 1418, Buttons[gr_screen.res][EXIT_BUTTON].xt,  Buttons[gr_screen.res][EXIT_BUTTON].yt, &Buttons[gr_screen.res][EXIT_BUTTON].button, UI_XSTR_COLOR_PINK);             
1389
1390         if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
1391                 Buttons[gr_screen.res][SIMULATOR_TAB].button.disable();
1392                 Buttons[gr_screen.res][CUTSCENES_TAB].button.disable();
1393         }
1394
1395         // set some hotkeys
1396         Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.set_hotkey(KEY_LEFT);
1397         Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.set_hotkey(KEY_RIGHT);
1398         Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(KEY_UP);
1399         Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(KEY_DOWN);
1400
1401
1402         for (i=0; i<LIST_BUTTONS_MAX; i++) {
1403                 List_buttons[i].create(&Ui_window, "", 0, 0, 60, 30, 0, 1);
1404                 List_buttons[i].hide();
1405                 List_buttons[i].disable();
1406         }
1407
1408         View_window.create(&Ui_window, "", Tech_ship_display_coords[gr_screen.res][SHIP_X_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_Y_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_W_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_H_COORD], 1, 1);
1409         View_window.hide();
1410
1411         /*
1412         ShipWin01 = bm_load(NOX("ShipWin01"));
1413         ShipWin02 = bm_load(NOX("ShipWin02"));
1414         ShipWin03 = bm_load(NOX("ShipWin03"));
1415         ShipWin04 = bm_load(NOX("ShipWin04"));
1416         */
1417
1418         Buttons[gr_screen.res][HELP_BUTTON].button.set_hotkey(KEY_F1);
1419         Buttons[gr_screen.res][EXIT_BUTTON].button.set_hotkey(KEY_CTRLED | KEY_ENTER);
1420         Buttons[gr_screen.res][SCROLL_LIST_UP].button.set_hotkey(KEY_PAGEUP);
1421         Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.set_hotkey(KEY_PAGEDOWN);
1422
1423         // init help overlay states
1424         help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
1425
1426         // setup slider
1427         Tech_slider.create(&Ui_window, Tech_slider_coords[gr_screen.res][SHIP_X_COORD], Tech_slider_coords[gr_screen.res][SHIP_Y_COORD], Tech_slider_coords[gr_screen.res][SHIP_W_COORD], Tech_slider_coords[gr_screen.res][SHIP_H_COORD], Num_ship_types, Tech_slider_filename[gr_screen.res], &tech_scroll_list_up, &tech_scroll_list_down, &tech_ship_scroll_capture);
1428
1429         Cur_anim_instance = NULL;
1430
1431         // zero weapon and intel anim/bitmap stuff
1432         for(idx=0; idx<MAX_WEAPON_TYPES; idx++){
1433                 Weapon_list[idx].animation = NULL;
1434                 Weapon_list[idx].bitmap = -1;
1435         }
1436         for(idx=0; idx<MAX_INTEL_ENTRIES; idx++){
1437                 Intel_list[idx].animation = NULL;
1438                 Intel_list[idx].bitmap = -1;
1439         }
1440
1441         Anim_playing_id = -1;
1442         techroom_change_tab(Tab);
1443 }
1444
1445 void techroom_close()
1446 {
1447         int i;
1448
1449         techroom_stop_anim(-1);
1450         for (i=0; i<MAX_WEAPON_TYPES; i++) {
1451                 if ( Weapon_list[i].animation ) {
1452                         anim_free(Weapon_list[i].animation);
1453                         Weapon_list[i].animation = NULL;
1454                 }
1455                 if( Weapon_list[i].bitmap >= 0 ){
1456                         bm_unload(Weapon_list[i].bitmap);
1457                         Weapon_list[i].bitmap = -1;
1458                 }
1459         }
1460
1461         for (i=0; i<MAX_INTEL_ENTRIES; i++){
1462                 if (Intel_list[i].animation != NULL) {
1463                         anim_free(Intel_list[i].animation);
1464                         Intel_list[i].animation = NULL;
1465                 }
1466                 if( Intel_list[i].bitmap >= 0 ){
1467                         bm_unload(Intel_list[i].bitmap);
1468                         Intel_list[i].bitmap = -1;
1469                 }
1470         }
1471
1472         Ships_loaded = 0;
1473         Weapons_loaded = 0;
1474         Intel_loaded = 0;
1475
1476         /*
1477         if (ShipWin01){
1478                 bm_unload(ShipWin01);
1479         }
1480         if (ShipWin02){
1481                 bm_unload(ShipWin02);
1482         }
1483         if (ShipWin03){
1484                 bm_unload(ShipWin03);
1485         }
1486         if (ShipWin04){
1487                 bm_unload(ShipWin04);
1488         }
1489         */
1490
1491         if (Tech_background_bitmap) {
1492                 bm_unload(Tech_background_bitmap);
1493         }
1494
1495         Ui_window.destroy();
1496         common_free_interface_palette();                // restore game palette
1497         if (Palette_bmp){
1498                 bm_unload(Palette_bmp);
1499         }
1500
1501         // restore detail settings
1502         Detail.detail_distance = Tech_detail_backup;
1503         Detail.hardware_textures = Tech_texture_backup;
1504 }
1505
1506 void techroom_do_frame(float frametime)
1507 {
1508         int i, k;       
1509
1510         // turn off controls when overlay is on
1511         if ( help_overlay_active(TECH_ROOM_OVERLAY) ) {
1512                 Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
1513                 Ui_window.set_ignore_gadgets(1);
1514         }
1515
1516         // turn off controls in trackball mode
1517         if (Trackball_active) {
1518                 Ui_window.set_ignore_gadgets(1);
1519         } else {
1520                 Ui_window.set_ignore_gadgets(0);
1521         }
1522
1523         k = Ui_window.process() & ~KEY_DEBUGGED;
1524
1525         if ( (k > 0) || B1_JUST_RELEASED ) {
1526                 if ( help_overlay_active(TECH_ROOM_OVERLAY) ) {
1527                         help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
1528                         Ui_window.set_ignore_gadgets(0);
1529                         k = 0;
1530                 }
1531         }
1532
1533         if ( !help_overlay_active(TECH_ROOM_OVERLAY) ) {
1534                 Ui_window.set_ignore_gadgets(0);
1535         }
1536
1537         switch (k) {
1538                 case KEY_SHIFTED | KEY_TAB:  // activate previous tab
1539                         i = Tab - 1;
1540                         if (i < 0) {
1541                                 i = NUM_TABS - 1;
1542                         }
1543
1544                         techroom_change_tab(i);
1545                         break;
1546
1547                 case KEY_TAB:  // activate next tab
1548                         i = Tab + 1;
1549                         if (i >= NUM_TABS) {
1550                                 i = 0;
1551                         }
1552
1553                         techroom_change_tab(i);
1554                         break;
1555
1556                 case KEY_CTRLED | KEY_DOWN:
1557                         if ( !(Player->flags & PLAYER_FLAGS_IS_MULTI) ) {
1558                                 techroom_button_pressed(SIMULATOR_TAB);
1559                                 break;
1560                         }
1561                         // fall through
1562
1563                 case KEY_CTRLED | KEY_UP:
1564                         techroom_button_pressed(CREDITS_TAB);
1565                         break;
1566 /*
1567                 case KEY_UP:
1568                         tech_prev_entry();
1569                         break;
1570
1571                 case KEY_DOWN:
1572                         tech_next_entry();
1573                         break;
1574 */
1575                 case KEY_CTRLED | KEY_ENTER:
1576                 case KEY_ESC:
1577                         gameseq_post_event(GS_EVENT_MAIN_MENU);
1578                         break;
1579         }       
1580
1581         // check ship model window for activity
1582         if (View_window.pressed()) {
1583                 Trackball_active = 1;
1584                 Trackball_mode = 1;
1585         }
1586         if (B1_RELEASED) {
1587                 Trackball_active = 0;
1588         }
1589
1590         // check all da buttons
1591         for (i=0; i<NUM_BUTTONS; i++) {
1592                 if (Buttons[gr_screen.res][i].button.pressed()) {
1593                         if (techroom_button_pressed(i)) {
1594                                 return;
1595                         }
1596                 }
1597         }
1598
1599         // check for mouseovers/clicks on the selection list
1600         Select_tease_line = -1;
1601         for (i=0; i<LIST_BUTTONS_MAX; i++) {
1602                 if (List_buttons[i].is_mouse_on()) {
1603                         Select_tease_line = i + List_offset;
1604                 }
1605         
1606                 if (List_buttons[i].pressed()) {
1607                         Cur_entry = i + List_offset;
1608                         gamesnd_play_iface(SND_USER_SELECT);
1609                         techroom_select_new_entry();
1610                 }
1611         }
1612
1613         // clear & draw bg bitmap
1614         GR_MAYBE_CLEAR_RES(Tech_background_bitmap);
1615         if (Tech_background_bitmap >= 0) {
1616                 gr_set_bitmap(Tech_background_bitmap);
1617                 gr_bitmap(0, 0);
1618         }
1619
1620         // render
1621         switch (Tab) {
1622                 case SHIPS_DATA_TAB:
1623                         techroom_ships_render(frametime);
1624
1625                         /*
1626                         if (ShipWin01) {
1627                                 gr_set_bitmap(ShipWin01);
1628                                 gr_bitmap(223, 104);
1629                         }
1630
1631                         if (ShipWin02) {
1632                                 gr_set_bitmap(ShipWin02);
1633                                 gr_bitmap(621, 124);
1634                         }
1635
1636                         if (ShipWin03) {
1637                                 gr_set_bitmap(ShipWin03);
1638                                 gr_bitmap(223, 338);
1639                         }
1640
1641                         if (ShipWin04) {
1642                                 gr_set_bitmap(ShipWin04);
1643                                 gr_bitmap(218, 124);
1644                         }
1645                         */
1646
1647                         break;
1648
1649                 case WEAPONS_DATA_TAB:
1650                         techroom_weapons_render2(frametime);
1651                         break;
1652
1653                 case INTEL_DATA_TAB:
1654                         techroom_intel_render(frametime);
1655                         break;
1656         }
1657
1658         Ui_window.draw();
1659
1660         for (i=TECH_DATABASE_TAB; i<=CREDITS_TAB; i++) {
1661                 if (Buttons[gr_screen.res][i].button.button_down()) {
1662                         break;
1663                 }
1664         }
1665         if (i > CREDITS_TAB) {
1666                 Buttons[gr_screen.res][TECH_DATABASE_TAB].button.draw_forced(2);
1667         }
1668
1669         for (i=0; i<NUM_TABS; i++){
1670                 if (Buttons[gr_screen.res][i].button.button_down()){
1671                         break;
1672                 }
1673         }
1674         if (i == NUM_TABS){
1675                 Buttons[gr_screen.res][Tab].button.draw_forced(2);
1676         }
1677
1678         // blit help overlay if active
1679         help_overlay_maybe_blit(TECH_ROOM_OVERLAY);
1680
1681         gr_flip();
1682 }
1683