2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/MenuUI/TechMenu.cpp $
15 * C module that contains functions to drive the Tech Menu user interface
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
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
29 * Revision 1.8 2004/09/20 01:31:44 theoddone33
32 * Revision 1.7 2003/08/03 16:10:29 taylor
33 * cleanup; compile warning fixes
35 * Revision 1.6 2003/05/25 02:30:42 taylor
38 * Revision 1.5 2002/06/17 06:33:09 relnev
39 * ryan's struct patch for gcc 2.95
41 * Revision 1.4 2002/06/09 04:41:22 relnev
42 * added copyright header
44 * Revision 1.3 2002/06/02 04:26:34 relnev
47 * Revision 1.2 2002/05/07 03:16:46 theoddone33
48 * The Great Newline Fix
50 * Revision 1.1.1.1 2002/05/03 03:28:09 root
54 * 43 11/02/99 3:22p Jefff
55 * translate ship names in tech room
57 * 42 10/25/99 5:47p Jefff
58 * reassigned some xstr ids
60 * 41 10/12/99 4:50p Jefff
62 * 40 9/08/99 11:09a Dave
63 * Use stills for intel and weapon stuff in the techroom if animations
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
71 * 38 9/03/99 11:19a Jefff
72 * fixed double render of intel descriptions
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
80 * 36 9/01/99 5:12p Jefff
81 * Fixed bad scroll bug
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
88 * 34 8/24/99 8:55p Dave
89 * Make sure nondimming pixels work properly in tech menu.
91 * 33 8/24/99 10:47a Jefff
92 * tech room weapon anims. added tech anim field to weapons.tbl
94 * 32 8/10/99 5:29p Jefff
95 * use new tech_title field in weapons array
97 * 31 8/10/99 3:45p Jefff
98 * Put the smack down on the tech room. Its all new, but tastefully done.
100 * 30 8/09/99 5:53p Jefff
102 * 29 8/02/99 10:27a Jefff
103 * removed a warning for the time being
105 * 28 8/02/99 10:13a Jefff
106 * started scrubbing, waiting till after demo to continue
108 * 27 7/28/99 1:02p Jefff
109 * Changed "Species" to "Intelligence" -- also changed in strings.tbl.
111 * 26 7/26/99 4:33p Jordonr
112 * Don't need techroom palette
114 * 25 7/20/99 1:49p Dave
115 * Peter Drake build. Fixed some release build warnings.
117 * 24 7/19/99 2:13p Dave
118 * Added some new strings for Heiko.
120 * 23 7/14/99 9:42a Dave
121 * Put in clear_color debug function. Put in base for 3dnow stuff / P3
124 * 22 6/16/99 4:06p Dave
125 * New pilot info popup. Added new draw-bitmap-as-poly function.
127 * 21 5/09/99 8:57p Dave
128 * Final E3 build preparations.
130 * 20 5/09/99 6:00p Dave
131 * Lots of cool new effects. E3 build tweaks.
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
137 * 18 4/26/99 5:05p Neilk
138 * updated to new artwork, added slider support
140 * 17 4/25/99 3:02p Dave
141 * Build defines for the E3 build.
143 * 16 4/23/99 12:01p Johnson
144 * Added SIF_HUGE_SHIP
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.
150 * 14 4/08/99 2:10a Dave
151 * Numerous bug fixes for the beta. Added builtin mission info for the
154 * 13 2/19/99 11:42a Dave
155 * Put in model rendering autocentering.
157 * 12 2/01/99 5:55p Dave
158 * Removed the idea of explicit bitmaps for buttons. Fixed text
159 * highlighting for disabled gadgets.
161 * 11 1/30/99 5:08p Dave
162 * More new hi-res stuff.Support for nice D3D textures.
164 * 10 1/29/99 3:56p Neilk
165 * Converted tech_infos screens to multiresolution
167 * 9 1/29/99 3:54p Neilk
169 * 8 1/29/99 12:47a Dave
170 * Put in sounds for beam weapon. A bunch of interface screens (tech
173 * 7 11/30/98 1:07p Dave
174 * 16 bit conversion, first run.
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.
180 * 5 10/16/98 9:40a Andsager
181 * Remove ".h" files from model.h
183 * 4 10/13/98 2:47p Andsager
184 * Remove reference to Tech_shivan_species_avail
186 * 3 10/13/98 9:28a Dave
187 * Started neatening up freespace.h. Many variables renamed and
188 * reorganized. Added AlphaColors.[h,cpp]
190 * 2 10/07/98 10:53a Dave
193 * 1 10/07/98 10:49a Dave
195 * 67 9/21/98 10:02p Dave
196 * Last minute changes to techroom weapon/ship/species stuff.
198 * 66 9/07/98 2:49p Dan
199 * Removed spurious SDL_assert
201 * 65 7/06/98 2:42p Hoffoss
202 * Fixed bug with weapons shown in tech database.
204 * 64 6/10/98 11:48a Lawrance
205 * fix bug with trying to free NULL anims
207 * 63 6/05/98 9:54a Lawrance
210 * 62 6/01/98 11:43a John
211 * JAS & MK: Classified all strings for localization.
213 * 61 5/26/98 11:10a Lawrance
214 * Fix bug where window controls get disabled when F1 pressed twice
216 * 60 5/23/98 10:38p Lawrance
217 * Avoid doing a cfile refresh when running debug
219 * 59 5/23/98 6:49p Lawrance
220 * Fix problems with refreshing the file list when a CD is inserted
222 * 58 5/22/98 11:15a Lawrance
223 * Tweak how CD gets asked for
225 * 57 5/22/98 1:06a Hoffoss
226 * Made Fred not use OLE.
228 * 56 5/21/98 6:57p Lawrance
229 * Only ask for the CD once
231 * 55 5/21/98 12:46a Hoffoss
232 * Made text offset reset when new description is loaded.
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.
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).
242 * 52 5/20/98 2:11p Hoffoss
243 * Fixed some species description problems.
245 * 51 5/18/98 6:45p Hoffoss
246 * Added species descriptions to species database in techroom.
248 * 50 5/17/98 6:13p Hoffoss
249 * Fixed scrolling of info text area.
255 #include "gamesequence.h"
256 #include "techmenu.h"
259 #include "snazzyui.h"
260 #include "managepilot.h"
264 #include "missioncampaign.h"
265 #include "missionshipchoice.h"
266 #include "freespace.h"
267 #include "mainhallmenu.h"
268 #include "missionscreencommon.h"
274 #include "contexthelp.h"
275 #include "alphacolors.h"
276 #include "animplay.h"
277 #include "localize.h"
278 #include "lighting.h"
280 #define REVOLUTION_RATE 5.2f
283 #define NUM_BUTTONS 18
285 #define NUM_BUTTONS 16
288 #define LIST_BUTTONS_MAX 41
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)
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
303 #define SCROLL_LIST_UP 7
304 #define SCROLL_LIST_DOWN 8
305 #define SCROLL_INFO_UP 9
306 #define SCROLL_INFO_DOWN 10
308 #define PREV_ENTRY_BUTTON 11
309 #define NEXT_ENTRY_BUTTON 12
311 #define HELP_BUTTON 13
312 #define OPTIONS_BUTTON 14
313 #define EXIT_BUTTON 15
316 #define PREV_ENTRY_BUTTON2 16
317 #define NEXT_ENTRY_BUTTON2 17
321 #define REPEAT (1<<0)
322 #define NO_MOUSE_OVER_SOUND (1<<1)
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
330 // background filename for species
331 // note weapon filename is now same as ship filename
332 const char *Tech_background_filename[GR_NUM_RESOLUTIONS] = {
336 const char *Tech_mask_filename[GR_NUM_RESOLUTIONS] = {
341 const char *Tech_slider_filename[GR_NUM_RESOLUTIONS] = {
348 // need the second background for FS1
349 const char *Tech_data_background_filename = {
352 const char *Tech_data_mask_filename = {
357 int Tech_list_coords[GR_NUM_RESOLUTIONS][4] = {
370 int Tech_ship_display_coords[GR_NUM_RESOLUTIONS][4] = {
383 int Tech_desc_coords[GR_NUM_RESOLUTIONS][4] = {
396 int Tech_ani_coords[GR_NUM_RESOLUTIONS][2] = {
410 int Tech_data_desc_coords[GR_NUM_RESOLUTIONS][4] = {
421 int Tech_slider_coords[GR_NUM_RESOLUTIONS][4] = {
432 int Tech_detail_backup;
433 int Tech_texture_backup;
435 #define MAX_TEXT_LINES 100
436 #define MAX_TEXT_LINE_LEN 256
438 struct techroom_buttons {
439 const char *filename;
444 UI_BUTTON button; // because we have a class inside this struct, we need the constructor below..
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) {}
449 static techroom_buttons Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
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
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
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
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
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
518 static UI_WINDOW Ui_window;
519 static UI_BUTTON View_window;
520 //static int Background_bitmap;
522 static int Tech_data_background_bitmap;
524 static int Tech_background_bitmap;
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;
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];
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;
548 static int ShipWin01;
549 static int ShipWin02;
550 static int ShipWin03;
551 static int ShipWin04;
553 static ubyte Palette[768];
554 //static char Palette_name[128]; // no longer used
556 static int Ships_loaded = 0;
557 static int Weapons_loaded = 0;
558 static int Intel_loaded = 0;
560 // out entry data struct & vars
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
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;
581 static UI_SLIDER2 Tech_slider;
586 static const char *Intel_anim_filenames[MAX_INTEL_ENTRIES] = {
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;
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();
605 void techroom_data_init();
606 void techroom_tab_setup(int set_palette);
612 ////////////////////////////////////////////////////
613 // like, functions and stuff
615 void techroom_init_desc(char *src, int w)
617 Text_size = Text_offset = 0;
622 Text_size = split_str(src, w, Text_line_size, Text_lines, MAX_TEXT_LINES);
623 SDL_assert(Text_size >= 0 && Text_size < MAX_TEXT_LINES);
626 void techroom_select_new_entry()
628 SDL_assert(Current_list != NULL);
629 if (Current_list == NULL) return;
631 Cur_entry_index = Current_list[Cur_entry].index;
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];
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;
642 Techroom_ship_modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
645 // page in ship textures properly (takes care of nondimming pixels)
646 model_page_in_textures(Techroom_ship_modelnum, Cur_entry_index);
648 Techroom_ship_modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
650 // page in ship textures properly (takes care of nondimming pixels)
651 model_page_in_textures(Techroom_ship_modelnum, Cur_entry_index);
654 Techroom_ship_modelnum = -1;
658 // Techroom_ship_rot = PI;
661 if ( (Tab == WEAPONS_DATA_TAB) || (Tab == INTEL_DATA_TAB) ) {
662 techroom_init_desc(Current_list[Cur_entry].desc, Tech_data_desc_coords[gr_screen.res][SHIP_W_COORD]);
664 techroom_init_desc(Current_list[Cur_entry].desc, Tech_desc_coords[gr_screen.res][SHIP_W_COORD]);
667 techroom_init_desc(Current_list[Cur_entry].desc, Tech_desc_coords[gr_screen.res][SHIP_W_COORD]);
669 techroom_start_anim();
672 // write out the current description in the bottom window
673 void techroom_render_desc(int xo, int yo, int h)
675 int y, z, len, font_height;
676 char line[MAX_TEXT_LINE_LEN + 1];
678 font_height = gr_get_font_height();
682 while (y + font_height <= h) {
687 len = Text_line_size[z] + 1;
688 if (len > MAX_TEXT_LINE_LEN){
689 len = MAX_TEXT_LINE_LEN;
692 SDL_strlcpy(line, Text_lines[z], len);
693 gr_string(xo, yo + y, line);
699 // maybe output 'more' indicator
700 #ifndef MAKE_FS1 // not used in original
701 if ( z < Text_size ) {
702 // can be scrolled down
703 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
704 int more_txt_y = Tech_desc_coords[gr_screen.res][1] + Tech_desc_coords[gr_screen.res][3]; // located below brief text, centered
706 gr_get_string_size(&w, &h, XSTR("more", 1469), strlen(XSTR("more", 1469)));
707 gr_set_color_fast(&Color_black);
708 gr_rect(more_txt_x-2, more_txt_y, w+3, h);
709 gr_set_color_fast(&Color_red);
710 gr_string(more_txt_x, more_txt_y, XSTR("more", 1469)); // base location on the input x and y?
716 // new version of weapons
717 void techroom_weapons_render2(float frametime)
719 // render common stuff
721 tech_common_render();
723 // render description in its box
724 gr_set_color_fast(&Color_text_normal);
725 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]);
728 // render the animation
730 // JAS: This code is hacked to allow the animation to use all 256 colors
731 extern int Palman_allow_any_color;
732 Palman_allow_any_color = 1;
733 anim_render_all(0, frametime);
734 Palman_allow_any_color = 0;
737 // if our active item has a bitmap instead of an animation, draw it
738 if((Cur_entry > 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
739 gr_set_bitmap(Current_list[Cur_entry].bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
740 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
744 // renders the stuff common to all 3 tech room tabs
745 void tech_common_render()
748 int y, z, font_height;
750 // render description in its box
751 gr_set_color_fast(&Color_text_normal);
752 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 font_height = gr_get_font_height();
756 // draw the list of entries
759 while (y + font_height <= Tech_list_coords[gr_screen.res][SHIP_H_COORD]) {
760 if (z >= Current_list_size) {
764 if (z == Cur_entry) {
765 gr_set_color_fast(&Color_text_selected);
766 } else if (z == Select_tease_line) {
767 gr_set_color_fast(&Color_text_subselected);
769 gr_set_color_fast(&Color_text_normal);
772 SDL_strlcpy(buf, Current_list[z].name, SDL_arraysize(buf));
774 lcl_translate_ship_name(buf, SDL_arraysize(buf));
777 gr_force_fit_string(buf, 255, Tech_list_coords[gr_screen.res][SHIP_W_COORD]);
778 gr_string(Tech_list_coords[gr_screen.res][SHIP_X_COORD], Tech_list_coords[gr_screen.res][SHIP_Y_COORD] + y, buf);
780 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);
781 List_buttons[z - List_offset].enable(1);
787 // disable the rest of the list buttons
789 while (z < LIST_BUTTONS_MAX) {
790 List_buttons[z++].disable();
794 void techroom_ships_render(float frametime)
796 // render all the common stuff
797 tech_common_render();
799 // now render the trackball ship, which is unique to the ships tab
801 angles rot_angles, view_angles;
803 ship_info *sip = &Ship_info[Cur_entry_index];
805 // get correct revolution rate
806 rev_rate = REVOLUTION_RATE;
808 if (z & SIF_BIG_SHIP) {
811 if (z & SIF_HUGE_SHIP) {
815 // rotate the ship as much as required for this frame
816 Techroom_ship_rot += PI2 * frametime / rev_rate;
817 while (Techroom_ship_rot > PI2){
818 Techroom_ship_rot -= PI2;
822 gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0, -1.0f, -1.0f);
825 if (Trackball_active) {
829 if (Trackball_active) {
830 mouse_get_delta(&dx, &dy);
832 vm_trackball(-dx, -dy, &mat1);
833 vm_matrix_x_matrix(&mat2, &mat1, &Techroom_ship_orient);
834 Techroom_ship_orient = mat2;
839 // setup stuff needed to render the ship
840 view_angles.p = -0.6f;
841 view_angles.b = 0.0f;
842 view_angles.h = 0.0f;
843 vm_angles_2_matrix(&Techroom_ship_orient, &view_angles);
847 rot_angles.h = Techroom_ship_rot;
848 vm_rotate_matrix_by_angles(&Techroom_ship_orient, &rot_angles);
851 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]);
854 #ifdef MULTIPLAYER_BETA_BUILD
855 if((sip->flags & SIF_SUPERCAP) || (sip->flags & SIF_DRYDOCK)) {
856 gr_set_color_fast(&Color_bright);
857 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!"));
861 g3_set_view_matrix(&sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * 1.3f);
863 // lighting for techroom
865 vector light_dir = vmd_zero_vector;
867 light_add_directional(&light_dir, 0.85f, 1.0f, 1.0f, 1.0f);
868 // light_filter_reset();
870 // lighting for techroom
872 model_clear_instance(Techroom_ship_modelnum);
873 model_set_detail_level(0);
874 model_render(Techroom_ship_modelnum, &Techroom_ship_orient, &vmd_zero_vector, MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER);
881 g3_set_view_matrix(&sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * 1.3f);
883 // lighting for techroom
885 vector light_dir = vmd_zero_vector;
886 light_dir.xyz.y = 1.0f;
887 light_add_directional(&light_dir, 0.85f, 1.0f, 1.0f, 1.0f);
888 // light_filter_reset();
890 // lighting for techroom
892 model_clear_instance(Techroom_ship_modelnum);
893 model_set_detail_level(0);
894 model_render(Techroom_ship_modelnum, &Techroom_ship_orient, &vmd_zero_vector, MR_LOCK_DETAIL | MR_AUTOCENTER);
902 // select previous entry in current list
903 void tech_prev_entry()
910 gamesnd_play_iface(SND_GENERAL_FAIL);
914 Cur_entry = Current_list_size - 1;
916 // scroll to end of list
917 List_offset = Cur_entry - Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() + 1;
918 if (List_offset < 0) {
919 // this happens when there are not enough items to scroll
923 Tech_slider.force_currentItem(Tech_slider.get_numberItems());
926 // maybe adjust list position by 1
927 if (List_offset > Cur_entry) {
928 tech_scroll_list_up();
930 Tech_slider.forceUp();
935 techroom_select_new_entry();
936 gamesnd_play_iface(SND_SCROLL);
939 // select next entry in current list
940 void tech_next_entry()
943 if (Cur_entry >= Current_list_size) {
945 // stop at last entry, play fail sound
948 gamesnd_play_iface(SND_GENERAL_FAIL);
954 // scroll to beginning of list
957 Tech_slider.force_currentItem(Cur_entry);
960 // maybe adjust list position by 1
961 if (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() <= Cur_entry) {
962 tech_scroll_list_down();
964 Tech_slider.forceDown();
969 techroom_select_new_entry();
970 gamesnd_play_iface(SND_SCROLL);
973 void tech_scroll_info_up()
977 gamesnd_play_iface(SND_SCROLL);
979 gamesnd_play_iface(SND_GENERAL_FAIL);
983 void tech_scroll_info_down()
987 if (Tab == SHIPS_DATA_TAB){
988 h = Tech_desc_coords[gr_screen.res][SHIP_H_COORD];
990 h = Tech_desc_coords[gr_screen.res][3];
993 if (Text_offset + h / gr_get_font_height() < Text_size) {
995 gamesnd_play_iface(SND_SCROLL);
997 gamesnd_play_iface(SND_GENERAL_FAIL);
1001 void tech_scroll_list_up()
1003 if (List_offset > 0) {
1007 int last = List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() - 1;
1009 if (last < Cur_entry) {
1011 techroom_select_new_entry();
1014 gamesnd_play_iface(SND_SCROLL);
1016 gamesnd_play_iface(SND_GENERAL_FAIL);
1020 void tech_scroll_list_down()
1022 if (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() < Current_list_size) {
1026 if (List_offset > Cur_entry) {
1028 techroom_select_new_entry();
1031 gamesnd_play_iface(SND_SCROLL);
1033 gamesnd_play_iface(SND_GENERAL_FAIL);
1037 // this doesnt do a damn thing...
1038 void tech_ship_scroll_capture()
1040 techroom_select_new_entry();
1044 // this is obsolete - see techroom_weapons_render2(...)
1045 void techroom_weapons_render(float frametime)
1047 gr_set_color_fast(&Color_text_normal);
1048 techroom_render_desc(Tech_desc_coords[gr_screen.res][0], Tech_desc_coords[gr_screen.res][1], Tech_desc_coords[gr_screen.res][3]);
1051 // JAS: This code is hacked to allow the animation to use all 256 colors
1052 extern int Palman_allow_any_color;
1053 Palman_allow_any_color = 1;
1054 anim_render_all(0, frametime);
1055 Palman_allow_any_color = 0;
1058 // if our active item has a bitmap instead of an animation, draw it
1059 if((Cur_entry >= 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
1060 gr_set_bitmap(Current_list[Cur_entry].bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1061 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
1065 void techroom_intel_render(float frametime)
1068 tech_common_render();
1070 // render description in its box
1071 gr_set_color_fast(&Color_text_normal);
1072 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]);
1076 // JAS: This code is hacked to allow the animation to use all 256 colors
1077 extern int Palman_allow_any_color;
1078 Palman_allow_any_color = 1;
1079 anim_render_all(0, frametime);
1080 Palman_allow_any_color = 0;
1083 // if our active item has a bitmap instead of an animation, draw it
1084 if((Cur_entry >= 0) && (Current_list[Cur_entry].animation == NULL) && (Current_list[Cur_entry].bitmap >= 0)){
1085 gr_set_bitmap(Current_list[Cur_entry].bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1086 gr_bitmap(Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
1090 void techroom_stop_anim(int id)
1092 if (Cur_anim_instance && (id != Anim_playing_id)) {
1093 anim_stop_playing(Cur_anim_instance);
1094 Cur_anim_instance = NULL;
1098 void techroom_start_anim()
1102 anim_play_struct aps;
1104 if (Cur_entry < 0) {
1105 techroom_stop_anim(-1);
1106 Anim_playing_id = -1;
1109 if (Tab == WEAPONS_DATA_TAB) {
1112 id = Cur_entry + 2000; // this offset is arbitrary?
1115 techroom_stop_anim(id);
1117 // if we actually have an animation
1118 if(Current_list[Cur_entry].animation != NULL){
1119 animp = Current_list[Cur_entry].animation;
1121 if (id != Anim_playing_id) {
1122 Anim_playing_id = -1;
1124 anim_play_init(&aps, animp, Tech_ani_coords[gr_screen.res][0], Tech_ani_coords[gr_screen.res][1]);
1126 Cur_anim_instance = anim_play(&aps);
1127 Anim_playing_id = id;
1131 memcpy(Palette, animp->palette, 384);
1132 gr_set_palette(animp->name, Palette, 1);
1139 void techroom_change_tab(int num)
1141 int i, multi = 0, mask;
1143 int font_height, max_num_entries_viewable;
1147 // SDL_assert(Current_list_size >= 0);
1150 multi = Player->flags & PLAYER_FLAGS_IS_MULTI;
1152 for (i=0; i<LIST_BUTTONS_MAX; i++){
1153 List_buttons[i].disable();
1156 // disable some stuff in multiplayer
1157 if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
1158 Buttons[gr_screen.res][SIMULATOR_TAB].button.disable();
1159 Buttons[gr_screen.res][CUTSCENES_TAB].button.disable();
1163 case SHIPS_DATA_TAB:
1164 mask = multi ? SIF_IN_TECH_DATABASE_M : SIF_IN_TECH_DATABASE;
1166 // load ship info if necessary
1167 if (Ships_loaded == 0) {
1169 for (i=0; i<Num_ship_types; i++) {
1171 if (Ship_info[i].flags & mask) {
1173 // make sure it has a description before displaying
1174 if ((Ship_info[i].flags & mask) && (Ship_info[i].tech_desc)) {
1176 // this ship should be displayed, fill out the entry struct
1177 Ship_list[Ship_list_size].bitmap = -1;
1178 Ship_list[Ship_list_size].index = i;
1179 Ship_list[Ship_list_size].animation = NULL; // no anim for ships
1180 Ship_list[Ship_list_size].has_anim = 0; // no anim for ships
1181 Ship_list[Ship_list_size].name = Ship_info[i].name;
1182 Ship_list[Ship_list_size].desc = Ship_info[i].tech_desc;
1189 Current_list = Ship_list;
1190 Current_list_size = Ship_list_size;
1193 font_height = gr_get_font_height();
1194 max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1195 Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1198 // no anim to start here
1201 case WEAPONS_DATA_TAB:
1203 techroom_data_init();
1205 // load weapon info & anims if necessary
1206 if (Weapons_loaded == 0) {
1207 Weapon_list_size = 0;
1208 mask = multi ? WIF_PLAYER_ALLOWED : WIF_IN_TECH_DATABASE;
1210 for (i=0; i<MAX_WEAPON_TYPES; i++) {
1211 if (Weapon_info[i].wi_flags & mask) {
1213 // note: hack here to exclude dogfight weapons -- dont put weapon in if it has same description as pvs weapon
1214 if ((Weapon_list_size > 0) && (!strcmp(Weapon_info[i].tech_desc, Weapon_list[Weapon_list_size-1].desc))) {
1216 // exclude entries with no description, basically the same as above but helps get rid of special cases as well
1217 if ((Weapon_list_size > 0) && (!Weapon_info[i].tech_desc)) {
1222 // we have a weapon that should be in the tech db, so fill out the entry struct
1223 Weapon_list[Weapon_list_size].index = i;
1224 Weapon_list[Weapon_list_size].desc = Weapon_info[i].tech_desc;
1225 Weapon_list[Weapon_list_size].has_anim = 1;
1226 Weapon_list[Weapon_list_size].name = Weapon_info[i].tech_title;
1227 Weapon_list[Weapon_list_size].bitmap = -1;
1228 if (Weapon_list[Weapon_list_size].name[0] == 0) {
1229 Weapon_list[Weapon_list_size].name = Weapon_info[i].name;
1233 // figure out the animation based on weapon name
1234 if (!strcmp(Weapon_info[i].name, "ML-16 Laser")) {
1235 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_ML16.ani", NAME_LENGTH);
1236 } else if (!strcmp(Weapon_info[i].name, "Disruptor")) {
1237 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Disruptor.ani", NAME_LENGTH);
1238 } else if (!strcmp(Weapon_info[i].name, "D-Advanced")) {
1239 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_DAdvanced.ani", NAME_LENGTH);
1240 } else if (!strcmp(Weapon_info[i].name, "Avenger")) {
1241 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Avenger.ani", NAME_LENGTH);
1242 } else if (!strcmp(Weapon_info[i].name, "Flail")) {
1243 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Flail.ani", NAME_LENGTH);
1244 } else if (!strcmp(Weapon_info[i].name, "Prometheus")) {
1245 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Prometheus.ani", NAME_LENGTH);
1246 } else if (!strcmp(Weapon_info[i].name, "Banshee")) {
1247 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Banshee.ani", NAME_LENGTH);
1248 } else if (!strcmp(Weapon_info[i].name, "MX-50")) {
1249 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_MX50.ani", NAME_LENGTH);
1250 } else if (!strcmp(Weapon_info[i].name, "D-Missile")) {
1251 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_DisruptorMissile.ani", NAME_LENGTH);
1252 } else if (!strcmp(Weapon_info[i].name, "Fury")) {
1253 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Fury.ani", NAME_LENGTH);
1254 } else if (!strcmp(Weapon_info[i].name, "Hornet")) {
1255 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Hornet.ani", NAME_LENGTH);
1256 } else if (!strcmp(Weapon_info[i].name, "Interceptor")) {
1257 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Interceptor.ani", NAME_LENGTH);
1258 } else if (!strcmp(Weapon_info[i].name, "Phoenix V")) {
1259 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Phoenix.ani", NAME_LENGTH);
1260 } else if (!strcmp(Weapon_info[i].name, "Synaptic")) {
1261 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Synaptic.ani", NAME_LENGTH);
1262 } else if (!strcmp(Weapon_info[i].name, "Stiletto")) {
1263 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Stiletto.ani", NAME_LENGTH);
1264 } else if (!strcmp(Weapon_info[i].name, "Tsunami")) {
1265 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Tsunami.ani", NAME_LENGTH);
1266 } else if (!strcmp(Weapon_info[i].name, "Harbinger")) {
1267 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_Harbinger.ani", NAME_LENGTH);
1268 } else if (!strcmp(Weapon_info[i].name, "Leech Cannon")) {
1269 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_leech.ani", NAME_LENGTH);
1270 } else if (!strcmp(Weapon_info[i].name, "EM Pulse")) {
1271 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_empulse.ani", NAME_LENGTH);
1272 } else if (!strcmp(Weapon_info[i].name, "S-Breaker")) {
1273 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_sbreaker.ani", NAME_LENGTH);
1274 } else if (!strcmp(Weapon_info[i].name, "Cluster Bomb")) {
1275 SDL_strlcpy(Weapon_info[i].tech_anim_filename, "CB_cluster.ani", NAME_LENGTH);
1279 // load the weapon animation
1280 if(!techroom_load_ani(&Weapon_list[Weapon_list_size].animation, Weapon_info[i].tech_anim_filename)){
1281 Weapon_list[Weapon_list_size].has_anim = 0;
1282 Weapon_list[Weapon_list_size].animation = NULL;
1284 // hmm. try a bitmap instead
1285 Weapon_list[Weapon_list_size].bitmap = bm_load(Weapon_info[i].tech_anim_filename);
1295 Current_list = Weapon_list;
1296 Current_list_size = Weapon_list_size;
1299 font_height = gr_get_font_height();
1300 max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1301 Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1304 techroom_start_anim();
1307 case INTEL_DATA_TAB:
1310 techroom_data_init();
1312 // load intel if necessary
1313 if ( Intel_loaded == 0 ) {
1314 // now populate the entry structs
1315 Intel_list_size = 0;
1316 for (i=0; i<Intel_info_size; i++) {
1318 if (Intel_info[i].in_tech_db != 0) {
1319 // leave option for no animation if string == "none"
1320 if (!strcmp(Intel_info[i].anim_filename, "none")) {
1321 Intel_list[Intel_list_size].has_anim = 0;
1322 Intel_list[Intel_list_size].animation = NULL;
1324 // try and load as an animation
1325 Intel_list[Intel_list_size].has_anim = 0;
1326 Intel_list[Intel_list_size].bitmap = -1;
1327 if(techroom_load_ani(&Intel_list[Intel_list_size].animation, Intel_info[i].anim_filename)){
1328 Intel_list[Intel_list_size].has_anim = 1;
1330 Intel_list[Intel_list_size].bitmap = bm_load(Intel_info[i].anim_filename);
1334 Intel_list[Intel_list_size].desc = Intel_info[i].desc;
1335 Intel_list[Intel_list_size].index = i;
1336 Intel_list[Intel_list_size].name = Intel_info[i].name;
1343 // index lookup on intel is a pretty pointless, but it keeps everything
1344 // consistent and doesnt really hurt anything
1345 Current_list = Intel_list;
1346 Current_list_size = Intel_list_size;
1349 font_height = gr_get_font_height();
1350 max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
1351 Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);
1354 techroom_start_anim();
1360 techroom_select_new_entry();
1363 techroom_tab_setup(1);
1367 int techroom_button_pressed(int num)
1370 case SHIPS_DATA_TAB:
1371 case WEAPONS_DATA_TAB:
1372 case INTEL_DATA_TAB:
1373 techroom_change_tab(num);
1377 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1378 gamesnd_play_iface(SND_SWITCH_SCREENS);
1379 gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
1386 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1387 gamesnd_play_iface(SND_SWITCH_SCREENS);
1388 gameseq_post_event(GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN);
1395 #if !defined(E3_BUILD) && !defined(PD_BUILD)
1396 gamesnd_play_iface(SND_SWITCH_SCREENS);
1397 gameseq_post_event(GS_EVENT_CREDITS);
1403 case PREV_ENTRY_BUTTON:
1407 case NEXT_ENTRY_BUTTON:
1412 case PREV_ENTRY_BUTTON2:
1416 case NEXT_ENTRY_BUTTON2:
1421 case SCROLL_LIST_UP:
1422 tech_scroll_list_up();
1424 Tech_slider.forceUp();
1428 case SCROLL_LIST_DOWN:
1429 tech_scroll_list_down();
1431 Tech_slider.forceDown();
1435 case SCROLL_INFO_UP:
1436 tech_scroll_info_up();
1439 case SCROLL_INFO_DOWN:
1440 tech_scroll_info_down();
1444 launch_context_help();
1445 gamesnd_play_iface(SND_HELP_PRESSED);
1448 case OPTIONS_BUTTON:
1449 gamesnd_play_iface(SND_SWITCH_SCREENS);
1450 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1454 gamesnd_play_iface(SND_COMMIT_PRESSED);
1455 gameseq_post_event(GS_EVENT_MAIN_MENU);
1462 int techroom_load_ani(anim **animpp, char *name)
1464 int load_attempts = 0;
1465 char anim_filename[64] = "2_";
1468 // (i dont think there are any hi-res anims for these tho)
1469 if (gr_screen.res == GR_1024) {
1470 SDL_strlcat(anim_filename, name, SDL_arraysize(anim_filename));
1472 SDL_strlcpy(anim_filename, name, SDL_arraysize(anim_filename));
1476 if ( load_attempts++ > 5 ) {
1477 // Tech_room_ask_for_cd = 0;
1481 *animpp = anim_load(anim_filename);
1484 } else if (gr_screen.res == GR_1024) {
1485 // try to load low-res version if hi-res failed
1486 *animpp = anim_load(name);
1492 // couldn't load animation, ask user to insert CD (if necessary)
1493 // if ( Tech_room_ask_for_cd ) {
1494 // if ( game_do_cd_check() == 0 ) {
1495 // Tech_room_ask_for_cd = 0;
1506 void techroom_intel_init()
1508 static int inited = 0;
1510 // open localization
1515 read_file_text("species.tbl");
1518 Intel_info_size = 0;
1521 while (optional_string("$Entry:")) {
1522 SDL_assert(Intel_info_size < MAX_INTEL_ENTRIES);
1523 if (Intel_info_size >= MAX_INTEL_ENTRIES) break;
1525 required_string("$Name:");
1526 stuff_string(Intel_info[Intel_info_size].name, F_NAME, NULL, 32);
1527 required_string("$Anim:");
1528 stuff_string(Intel_info[Intel_info_size].anim_filename, F_NAME, NULL, 32);
1529 required_string("$AlwaysInTechRoom:");
1530 stuff_int(&Intel_info[Intel_info_size].in_tech_db);
1531 required_string("$Description:");
1532 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1538 if (optional_string("$Terran Tech Description:")) {
1539 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1540 SDL_strlcpy(Intel_info[Intel_info_size].name, "Terran", SDL_arraysize(Intel_info[0].name));
1541 SDL_strlcpy(Intel_info[Intel_info_size].anim_filename, Intel_anim_filenames[0], SDL_arraysize(Intel_info[0].anim_filename));
1542 Intel_info[Intel_info_size].in_tech_db = 1;
1547 if (optional_string("$Vasudan Tech Description:")) {
1549 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1550 SDL_strlcpy(Intel_info[Intel_info_size].name, "Vasudan", SDL_arraysize(Intel_info[0].name));
1551 SDL_strlcpy(Intel_info[Intel_info_size].anim_filename, Intel_anim_filenames[1], SDL_arraysize(Intel_info[0].anim_filename));
1552 Intel_info[Intel_info_size].in_tech_db = 1;
1557 if (optional_string("$Shivan Tech Description:")) {
1559 stuff_string(Intel_info[Intel_info_size].desc, F_MULTITEXT, NULL, TECH_INTEL_DESC_LEN);
1560 SDL_strlcpy(Intel_info[Intel_info_size].name, "Shivan", SDL_arraysize(Intel_info[0].name));
1561 SDL_strlcpy(Intel_info[Intel_info_size].anim_filename, Intel_anim_filenames[2], SDL_arraysize(Intel_info[0].anim_filename));
1562 // Shivans are only visible after mission sm1-05a in campaign
1563 Intel_info[Intel_info_size].in_tech_db = 0;
1569 } catch (parse_error_t rval) {
1570 Error(LOCATION, "Unable to parse species.tbl! Code = %i.\n", (int)rval);
1574 // close localization
1578 void techroom_init()
1581 techroom_buttons *b;
1593 // Tech_room_ask_for_cd = 1;
1595 // backup and bash detail level stuff
1596 Tech_detail_backup = Detail.detail_distance;
1597 Detail.detail_distance = MAX_DETAIL_LEVEL;
1598 Tech_texture_backup = Detail.hardware_textures;
1599 Detail.hardware_textures = MAX_DETAIL_LEVEL;
1602 Palette_bmp = bm_load("TechDataPalette");
1603 SDL_assert(Palette_bmp);
1604 bm_get_palette(Palette_bmp, Palette, Palette_name); // get the palette for this bitmap
1605 gr_set_palette(Palette_name, Palette, 1);
1609 common_set_interface_palette("TechDataPalette");
1613 The_mission.flags &= ~MISSION_FLAG_FULLNEB;
1616 Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1617 #ifndef MAKE_FS1 // do this with techroom_tab_setup()
1618 Ui_window.set_mask_bmap(Tech_mask_filename[gr_screen.res]);
1621 Tech_background_bitmap = bm_load(Tech_background_filename[gr_screen.res]);
1622 if (Tech_background_bitmap < 0) {
1623 // failed to load bitmap, not a good thing
1627 #ifdef MAKE_FS1 // for weapons/species tab
1628 Tech_data_background_bitmap = bm_load(Tech_data_background_filename);
1629 if (Tech_data_background_bitmap < 0) {
1630 // failed to load bitmap, not a good thing
1634 techroom_tab_setup(0);
1636 // don't draw buttons that are only on other tabs
1637 for (i=0; i<PREV_ENTRY_BUTTON2; i++) {
1639 for (i=0; i<NUM_BUTTONS; i++) {
1641 b = &Buttons[gr_screen.res][i];
1643 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1644 // set up callback for when a mouse first goes over a button
1646 b->button.set_bmaps(b->filename);
1647 // if ( !(b->flags & NO_MOUSE_OVER_SOUND) ) {
1648 b->button.set_highlight_action(common_play_highlight_sound);
1655 b->button.link_hotspot(b->hotspot);
1659 // common tab button text
1660 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);
1661 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);
1662 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);
1663 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);
1665 // common ship/weapon/intel text
1666 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);
1667 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);
1668 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);
1670 // common help/options/commit text
1672 // NK: removed these two text labels on Tech screen update 4/26/99
1673 // 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);
1674 // 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);
1675 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);
1678 if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
1679 Buttons[gr_screen.res][SIMULATOR_TAB].button.disable();
1680 Buttons[gr_screen.res][CUTSCENES_TAB].button.disable();
1684 Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.set_hotkey(SDLK_LEFT);
1685 Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.set_hotkey(SDLK_RIGHT);
1686 Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(SDLK_UP);
1687 Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(SDLK_DOWN);
1690 for (i=0; i<LIST_BUTTONS_MAX; i++) {
1691 List_buttons[i].create(&Ui_window, "", 0, 0, 60, 30, 0, 1);
1692 List_buttons[i].hide();
1693 List_buttons[i].disable();
1696 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);
1700 ShipWin01 = bm_load(NOX("ShipWin01"));
1701 ShipWin02 = bm_load(NOX("ShipWin02"));
1702 ShipWin03 = bm_load(NOX("ShipWin03"));
1703 ShipWin04 = bm_load(NOX("ShipWin04"));
1706 Buttons[gr_screen.res][HELP_BUTTON].button.set_hotkey(SDLK_F1);
1707 Buttons[gr_screen.res][EXIT_BUTTON].button.set_hotkey(KEY_CTRLED | SDLK_RETURN);
1708 Buttons[gr_screen.res][SCROLL_LIST_UP].button.set_hotkey(SDLK_PAGEUP);
1709 Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.set_hotkey(SDLK_PAGEDOWN);
1711 // init help overlay states
1712 help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
1716 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);
1719 Cur_anim_instance = NULL;
1721 // zero weapon and intel anim/bitmap stuff
1722 for(idx=0; idx<MAX_WEAPON_TYPES; idx++){
1723 Weapon_list[idx].animation = NULL;
1724 Weapon_list[idx].bitmap = -1;
1726 for(idx=0; idx<MAX_INTEL_ENTRIES; idx++){
1727 Intel_list[idx].animation = NULL;
1728 Intel_list[idx].bitmap = -1;
1731 Anim_playing_id = -1;
1732 techroom_change_tab(Tab);
1735 void techroom_close()
1739 techroom_stop_anim(-1);
1740 for (i=0; i<MAX_WEAPON_TYPES; i++) {
1741 if ( Weapon_list[i].animation ) {
1742 anim_free(Weapon_list[i].animation);
1743 Weapon_list[i].animation = NULL;
1745 if( Weapon_list[i].bitmap >= 0 ){
1746 bm_unload(Weapon_list[i].bitmap);
1747 Weapon_list[i].bitmap = -1;
1751 for (i=0; i<MAX_INTEL_ENTRIES; i++){
1752 if (Intel_list[i].animation != NULL) {
1753 anim_free(Intel_list[i].animation);
1754 Intel_list[i].animation = NULL;
1756 if( Intel_list[i].bitmap >= 0 ){
1757 bm_unload(Intel_list[i].bitmap);
1758 Intel_list[i].bitmap = -1;
1768 bm_unload(ShipWin01);
1771 bm_unload(ShipWin02);
1774 bm_unload(ShipWin03);
1777 bm_unload(ShipWin04);
1780 if (Tech_data_background_bitmap) {
1781 bm_unload(Tech_data_background_bitmap);
1785 if (Tech_background_bitmap) {
1786 bm_unload(Tech_background_bitmap);
1789 Ui_window.destroy();
1790 common_free_interface_palette(); // restore game palette
1793 bm_unload(Palette_bmp);
1797 // restore detail settings
1798 Detail.detail_distance = Tech_detail_backup;
1799 Detail.hardware_textures = Tech_texture_backup;
1803 void techroom_data_init()
1806 techroom_buttons *b;
1808 for (i=PREV_ENTRY_BUTTON2; i<NUM_BUTTONS; i++) {
1809 b = &Buttons[gr_screen.res][i];
1811 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1812 // set up callback for when a mouse first goes over a button
1814 b->button.set_bmaps(b->filename);
1815 b->button.set_highlight_action(common_play_highlight_sound);
1820 b->button.link_hotspot(b->hotspot);
1824 void techroom_tab_setup(int set_palette)
1829 // activate, deactivate any necessary controls
1830 for (i=0; i<NUM_BUTTONS; i++) {
1831 Buttons[gr_screen.res][i].button.enable();
1832 if (Buttons[gr_screen.res][i].filename)
1833 Buttons[gr_screen.res][i].button.unhide();
1836 // do other special processing
1838 case SHIPS_DATA_TAB:
1839 // set the mask for this tab
1840 Ui_window.set_mask_bmap(Tech_mask_filename[gr_screen.res]);
1842 // setup hotkeys to scroll list
1843 Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(SDLK_UP);
1844 Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(SDLK_DOWN);
1846 // hide extra buttons
1847 Buttons[gr_screen.res][PREV_ENTRY_BUTTON2].button.hide();
1848 Buttons[gr_screen.res][NEXT_ENTRY_BUTTON2].button.hide();
1851 case WEAPONS_DATA_TAB:
1852 // set the mask for this tab
1853 Ui_window.set_mask_bmap(Tech_data_mask_filename);
1855 // the list isn't supposed to scroll so clear the hotkeys
1856 Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(-1);
1857 Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(-1);
1859 // hide extra buttons
1860 Buttons[gr_screen.res][SCROLL_LIST_UP].button.hide();
1861 Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.hide();
1862 Buttons[gr_screen.res][SCROLL_INFO_UP].button.hide();
1863 Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.hide();
1864 Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.hide();
1865 Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.hide();
1868 case INTEL_DATA_TAB:
1869 // set the mask for this tab
1870 Ui_window.set_mask_bmap(Tech_data_mask_filename);
1872 // the list isn't supposed to scroll so clear the hotkeys
1873 Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(-1);
1874 Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(-1);
1876 // hide extra buttons
1877 Buttons[gr_screen.res][SCROLL_LIST_UP].button.hide();
1878 Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.hide();
1879 Buttons[gr_screen.res][SCROLL_INFO_UP].button.hide();
1880 Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.hide();
1881 Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.hide();
1882 Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.hide();
1888 void techroom_do_frame(float frametime)
1892 // turn off controls when overlay is on
1893 if ( help_overlay_active(TECH_ROOM_OVERLAY) ) {
1894 Buttons[gr_screen.res][HELP_BUTTON].button.reset_status();
1895 Ui_window.set_ignore_gadgets(1);
1898 // turn off controls in trackball mode
1899 if (Trackball_active) {
1900 Ui_window.set_ignore_gadgets(1);
1902 Ui_window.set_ignore_gadgets(0);
1905 k = Ui_window.process() & ~KEY_DEBUGGED;
1907 if ( (k > 0) || B1_JUST_RELEASED ) {
1908 if ( help_overlay_active(TECH_ROOM_OVERLAY) ) {
1909 help_overlay_set_state(TECH_ROOM_OVERLAY, 0);
1910 Ui_window.set_ignore_gadgets(0);
1915 if ( !help_overlay_active(TECH_ROOM_OVERLAY) ) {
1916 Ui_window.set_ignore_gadgets(0);
1920 case KEY_SHIFTED | SDLK_TAB: // activate previous tab
1926 techroom_change_tab(i);
1929 case SDLK_TAB: // activate next tab
1931 if (i >= NUM_TABS) {
1935 techroom_change_tab(i);
1938 case KEY_CTRLED | SDLK_DOWN:
1939 if ( !(Player->flags & PLAYER_FLAGS_IS_MULTI) ) {
1940 techroom_button_pressed(SIMULATOR_TAB);
1945 case KEY_CTRLED | SDLK_UP:
1946 techroom_button_pressed(CREDITS_TAB);
1949 * Not used any longer, using ui_button hotkeys instead. This is just here for
1954 tech_scroll_info_up();
1958 tech_scroll_info_down();
1970 tech_scroll_list_up();
1974 tech_scroll_list_down();
1978 case KEY_CTRLED | SDLK_RETURN:
1980 gameseq_post_event(GS_EVENT_MAIN_MENU);
1984 // check ship model window for activity
1985 if (View_window.pressed()) {
1986 Trackball_active = 1;
1990 Trackball_active = 0;
1993 // check all da buttons
1994 for (i=0; i<NUM_BUTTONS; i++) {
1995 if (Buttons[gr_screen.res][i].button.pressed()) {
1996 if (techroom_button_pressed(i)) {
2002 // check for mouseovers/clicks on the selection list
2003 Select_tease_line = -1;
2004 for (i=0; i<LIST_BUTTONS_MAX; i++) {
2005 if (List_buttons[i].is_mouse_on()) {
2006 Select_tease_line = i + List_offset;
2009 if (List_buttons[i].pressed()) {
2010 Cur_entry = i + List_offset;
2011 gamesnd_play_iface(SND_USER_SELECT);
2012 techroom_select_new_entry();
2016 #ifndef MAKE_FS1 // do this per tab instead
2017 // clear & draw bg bitmap
2018 GR_MAYBE_CLEAR_RES(Tech_background_bitmap);
2019 if (Tech_background_bitmap >= 0) {
2020 gr_set_bitmap(Tech_background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2027 case SHIPS_DATA_TAB:
2029 // clear & draw bg bitmap
2030 GR_MAYBE_CLEAR_RES(Tech_background_bitmap);
2031 if (Tech_background_bitmap >= 0) {
2032 gr_set_bitmap(Tech_background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2036 techroom_ships_render(frametime);
2040 gr_set_bitmap(ShipWin01, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2041 gr_bitmap(223, 104);
2045 gr_set_bitmap(ShipWin02, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2046 gr_bitmap(621, 124);
2050 gr_set_bitmap(ShipWin03, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2051 gr_bitmap(223, 338);
2055 gr_set_bitmap(ShipWin04, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2056 gr_bitmap(218, 124);
2062 case WEAPONS_DATA_TAB:
2064 // clear & draw bg bitmap
2065 GR_MAYBE_CLEAR_RES(Tech_data_background_bitmap);
2066 if (Tech_data_background_bitmap >= 0) {
2067 gr_set_bitmap(Tech_data_background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2071 techroom_weapons_render2(frametime);
2075 case INTEL_DATA_TAB:
2077 // clear & draw bg bitmap
2078 GR_MAYBE_CLEAR_RES(Tech_data_background_bitmap);
2079 if (Tech_data_background_bitmap >= 0) {
2080 gr_set_bitmap(Tech_data_background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2084 techroom_intel_render(frametime);
2091 for (i=TECH_DATABASE_TAB; i<=CREDITS_TAB; i++) {
2092 if (Buttons[gr_screen.res][i].button.button_down()) {
2096 if (i > CREDITS_TAB) {
2097 Buttons[gr_screen.res][TECH_DATABASE_TAB].button.draw_forced(2);
2100 for (i=0; i<NUM_TABS; i++){
2101 if (Buttons[gr_screen.res][i].button.button_down()){
2106 Buttons[gr_screen.res][Tab].button.draw_forced(2);
2109 // blit help overlay if active
2110 help_overlay_maybe_blit(TECH_ROOM_OVERLAY);