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