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