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