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