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