]> icculus.org git repositories - taylor/freespace2.git/blob - src/missionui/missionweaponchoice.cpp
a few NDEBUG updates.
[taylor/freespace2.git] / src / missionui / missionweaponchoice.cpp
1 /*
2  * $Logfile: /Freespace2/code/MissionUI/MissionWeaponChoice.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * C module for the weapon loadout screen
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:46  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:10  root
14  * Initial import.
15  *
16  * 
17  * 40    11/01/99 11:22a Jefff
18  * some weapon name translations
19  * 
20  * 39    9/10/99 10:26a Jefff
21  * default weapon anim selection fix
22  * 
23  * 38    9/06/99 3:30p Mikek
24  * Added system for restricting weapon choices based on ship class for
25  * dogfight missions.
26  * 
27  * 37    8/27/99 11:59a Jefff
28  * fixed unnecessary sound playing
29  * 
30  * 36    8/05/99 3:40p Jefff
31  * hi-res text adjustments
32  * 
33  * 35    8/05/99 11:32a Jefff
34  * fixed hi-res weapon anims not loading from packfile
35  * 
36  * 34    7/30/99 4:35p Andsager
37  * Clean up change ship sound
38  * 
39  * 33    7/30/99 4:22p Andsager
40  * restored ship and weapon anim sounds for demo.  Added sound for
41  * changing ship in weapon loadout screen.
42  * 
43  * 32    7/27/99 7:34p Jefff
44  * Lotsa clean up, moving stuff around, generally making the whole damn
45  * thing work right.
46  * 
47  * 31    7/27/99 3:01p Jefff
48  * crippled wl_start_slot_animation to prevent loading of overhead ship
49  * .anis.  also began modifications for multiplayer interface.
50  * 
51  * 30    7/25/99 5:49p Jefff
52  * initial weapon ani is now one of the ship's weapons.  this will fall
53  * back to the original search if the ship should be weaponless.
54  * 
55  * 29    7/24/99 6:03p Jefff
56  * Added "lock" text to multiplayer lock button
57  * 
58  * 28    7/21/99 6:02p Jefff
59  * fixed weapon counts running into weapon icons
60  * 
61  * 27    7/21/99 3:24p Andsager
62  * Modify demo to use 2 frame ship and weapon select anis and cut sounds
63  * associated with ani
64  * 
65  * 26    7/20/99 7:07p Jefff
66  * added "reset" text above reset button
67  * 
68  * 25    7/20/99 1:48p Jefff
69  * Long weapon titles now wrap to next line
70  * 
71  * 24    7/20/99 10:44a Jefff
72  * increased WEAPON_DESC_MAX_LINES to 6
73  * 
74  * 23    7/20/99 12:26a Jefff
75  * text wipe sound FX
76  * 
77  * 22    7/19/99 5:08p Jefff
78  * Added text descriptions for selected weapons, complete with wipe
79  * effect.
80  * 
81  * 21    7/16/99 1:50p Dave
82  * 8 bit aabitmaps. yay.
83  * 
84  * 20    7/15/99 9:20a Andsager
85  * FS2_DEMO initial checkin
86  * 
87  * 19    7/11/99 3:20p Kellys
88  * Make sure we load high-res weapon rotations in 1024
89  * 
90  * 18    7/09/99 5:54p Dave
91  * Seperated cruiser types into individual types. Added tons of new
92  * briefing icons. Campaign screen.
93  * 
94  * 17    7/09/99 12:21a Dave
95  * Change weapon loop anim frame.
96  * 
97  * 16    3/25/99 2:45p Neilk
98  * Fixed lock button
99  * 
100  * 15    3/23/99 9:23p Neilk
101  * fixed various multiplayer lock button problems
102  * 
103  * 14    3/10/99 6:21p Neilk
104  * Added new artwork for hires
105  * 
106  * 13    2/21/99 6:01p Dave
107  * Fixed standalone WSS packets. 
108  * 
109  * 12    2/18/99 11:46a Neilk
110  * hires interface coord support
111  * 
112  * 11    2/11/99 3:08p Dave
113  * PXO refresh button. Very preliminary squad war support.
114  * 
115  * 10    2/01/99 5:55p Dave
116  * Removed the idea of explicit bitmaps for buttons. Fixed text
117  * highlighting for disabled gadgets.
118  * 
119  * 9     1/30/99 1:29a Dave
120  * Fixed nebula thumbnail problem. Full support for 1024x768 choose pilot
121  * screen.  Fixed beam weapon death messages.
122  * 
123  * 8     1/29/99 4:17p Dave
124  * New interface screens.
125  * 
126  * 7     1/27/99 9:56a Dave
127  * Temporary checkin of beam weapons for Dan to make cool sounds.
128  * 
129  * 6     12/18/98 1:13a Dave
130  * Rough 1024x768 support for Direct3D. Proper detection and usage through
131  * the launcher.
132  * 
133  * 5     11/30/98 1:07p Dave
134  * 16 bit conversion, first run.
135  * 
136  * 4     11/17/98 11:12a Dave
137  * Removed player identification by address. Now assign explicit id #'s.
138  * 
139  * 3     10/13/98 9:29a Dave
140  * Started neatening up freespace.h. Many variables renamed and
141  * reorganized. Added AlphaColors.[h,cpp]
142  * 
143  * 2     10/07/98 10:53a Dave
144  * Initial checkin.
145  * 
146  * 1     10/07/98 10:50a Dave
147  * 
148  * 119   6/17/98 11:06a Lawrance
149  * put in weapon description tooltip
150  * 
151  * 118   6/13/98 6:01p Hoffoss
152  * Externalized all new (or forgot to be added) strings to all the code.
153  * 
154  * 117   6/01/98 11:43a John
155  * JAS & MK:  Classified all strings for localization.
156  * 
157  * 116   5/19/98 8:35p Dave
158  * Revamp PXO channel listing system. Send campaign goals/events to
159  * clients for evaluation. Made lock button pressable on all screens. 
160  * 
161  * 115   5/18/98 2:49p Lawrance
162  * Put in weapon animation sound hook
163  * 
164  * 114   5/08/98 7:52p Lawrance
165  * Add code to loop new weapon animations
166  * 
167  * 113   5/06/98 11:50p Lawrance
168  * Clean up help overlay code for loadout screens
169  * 
170  * 112   5/04/98 5:27p Johnson
171  * Fixed a team vs. team weapons loadout bug.
172  * 
173  * 111   5/03/98 1:55a Lawrance
174  * Fix some sound problems with loadout screens
175  * 
176  * 110   4/30/98 6:03p Lawrance
177  * Make drag and drop work better.
178  * 
179  * 109   4/27/98 6:02p Dave
180  * Modify how missile scoring works. Fixed a team select ui bug. Speed up
181  * multi_lag system. Put in new main hall.
182  * 
183  * 108   4/24/98 2:17a Lawrance
184  * repositioin ship name in weapons loadout
185  * 
186  * 107   4/22/98 7:24p Dave
187  * Made sure the "player/ships" locked button for multiplayer appears on
188  * all briefing screens.
189  * 
190  * 106   4/21/98 6:45p Dave
191  * AL: Fix bug with replacement weapons on ships
192  * 
193  * 105   4/17/98 5:27p Dave
194  * More work on the multi options screen. Fixed many minor ui todo bugs.
195  * 
196  * 104   4/16/98 8:05p Lawrance
197  * fix some bugs with numbers over-writing weapon icons
198  * 
199  * 103   4/10/98 4:51p Hoffoss
200  * Made several changes related to tooltips.
201  * 
202  * 102   4/08/98 1:18a Lawrance
203  * Fix bug that could occur when picking alternate weapons (ie count could
204  * have been wrong due to missile size)
205  * 
206  * 101   4/07/98 5:42p Dave
207  * Put in support for ui display of voice system status (recording,
208  * playing back, etc). Make sure main hall music is stopped before
209  * entering a multiplayer game via ingame join.
210  * 
211  * 100   4/02/98 11:40a Lawrance
212  * check for #ifdef DEMO instead of #ifdef DEMO_RELEASE
213  * 
214  * 99    3/31/98 1:50p Duncan
215  * ALAN: fix bugs with selecting alternate weapons 
216  * 
217  * 98    3/30/98 12:18a Lawrance
218  * change some DEMO_RELEASE code to not compile code rather than return
219  * early
220  * 
221  * 97    3/29/98 1:24p Dave
222  * Make chatbox not clear between multiplayer screens. Select player ship
223  * as default in mp team select and weapons select screens. Made create
224  * game mission list use 2 fixed size columns.
225  * 
226  * 96    3/29/98 12:55a Lawrance
227  * Get demo build working with limited set of data.
228  * 
229  * 95    3/26/98 5:47p Lawrance
230  * Implement default weapon picking if default weapons not available in
231  * pool
232  * 
233  * 94    3/25/98 8:43p Hoffoss
234  * Changed anim_play() to not be so damn complex when you try and call it.
235  * 
236  * 93    3/25/98 11:23a Mike
237  * Fix stack overwrite due to async between MAX_SECONDARY_WEAPONS and
238  * MAX_WL_SECONDARY.
239  * 
240  * 92    3/21/98 2:47p Dave
241  * Fixed chat packet routing problem on standalone. Fixed wss_request
242  * packet routing on standalone.
243  * 
244  * 91    3/19/98 5:34p Lawrance
245  * Tweak drag/drop behavior in weapons loadout
246  * 
247  * 90    3/14/98 2:48p Dave
248  * Cleaned up observer joining code. Put in support for file xfers to
249  * ingame joiners (observers or not). Revamped and reinstalled pseudo
250  * lag/loss system.
251  * 
252  * 89    3/12/98 4:03p Lawrance
253  * don't press buttons when icon dropped on them
254  * 
255  * 88    3/10/98 1:35p Lawrance
256  * Fix default selected weapon bug
257  * 
258  * 87    3/09/98 9:55p Lawrance
259  * Move secondary icons to the right to avoid overlap with numbers
260  * 
261  * 86    3/09/98 11:13a Lawrance
262  * Fix up drop sound effects used in loadout screens.
263  * 
264  * 85    3/06/98 5:36p Dave
265  * Finished up first rev of team vs team. Probably needs to be debugged
266  * thoroughly.
267  * 
268  * 84    3/05/98 5:03p Dave
269  * More work on team vs. team support for multiplayer. Need to fix bugs in
270  * weapon select.
271  * 
272  * 83    3/01/98 3:26p Dave
273  * Fixed a few team select bugs. Put in multiplayer intertface sounds.
274  * Corrected how ships are disabled/enabled in team select/weapon select
275  * screens.
276  * 
277  * 82    2/28/98 7:04p Lawrance
278  * Don't show reset button in multiplayer
279  * 
280  * 81    2/27/98 11:32a Andsager
281  * AL: Fix bug with showing valid weapon slots for ships that arrive late.
282  * 
283  * 80    2/26/98 4:59p Allender
284  * groundwork for team vs team briefings.  Moved weaponry pool into the
285  * Team_data structure.  Added team field into the p_info structure.
286  * Allow for mutliple structures in the briefing code.
287  * 
288  * 79    2/24/98 6:21p Lawrance
289  * Integrate new reset button into loadout screens
290  * 
291  * 78    2/22/98 4:17p John
292  * More string externalization classification... 190 left to go!
293  * 
294  * 77    2/22/98 12:19p John
295  * Externalized some strings
296  * 
297  * 76    2/19/98 6:26p Dave
298  * Fixed a few file xfer bugs. Tweaked mp team select screen. Put in
299  * initial support for player data uploading.
300  * 
301  * 75    2/18/98 10:37p Dave
302  * Fixed a mp team select bug which allowed players to commit at
303  * inappropriate times.
304  * 
305  * 74    2/18/98 3:56p Dave
306  * Several bugs fixed for mp team select screen. Put in standalone packet
307  * routing for team select.
308  * 
309  * 73    2/16/98 10:27a Lawrance
310  * Fix bug in wl_cull_illegal_weapons()
311  * 
312  * 72    2/15/98 11:28p Allender
313  * allow increase in MAX_WEAPON_TYPES by chaning all bitfield references
314  * 
315  * 71    2/13/98 5:15p Lawrance
316  * Fix help overlay bug in weapons loadout.
317  * 
318  * 70    2/13/98 3:46p Dave
319  * Put in dynamic chatbox sizing. Made multiplayer file lookups use cfile
320  * functions.
321  * 
322  * 69    2/09/98 11:24p Lawrance
323  * Allow player to click on disallowed weapons, but don't let them drag
324  * them away from the list.
325  * 
326  * 68    2/07/98 5:47p Lawrance
327  * reset flashing if a button gets highlighted
328  * 
329  * 67    2/06/98 5:15p Jasen
330  * AL: Allow up to 10000 of any given missile in the pool
331  * 
332  * 66    2/05/98 11:21p Lawrance
333  * When flashing buttons, use highlight frame
334  * 
335  * 65    2/02/98 3:36p Jasen
336  * AL: remove weapon debug name, and allow for 2 frame weapon anis
337  * 
338  * 64    2/02/98 3:21p Jasen
339  * Updated coords for weapon anim location.
340  * 
341  * 63    1/20/98 5:52p Lawrance
342  * account for no player ship when moving to weapons loadout
343  * 
344  * 62    1/20/98 2:23p Dave
345  * Removed optimized build warnings. 99% done with ingame join fixes.
346  * 
347  * 61    1/20/98 11:08a Lawrance
348  * Fix sound error when clicking on a weapon.
349  * 
350  * 60    1/19/98 2:17p Lawrance
351  * Fix bug that was not recognizing non-default weapons on late-arriving
352  * wings.
353  * 
354  * 59    1/15/98 4:09p Lawrance
355  * fix weapon scrolling bug
356  * 
357  * 58    1/14/98 6:44p Lawrance
358  * Take out unnecessary instance checking when freeing anims.
359  * 
360  * 57    1/12/98 5:17p Dave
361  * Put in a bunch of multiplayer sequencing code. Made weapon/ship select
362  * work through the standalone.
363  * 
364  * 56    1/10/98 12:47a Lawrance
365  * update some comments
366  * 
367  * 55    1/09/98 6:06p Dave
368  * Put in network sound support for multiplayer ship/weapon select
369  * screens. Made clients exit game correctly through warp effect. Fixed
370  * main hall menu help overlay bug.
371  * 
372  * 54    1/09/98 4:08p John
373  * Fixed a bug loading too many icon frames
374  * 
375  * 53    1/08/98 10:55p Lawrance
376  * Fix bug where forbidden weapons were not updated when a ship was
377  * changed before weapons loadout is entered.
378  * 
379  * 52    1/08/98 5:19p Sandeep
380  * Alan made a change which fixed missions with more than 4 types of
381  * secondary weapons.
382  * 
383  * 51    1/08/98 11:38a Lawrance
384  * correct typo
385  * 
386  * 50    1/08/98 11:36a Lawrance
387  * Get ship select and weapons loadout icon dropping sound effects working
388  * for single and multiplayer
389  * 
390  * 49    1/02/98 9:10p Lawrance
391  * Big changes to how colors get set on the HUD.
392  * 
393  * 48    12/30/97 6:08p Lawrance
394  * Fix bug where player discarded ship before entering weapon select
395  * 
396  * 47    12/29/97 4:21p Lawrance
397  * Flash buttons on briefing/ship select/weapons loadout when enough time
398  * has elapsed without activity.
399  * 
400  * 46    12/29/97 10:11a Lawrance
401  * Don't play drop sound when a weapon is clicked on in a slot.
402  * 
403  * 45    12/24/97 8:54p Lawrance
404  * Integrating new popup code
405  * 
406  * 44    12/24/97 1:19p Lawrance
407  * fix some bugs with the multiplayer ship/weapons loadout
408  * 
409  * 43    12/23/97 5:25p Allender
410  * more fixes to multiplayer ship selection.  Fixed strange reentrant
411  * problem with cf_callback when loading freespace data
412  * 
413  * 42    12/23/97 11:59a Allender
414  * changes to ship/wespon selection for multplayer.  added sounds to some
415  * interface screens.  Update and modiied end-of-briefing packets -- yet
416  * to be tested.
417  * 
418  * 41    12/23/97 11:48a Lawrance
419  * fix bug that could cause assert when swapping secondary weapons
420  * 
421  * 40    12/22/97 6:18p Lawrance
422  * Get save/restore of player loadout working with new code
423  * 
424  * 39    12/22/97 1:40a Lawrance
425  * Re-write ship select/weapons loadout to be multiplayer friendly
426  * 
427  * 38    12/19/97 1:23p Dave
428  * Put in multiplayer groundwork for new weapon/ship select screens.
429  * 
430  * 37    12/19/97 12:44p Dave
431  * Put in final touches on ship/weapon select. However, this is all going
432  * to be rewritten.
433  * 
434  * $NoKeywords: $
435  */
436
437 #include "missionscreencommon.h"
438 #include "missionweaponchoice.h"
439 #include "missionshipchoice.h"
440 #include "timer.h"
441 #include "key.h"
442 #include "mouse.h"
443 #include "bmpman.h"
444 #include "2d.h"
445 #include "snazzyui.h"
446 #include "animplay.h"
447 #include "freespace.h"
448 #include "gamesequence.h"
449 #include "multi.h"
450 #include "missionbrief.h"
451 #include "ui.h"
452 #include "gamesnd.h"
453 #include "animplay.h"
454 #include "contexthelp.h"
455 #include "chatbox.h"
456 #include "linklist.h"
457 #include "multimsgs.h"
458 #include "popup.h"
459 #include "multiteamselect.h"
460 #include "multiui.h"
461 #include "alphacolors.h"
462 #include "localize.h"
463
464 //#define MAX_PRIMARY_BANKS             3
465 //#define MAX_SECONDARY_BANKS   3       //      Lowered from 5 to 3 by MK on 3/25/98.  This needs to be <= MAX_WL_SECONDARY or you'll get stack overwrites.
466
467 #define IS_BANK_PRIMARY(x)                      (x<3?1:0)
468 #define IS_BANK_SECONDARY(x)            (x>2?1:0)
469
470 #define IS_LIST_PRIMARY(x)                      (Weapon_info[x].subtype==WP_MISSILE?0:1)
471 #define IS_LIST_SECONDARY(x)            (Weapon_info[x].subtype==WP_MISSILE?1:0)
472
473 //XSTR:OFF
474 #if (MAX_PRIMARY_BANKS > MAX_WL_PRIMARY)
475 #error "Illegal: MAX_PRIMARY_BANKS greater than MAX_WL_PRIMARY"
476 #endif
477
478 #if (MAX_SECONDARY_BANKS > MAX_WL_SECONDARY)
479 #error "Illegal: MAX_SECONDARY_BANKS greater than MAX_WL_SECONDARY"
480 #endif
481 //XSTR:ON
482
483 //////////////////////////////////////////////////////////////////
484 // Game-wide globals
485 //////////////////////////////////////////////////////////////////
486
487 // This game-wide global flag is set to 1 to indicate that the weapon
488 // select screen has been opened and memory allocated.  This flag
489 // is needed so we can know if weapon_select_close() needs to called if
490 // restoring a game from the Options screen invoked from weapon select
491 int Weapon_select_open = 0;
492
493 //////////////////////////////////////////////////////////////////
494 // UI Data
495 //////////////////////////////////////////////////////////////////
496
497 typedef struct wl_bitmap_group
498 {
499         int first_frame;
500         int num_frames;
501 } wl_bitmap_group;
502
503 #ifdef FS2_DEMO
504 #define WEAPON_ANIM_LOOP_FRAME                          1
505 #else
506 #define WEAPON_ANIM_LOOP_FRAME                          52                      // frame (from 0) to loop weapon anim
507 #endif
508
509 #define WEAPON_ICON_FRAME_NORMAL                                0
510 #define WEAPON_ICON_FRAME_HOT                                   1
511 #define WEAPON_ICON_FRAME_SELECTED                      2
512 #define WEAPON_ICON_FRAME_DISABLED                      3
513
514 // Weapn loadout specific buttons
515 #define NUM_WEAPON_BUTTONS                                              7
516 #define WL_BUTTON_SCROLL_PRIMARY_UP                     0
517 #define WL_BUTTON_SCROLL_PRIMARY_DOWN           1
518 #define WL_BUTTON_SCROLL_SECONDARY_UP           2
519 #define WL_BUTTON_SCROLL_SECONDARY_DOWN 3
520 #define WL_BUTTON_RESET                                                 4
521 #define WL_BUTTON_DUMMY                                                 5
522 #define WL_BUTTON_MULTI_LOCK                                    6
523 UI_WINDOW       Weapon_ui_window;
524 //UI_BUTTON     Weapon_buttons[NUM_WEAPON_BUTTONS];
525
526 static char *Wl_mask_single[GR_NUM_RESOLUTIONS] = {
527         "weaponloadout-m",
528         "2_weaponloadout-m"
529 };
530
531 static char *Wl_mask_multi[GR_NUM_RESOLUTIONS] = {
532         "weaponloadoutmulti-m",
533         "2_weaponloadoutmulti-m"
534 };
535
536 static char *Wl_loadout_select_mask[GR_NUM_RESOLUTIONS] = {
537         "weaponloadout-m",
538         "2_weaponloadout-m"
539 };
540
541
542 static char *Weapon_select_background_fname[GR_NUM_RESOLUTIONS] = {
543         "WeaponLoadout",
544         "2_WeaponLoadout"
545 };
546
547 static char *Weapon_select_multi_background_fname[GR_NUM_RESOLUTIONS] = {
548         "WeaponLoadoutMulti",
549         "2_WeaponLoadoutMulti"
550 };
551
552 int Weapon_select_background_bitmap;    // bitmap for weapon select brackground
553
554 static MENU_REGION      Weapon_select_region[NUM_WEAPON_REGIONS];
555 static int                              Num_weapon_select_regions;
556
557 // Mask bitmap pointer and Mask bitmap_id
558 static bitmap*  WeaponSelectMaskPtr;            // bitmap pointer to the weapon select mask bitmap
559 static ubyte*   WeaponSelectMaskData;   // pointer to actual bitmap data
560 static int              Weaponselect_mask_w, Weaponselect_mask_h;
561 static int              WeaponSelectMaskBitmap; // bitmap id of the weapon select mask bitmap
562
563
564 // convenient struct for handling all button controls
565 struct wl_buttons {
566         char *filename;
567         int x, y, xt, yt;
568         int hotspot;
569         UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..
570
571         wl_buttons(char *name, int x1, int y1, int xt1, int yt1, int h) : filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h) {}
572 };
573
574 static wl_buttons Buttons[GR_NUM_RESOLUTIONS][NUM_WEAPON_BUTTONS] = {
575         {
576                 wl_buttons("WLB_26",            24,     125,            -1,             -1,     26),
577                 wl_buttons("WLB_27",            24,     276,            -1,             -1,     27),
578                 wl_buttons("WLB_08",            24,     303,            -1,             -1,     8),
579                 wl_buttons("WLB_09",            24,     454,            -1,             -1,     9),
580                 wl_buttons("ssb_39",            571,    347,            -1,             -1,     39),
581                 wl_buttons("ssb_39",            0,              0,                      -1,             -1,     99),
582                 wl_buttons("TSB_34",            603,    374,            -1,             -1,     34)
583         },
584         {
585                 wl_buttons("2_WLB_26",  39,     200,            -1,             -1,     26),
586                 wl_buttons("2_WLB_27",  39,     442,            -1,             -1,     27),
587                 wl_buttons("2_WLB_08",  39,     485,            -1,             -1,     8),
588                 wl_buttons("2_WLB_09",  39,     727,            -1,             -1,     9),
589                 wl_buttons("2_ssb_39",  913,    556,            -1,             -1,     39),
590                 wl_buttons("2_ssb_39",  0,              0,                      -1,             -1,     99),
591                 wl_buttons("2_TSB_34",  966,    599,            -1,             -1,     34)
592         }
593 };
594
595 //static wl_bitmap_group wl_button_bitmaps[NUM_WEAPON_BUTTONS];
596
597 static int Weapon_button_scrollable[NUM_WEAPON_BUTTONS] = {0, 0, 0, 0, 0, 0, 0};
598
599 #define MAX_WEAPON_ICONS_ON_SCREEN 8
600
601 // X and Y locations of the weapon icons in the scrollable lists
602 //int Weapon_icon_x[MAX_WEAPON_ICONS_ON_SCREEN] = {27, 27, 27, 27, 36, 36, 36, 36};
603 //int Weapon_icon_y[MAX_WEAPON_ICONS_ON_SCREEN] = {152, 182, 212, 242, 331, 361, 391, 421};
604 static int Wl_weapon_icon_coords[GR_NUM_RESOLUTIONS][MAX_WEAPON_ICONS_ON_SCREEN][2] = {
605         {
606                 {27, 152},
607                 {27, 182},
608                 {27, 212},
609                 {27, 242},
610                 {36, 331},
611                 {36, 361},
612                 {36, 391},
613                 {36, 421}
614         },
615         {
616                 {59, 251},
617                 {59, 299},
618                 {59, 347},
619                 {59, 395},
620                 {59, 538},
621                 {59, 586},
622                 {59, 634},
623                 {59, 682}
624         }
625 };
626
627
628 static int Wl_bank_coords[GR_NUM_RESOLUTIONS][MAX_WL_WEAPONS][2] = {
629         {
630                 {106,127},
631                 {106,158},
632                 {106,189},
633                 {322,127},
634                 {322,158},
635                 {322,189},
636                 {322,220},
637         },
638         {
639                 {170,203},
640                 {170,246},
641                 {170,290},
642                 {552,203},
643                 {552,246},
644                 {552,290},
645                 {552,333},
646         }
647 };
648
649 static int Wl_bank_count_draw_flags[MAX_WL_WEAPONS] = { 
650         0, 0, 0,                        // primaries -- dont draw counts
651         1, 1, 1, 1              // secondaries -- do draw counts
652 };
653
654
655 static int Weapon_anim_class = -1;
656 static int Last_wl_ship_class;
657
658 static int Wl_overhead_coords[GR_NUM_RESOLUTIONS][2] = {
659         {
660                 // GR_640
661                 91, 117
662         },                      
663         {
664                 // GR_1024
665                 156, 183
666         }
667 };
668
669 static int Wl_weapon_ani_coords[GR_NUM_RESOLUTIONS][2] = {
670         {
671                 408, 82                 // GR_640
672         },
673         {
674                 648, 128                        // GR_1024
675         }
676 };
677
678 static int Wl_weapon_ani_coords_multi[GR_NUM_RESOLUTIONS][2] = {
679         {
680                 408, 143                        // GR_640
681         },
682         {
683                 648, 226                        // GR_1024
684         }
685 };
686
687
688 static int Wl_weapon_desc_coords[GR_NUM_RESOLUTIONS][2] = {
689         {
690                 508, 283                // GR_640
691         },
692         {
693                 813, 453                // GR_1024
694         }
695 };
696
697 static int Wl_delta_x, Wl_delta_y;
698
699 static int Wl_ship_name_coords[GR_NUM_RESOLUTIONS][2] = {
700         {
701                 85, 106
702         },
703         {
704                 136, 170
705         }
706 };
707
708
709 ///////////////////////////////////////////////////////////////////////
710 // UI data structs
711 ///////////////////////////////////////////////////////////////////////
712 typedef struct wl_ship_class_info
713 {
714         int                             overhead_bitmap;
715         anim_t                          *anim;
716         anim_instance_t *anim_instance;
717 } wl_ship_class_info;
718
719 wl_ship_class_info      Wl_ships[MAX_SHIP_TYPES];
720
721 typedef struct wl_icon_info
722 {
723         int                             icon_bmaps[NUM_ICON_FRAMES];
724         int                             current_icon_bmap;
725         int                             can_use;
726         anim_t                          *anim;
727         anim_instance_t *anim_instance;
728 } wl_icon_info;
729
730 wl_icon_info    Wl_icons_teams[MAX_TEAMS][MAX_WEAPON_TYPES];
731 wl_icon_info    *Wl_icons;
732
733 int Plist[MAX_WEAPON_TYPES];    // used to track scrolling of primary icon list
734 int Plist_start, Plist_size;
735
736 int Slist[MAX_WEAPON_TYPES];    // used to track scrolling of primary icon list
737 int Slist_start, Slist_size;
738
739 static int Selected_wl_slot = -1;                       // Currently selected ship slot
740 static int Selected_wl_class = -1;                      // Class of weapon that is selected
741 static int Hot_wl_slot = -1;                                    //      Ship slot that mouse is over (0..11)
742 static int Hot_weapon_icon = -1;                                // Icon number (0-7) which has mouse over it
743 static int Hot_weapon_bank = -1;                                // index (0-7) for weapon slot on ship that has a droppable icon over it
744 static int Hot_weapon_bank_icon = -1;
745
746 static int Wl_mouse_down_on_region = -1;
747
748
749 // weapon desc stuff
750 #define WEAPON_DESC_WIPE_TIME                   1.5f                    // time in seconds for wipe to occur (over WEAPON_DESC_MAX_LENGTH number of chars)
751 #define WEAPON_DESC_MAX_LINES                   7                               // max lines in the description incl. title
752 #define WEAPON_DESC_MAX_LENGTH          50                              // max chars per line of description text
753 static int Weapon_desc_wipe_done = 0;
754 static float Weapon_desc_wipe_time_elapsed = 0.0f;
755 static char Weapon_desc_lines[WEAPON_DESC_MAX_LINES][WEAPON_DESC_MAX_LENGTH];                   // 1st 2 lines are title, rest are desc
756
757 // maximum width the weapon title can be -- used in the line breaking 
758 int Weapon_title_max_width[GR_NUM_RESOLUTIONS] = { 200, 320 };
759
760 static int Wl_new_weapon_title_coords[GR_NUM_RESOLUTIONS][2] = {
761         {
762                 408, 75         // GR_640
763         },
764         {
765                 648, 118                // GR_1024
766         }
767 };
768
769 static int Wl_new_weapon_title_coords_multi[GR_NUM_RESOLUTIONS][2] = {
770         {
771                 408, 136                // GR_640
772         },
773         {
774                 648, 216                // GR_1024
775         }
776 };
777
778 static int Wl_new_weapon_desc_coords[GR_NUM_RESOLUTIONS][2] = {
779         {
780                 408, 247                // GR_640
781         },
782         {
783                 648, 395                // GR_1024
784         }
785 };
786
787 static int Wl_new_weapon_desc_coords_multi[GR_NUM_RESOLUTIONS][2] = {
788         {
789                 408, 308                // GR_640
790         },
791         {
792                 648, 493                // GR_1024
793         }
794 };
795
796 // ship select text
797 #define WEAPON_SELECT_NUM_TEXT                  2
798 UI_XSTR Weapon_select_text[GR_NUM_RESOLUTIONS][WEAPON_SELECT_NUM_TEXT] = {
799         { // GR_640
800                 { "Reset",                      1337,           580,    337,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][WL_BUTTON_RESET].button },
801                 { "Lock",                       1270,           602,    364,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][WL_BUTTON_MULTI_LOCK].button }
802         }, 
803         { // GR_1024
804                 { "Reset",                      1337,           938,    546,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][WL_BUTTON_RESET].button },
805                 { "Lock",                       1270,           964,    584,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][WL_BUTTON_MULTI_LOCK].button }
806         }
807 };
808
809
810 ///////////////////////////////////////////////////////////////////////
811 // Carried Icon
812 ///////////////////////////////////////////////////////////////////////
813 typedef struct carried_icon
814 {
815         int weapon_class;               // index Wl_icons[] for carried icon (-1 if carried from bank)
816         int num;                                        // number of units of weapon
817         int from_bank;                  // bank index that icon came from (0..2 primary, 3..6 secondary).  -1 if from list
818         int from_slot;                  // ship slot that weapon is part of 
819         int from_x, from_y;
820 } carried_icon;
821
822 static carried_icon Carried_wl_icon;
823
824 // forward declarations
825 void draw_wl_icons();
826 void wl_draw_ship_weapons(int index);
827 void wl_pick_icon_from_list(int index);
828 void pick_from_ship_slot(int num);
829 void start_weapon_animation(int weapon_class);
830 void stop_weapon_animation();
831 void wl_start_slot_animation(int n);
832 int wl_get_pilot_subsys_index(p_object *pobjp);
833
834 void wl_reset_to_defaults();
835
836 void wl_set_selected_slot(int slot_num);
837 void wl_maybe_reset_selected_slot();
838 void wl_maybe_reset_selected_weapon_class();
839
840 void wl_render_icon_count(int num, int x, int y);
841 void wl_render_weapon_desc();
842
843
844
845 // carry icon functions
846 void wl_reset_carried_icon();
847 int wl_icon_being_carried();
848 void wl_set_carried_icon(int from_bank, int from_slot, int weapon_class);
849
850
851 // Determine hack offset for how to draw fury missile icon. 
852 int wl_fury_missile_offset_hack(int weapon_class, int num_missiles)
853 {
854         if ( weapon_class < 0 ) {
855                 return 0;
856         }
857
858         if ( num_missiles < 100 ) {
859                 return 0 ;
860         }                       
861
862         if ( !strnicmp(Weapon_info[weapon_class].name, NOX("fury"), 4) ) {
863                 return 3;
864         }
865
866         return 0;
867 }
868
869 char *wl_tooltip_handler(char *str)
870 {
871         if (Selected_wl_class < 0)
872                 return NULL;
873
874         if (!stricmp(str, "@weapon_desc")) {
875                 char *str;
876                 int x, y, w, h;
877
878                 str = Weapon_info[Selected_wl_class].desc;
879                 gr_get_string_size(&w, &h, str);
880                 x = Wl_weapon_desc_coords[gr_screen.res][0] - w / 2;
881                 y = Wl_weapon_desc_coords[gr_screen.res][1] - h / 2;
882
883                 gr_set_color_fast(&Color_black);
884                 gr_rect(x - 5, y - 5, w + 10, h + 10);
885
886                 gr_set_color_fast(&Color_bright_white);
887                 gr_string(x, y, str);
888                 return NULL;
889         }
890
891         return NULL;
892 }
893
894 // reset the data inside the Carried_wl_icon
895 void wl_reset_carried_icon()
896 {
897         Carried_wl_icon.weapon_class = -1;
898         Carried_wl_icon.num = 0;
899         Carried_wl_icon.from_bank = -1;
900         Carried_wl_icon.from_slot = -1;
901 }
902
903 // Is an icon being carried?
904 int wl_icon_being_carried()
905 {
906         if ( Carried_wl_icon.weapon_class >= 0 ) {
907                 return 1;
908         }
909
910         return 0;
911 }
912
913 // Set carried icon data 
914 void wl_set_carried_icon(int from_bank, int from_slot, int weapon_class)
915 {
916         int mx,my;
917
918         Carried_wl_icon.from_bank = from_bank;
919         Carried_wl_icon.from_slot = from_slot;
920         Carried_wl_icon.weapon_class = weapon_class;
921
922         mouse_get_pos( &mx, &my );
923         Carried_wl_icon.from_x=mx;
924         Carried_wl_icon.from_y=my;
925
926         Buttons[gr_screen.res][WL_BUTTON_DUMMY].button.capture_mouse();
927 }
928
929 // determine if the carried icon has moved
930 int wl_carried_icon_moved()
931 {
932         int mx, my;
933         mouse_get_pos( &mx, &my );
934         if ( Carried_wl_icon.from_x != mx || Carried_wl_icon.from_y != my) {
935                 return 1;
936         }
937
938         return 0;
939 }
940
941 // return the index for the pilot subsystem in the parse object
942 int wl_get_pilot_subsys_index(p_object *pobjp)
943 {
944         int pilot_index, start_index, end_index, i;
945
946         // see if there is a PILOT subystem
947         start_index = pobjp->subsys_index;
948         end_index = start_index + pobjp->subsys_count;
949         pilot_index = -1;
950         for ( i = start_index; i < end_index; i++ ) {
951                 if ( !stricmp(Subsys_status[i].name, NOX("pilot") ) ) {
952                         pilot_index = i;
953                         break;
954                 }
955         }
956
957         if ( pilot_index == -1 ) {
958                 Error(LOCATION,"Parse object doesn't have a pilot subsystem\n");
959                 return -1;
960         }
961
962         return pilot_index;
963 }
964
965 // Pause the current weapon animation
966 void wl_pause_anim()
967 {
968         if ( Weapon_anim_class >= 0 && Wl_icons[Weapon_anim_class].anim_instance ) {
969                 anim_pause(Wl_icons[Weapon_anim_class].anim_instance);
970         }
971 }
972
973 // Unpause the current weapon animation
974 void wl_unpause_anim()
975 {
976         if ( Weapon_anim_class >= 0 && Wl_icons[Weapon_anim_class].anim_instance ) {
977                 anim_unpause(Wl_icons[Weapon_anim_class].anim_instance);
978         }
979 }
980
981 // ---------------------------------------------------------------------------------
982 // weapon_button_do()
983 //
984 void weapon_button_do(int i)
985 {
986         switch ( i ) {
987                         case PRIMARY_SCROLL_UP:
988                                 if ( common_scroll_up_pressed(&Plist_start, Plist_size, 4) ) {
989                                         gamesnd_play_iface(SND_SCROLL);
990                                 } else {
991                                         gamesnd_play_iface(SND_GENERAL_FAIL);
992                                 }
993                         break;
994
995                         case PRIMARY_SCROLL_DOWN:
996                                 if ( common_scroll_down_pressed(&Plist_start, Plist_size, 4) ) {
997                                         gamesnd_play_iface(SND_SCROLL);
998                                 } else {
999                                         gamesnd_play_iface(SND_GENERAL_FAIL);
1000                                 }
1001                         break;
1002
1003                         case SECONDARY_SCROLL_UP:
1004                                 if ( common_scroll_up_pressed(&Slist_start, Slist_size, 4) ) {
1005                                         gamesnd_play_iface(SND_SCROLL);
1006                                 } else {
1007                                         gamesnd_play_iface(SND_GENERAL_FAIL);
1008                                 }
1009                         break;
1010
1011                         case SECONDARY_SCROLL_DOWN:
1012                                 if ( common_scroll_down_pressed(&Slist_start, Slist_size, 4) ) {
1013                                         gamesnd_play_iface(SND_SCROLL);
1014                                 } else {
1015                                         gamesnd_play_iface(SND_GENERAL_FAIL);
1016                                 }
1017                         break;
1018
1019                         case WL_RESET_BUTTON_MASK:
1020                                 wl_reset_to_defaults();
1021                                 break;
1022
1023                         case WL_BUTTON_MULTI_LOCK:
1024                                 Assert(Game_mode & GM_MULTIPLAYER);                             
1025                                 // the "lock" button has been pressed
1026                                 multi_ts_lock_pressed();
1027
1028                                 // disable the button if it is now locked
1029                                 if(multi_ts_is_locked()){
1030                                         Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.disable();
1031                                 }
1032                                 break;
1033
1034                         default:
1035                         break;
1036         }
1037 }
1038
1039 // -------------------------------------------------------------------
1040 // weapon_check_buttons()
1041 //
1042 // Check if any weapons loadout screen buttons have been pressed, and 
1043 // call weapon_button_do() if they have.
1044 //
1045 void weapon_check_buttons()
1046 {
1047         int                     i;
1048         wl_buttons      *b;
1049
1050         for ( i = 0; i < NUM_WEAPON_BUTTONS; i++ ) {
1051                 b = &Buttons[gr_screen.res][i];
1052                 
1053                 if ( b->button.pressed() ) {
1054                         if(i == WL_BUTTON_MULTI_LOCK){
1055                                 weapon_button_do(i);
1056                         } else {
1057                                 weapon_button_do(b->hotspot);
1058                         }
1059                 }
1060         }
1061 }
1062
1063 // -------------------------------------------------------------------
1064 // wl_redraw_pressed_buttons()
1065 //
1066 // Redraw any weapon loadout buttons that are pressed down.  This function is needed
1067 // since we sometimes need to draw pressed buttons last to ensure the entire
1068 // button gets drawn (and not overlapped by other buttons)
1069 //
1070 void wl_redraw_pressed_buttons()
1071 {
1072         int                     i;
1073         wl_buttons      *b;
1074         
1075         common_redraw_pressed_buttons();
1076
1077         for ( i = 0; i < NUM_WEAPON_BUTTONS; i++ ) {
1078                 b = &Buttons[gr_screen.res][i];
1079                 if ( b->button.button_down() ) {
1080                         b->button.draw_forced(2);
1081                 }
1082         }
1083 }
1084
1085 // ---------------------------------------------------------------------------------
1086 // weapon_buttons_init()
1087 //
1088 void weapon_buttons_init()
1089 {
1090         wl_buttons      *b;
1091         int                     i;
1092
1093         for ( i = 0; i < NUM_WEAPON_BUTTONS; i++ ) {
1094                 b = &Buttons[gr_screen.res][i];
1095                 b->button.create( &Weapon_ui_window, "", Buttons[gr_screen.res][i].x, Buttons[gr_screen.res][i].y, 60, 30, Weapon_button_scrollable[i]);
1096                 // set up callback for when a mouse first goes over a button
1097                 b->button.set_highlight_action( common_play_highlight_sound );
1098                 b->button.set_bmaps(Buttons[gr_screen.res][i].filename);
1099                 b->button.link_hotspot(Buttons[gr_screen.res][i].hotspot);
1100         }
1101
1102         if ( Game_mode & GM_MULTIPLAYER ) {
1103                 Buttons[gr_screen.res][WL_BUTTON_RESET].button.hide();
1104                 Buttons[gr_screen.res][WL_BUTTON_RESET].button.disable();               
1105
1106                 // if we're not the host of the game (or a team captain in team vs. team mode), disable the lock button
1107                 if(Netgame.type_flags & NG_TYPE_TEAM){
1108                         if(!(Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN)){
1109                                 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.disable();          
1110                         }
1111                 } else {
1112                         if(!(Net_player->flags & NETINFO_FLAG_GAME_HOST)){
1113                                 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.disable();                          
1114                         }
1115                 }
1116         } else {                
1117                 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.hide();
1118                 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.disable();
1119         }
1120
1121         // add all xstrs
1122         for(i=0; i<WEAPON_SELECT_NUM_TEXT; i++) {
1123                 Weapon_ui_window.add_XSTR(&Weapon_select_text[gr_screen.res][i]);
1124         }
1125
1126         Buttons[gr_screen.res][WL_BUTTON_DUMMY].button.hide();
1127         Buttons[gr_screen.res][WL_BUTTON_DUMMY].button.disable();       
1128 }
1129
1130 // ---------------------------------------------------------------------------------
1131 // wl_render_overhead_view()
1132 //
1133 void wl_render_overhead_view(float frametime)
1134 {
1135         char                                            name[NAME_LENGTH + CALLSIGN_LEN];
1136         wl_ship_class_info      *wl_ship;
1137         int                                             ship_class;
1138
1139         if ( Selected_wl_slot == -1 ) {
1140                 return;
1141         }
1142
1143         ship_class = Wss_slots[Selected_wl_slot].ship_class;
1144
1145         // check if ship class has changed and maybe play sound
1146         if (Last_wl_ship_class != ship_class) {
1147                 if (Last_wl_ship_class != -1) {
1148                         gamesnd_play_iface(SND_ICON_DROP);
1149                 }
1150                 Last_wl_ship_class = ship_class;
1151         }
1152
1153         wl_ship = &Wl_ships[ship_class];
1154
1155         if ( wl_ship->anim_instance == NULL ) {
1156                 if ( wl_ship->overhead_bitmap < 0 ) {
1157                         // load the bitmap
1158                         if (gr_screen.res == GR_640)
1159                         {
1160                                 // lo-res
1161                                 wl_ship->overhead_bitmap = bm_load(Ship_info[ship_class].overhead_filename);
1162                         } else {
1163                                 // high-res
1164                                 char filename[NAME_LENGTH+2] = "2_";
1165                                 strcat(filename, Ship_info[ship_class].overhead_filename);
1166                                 wl_ship->overhead_bitmap = bm_load(filename);
1167                         }
1168                         if ( wl_ship->overhead_bitmap < 0 ) {
1169                                 Int3();                 // bad things happened
1170                                 return;
1171                         }
1172                 }
1173                 gr_set_bitmap(wl_ship->overhead_bitmap);
1174                 gr_bitmap(Wl_overhead_coords[gr_screen.res][0], Wl_overhead_coords[gr_screen.res][1]);
1175         }
1176
1177         ss_return_name(Selected_wl_slot/4, Selected_wl_slot%4, name);
1178         gr_set_color_fast(&Color_normal);
1179         gr_string(Wl_ship_name_coords[gr_screen.res][0], Wl_ship_name_coords[gr_screen.res][1], name);
1180 }
1181
1182 // ---------------------------------------------------------------------------------
1183 // wl_get_ship_class()
1184 //
1185 //
1186 int wl_get_ship_class(int wl_slot)
1187 {
1188         return Wss_slots[wl_slot].ship_class;
1189 }
1190
1191 //      Return true if weapon_flags indicates a weapon that is legal for use in current game type.
1192 //      Function added by MK on 9/6/99 to support separate legal loadouts for dogfight missions.
1193 int weapon_allowed_for_game_type(int weapon_flags)
1194 {
1195         int     rval = 0;
1196
1197         if ((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)) {
1198                 if (weapon_flags & (1 << 1))
1199                         rval = 1;
1200         } else if (weapon_flags & (1 << 0))
1201                 rval  = 1;
1202
1203         return rval;
1204 }
1205
1206 // go through the possible weapons to choose from, and flag some as disabled since
1207 // that ship class cannot use that kind of weapon.  The weapon filter is specified
1208 // in ships.tbl, where each ship has a list of all the possible weapons it can use.
1209 void wl_set_disabled_weapons(int ship_class)
1210 {
1211         int                             i;
1212         ship_info               *sip;
1213
1214         if ( ship_class == - 1 )
1215                 return;
1216
1217         Assert(ship_class >= 0 && ship_class < MAX_SHIP_TYPES);
1218
1219         sip = &Ship_info[ship_class];
1220
1221         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1222                 //      Determine whether weapon #i is allowed on this ship class in the current type of mission.
1223                 //      As of 9/6/99, the only difference is dogfight missions have a different list of legal weapons.
1224                 Wl_icons[i].can_use = weapon_allowed_for_game_type(sip->allowed_weapons[i]);
1225         }
1226 }
1227
1228 // ---------------------------------------------------------------------------------
1229 // maybe_select_wl_slot()
1230 //
1231 // A slot index was clicked on, mabye change Selected_wl_slot
1232 void maybe_select_wl_slot(int block, int slot)
1233 {
1234         int sidx;
1235
1236         if ( Wss_num_wings <= 0 )
1237                 return;
1238
1239         sidx = block*4 + slot;
1240         if ( Wss_slots[sidx].ship_class < 0 ) {
1241                 return;
1242         }
1243
1244         wl_set_selected_slot(sidx);
1245 }
1246
1247 // ---------------------------------------------------------------------------------
1248 // maybe_select_new_weapon()
1249 //
1250 // Change to the weapon that corresponds to index in the weapon list
1251 //
1252 // input:       index           =>              weapon icon index (0-7)
1253 //
1254 void maybe_select_new_weapon(int index)
1255 {
1256         int weapon_class;
1257
1258         // if a weapon is being carried, do nothing
1259         if ( wl_icon_being_carried() ) {
1260                 return;
1261         }
1262
1263         int region_index = ICON_PRIMARY_0+index;
1264         if ( index > 3 ) {
1265                 region_index = ICON_SECONDARY_0 + (index - 4);
1266         }
1267
1268         if ( Wl_mouse_down_on_region != region_index ) {
1269                 return;
1270         }
1271
1272         if ( index < 4 ) {
1273                 weapon_class = Plist[Plist_start+index];
1274         } else {
1275                 weapon_class = Slist[Slist_start+index-4];
1276         }
1277
1278         if ( weapon_class >= 0 ) {
1279                 Selected_wl_class = weapon_class;
1280                 wl_pick_icon_from_list(index);
1281         }
1282 }
1283
1284 // ---------------------------------------------------------------------------------
1285 // maybe_select_new_ship_weapon()
1286 //
1287 // Change to the weapon that corresponds to the ship weapon slot
1288 //
1289 // input: index ->      index of bank (0..2 primary, 0..6 secondary)
1290 void maybe_select_new_ship_weapon(int index)
1291 {
1292         int *wep, *wep_count;
1293
1294         if ( Selected_wl_slot == -1 )
1295                 return;
1296
1297         if ( wl_icon_being_carried() ) {
1298                 return;
1299         }
1300
1301         wep = Wss_slots[Selected_wl_slot].wep;
1302         wep_count = Wss_slots[Selected_wl_slot].wep_count;
1303
1304         if ( wep[index] < 0 || wep_count[index] <= 0 ) {
1305                 return;
1306         }
1307
1308         if ( Wl_mouse_down_on_region != (ICON_SHIP_PRIMARY_0+index) ) {
1309                 return;
1310         }
1311
1312
1313         Selected_wl_class = wep[index];
1314 }
1315
1316 // Initialize Wl_pool[] to mission deafult
1317 void wl_init_pool(team_data *td)
1318 {
1319         int i;
1320
1321         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1322                 Wl_pool[i] = -1;
1323         }
1324
1325         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1326                 Wl_pool[i] = td->weaponry_pool[i];      // read from mission
1327         }
1328 }
1329
1330 // load the icons for a specific ship class
1331 void wl_load_icons(int weapon_class)
1332 {
1333         wl_icon_info    *icon;
1334         int                             first_frame, num_frames, i;
1335
1336         icon = &Wl_icons[weapon_class];
1337
1338         first_frame = bm_load_animation(Weapon_info[weapon_class].icon_filename, &num_frames);
1339         if ( first_frame == -1 ) {
1340                 Int3(); // Could not load in icon frames.. get Alan
1341                 return;
1342         }
1343
1344         for ( i = 0; i < num_frames ; i++ ) {
1345                 icon->icon_bmaps[i] = first_frame+i;
1346         }
1347 }
1348
1349 // Load in a specific weapon animation.  The data is loaded as a memory-mapped file since these animations
1350 // can be large.
1351 void wl_load_anim(int weapon_class)
1352 {
1353         char animation_filename[CF_MAX_FILENAME_LENGTH+4];
1354         wl_icon_info    *icon;
1355
1356         icon = &Wl_icons[weapon_class];
1357         Assert( icon->anim == NULL );
1358         
1359         // 1024x768 SUPPORT
1360         // If we are in 1024x768, we first want to append "2_" in front of the filename
1361         if (gr_screen.res == GR_1024) {
1362                 Assert(strlen(Weapon_info[weapon_class].anim_filename) <= 30);
1363                 strcpy(animation_filename, "2_");
1364                 strcat(animation_filename, Weapon_info[weapon_class].anim_filename);
1365
1366                 // now check if file exists
1367                 // GRR must add a .ANI at the end for detection
1368                 strcat(animation_filename,".ani");
1369                 icon->anim = anim_load(animation_filename, 1);
1370
1371                 if (icon->anim == NULL) {
1372                         mprintf(("Weapon ANI: Can not find %s, using lowres version instead.\n",animation_filename)); 
1373                         strcpy(animation_filename, Weapon_info[weapon_class].anim_filename);
1374                         icon->anim = anim_load(animation_filename, 1);
1375                 }
1376
1377                 /*
1378                 if (!cf_exist(animation_filename, CF_TYPE_INTERFACE)) {
1379                         // file does not exist, use original low res version
1380                         mprintf(("Weapon ANI: Can not find %s, using lowres version instead.\n",animation_filename)); 
1381                         strcpy(animation_filename, Weapon_info[weapon_class].anim_filename);
1382                 } else {
1383                         animation_filename[strlen(animation_filename) - 4] = '\0';
1384                         mprintf(("Weapon ANI: Found hires version of %s\n",animation_filename));
1385                 }
1386                 */
1387         } else {
1388                 strcpy(animation_filename, Weapon_info[weapon_class].anim_filename);
1389                 // load the compressed ship animation into memory 
1390                 // NOTE: if last parm of load_anim is 1, the anim file is mapped to memory 
1391                 icon->anim = anim_load(animation_filename, 1);
1392         }
1393
1394         if ( icon->anim == NULL ) {
1395                 Int3();         // couldn't load anim filename.. get Alan
1396         }
1397 }
1398
1399 // Load in any weapon animations.  This function assumes that Wl_pool has been inited.
1400 void wl_load_all_anims()
1401 {
1402         #ifndef DEMO // not for FS2_DEMO
1403
1404         int i;
1405
1406         // init anim members for weapon animations
1407         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1408                 Wl_icons[i].anim = NULL;
1409                 Wl_icons[i].anim_instance = NULL;
1410         }
1411
1412         // init anim member for overhead ship animations
1413         for ( i = 0; i < MAX_SHIP_TYPES; i++ ) {
1414                 Wl_ships[i].anim = NULL;
1415                 Wl_ships[i].anim_instance = NULL;
1416         }
1417
1418         // load up the animations used for weapons (they are memory-mapped)
1419         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1420                 if ( Wl_pool[i] > 0 ) {
1421                         wl_load_anim(i);
1422                 }
1423         }
1424
1425         #endif
1426 }
1427
1428 // release any anim instances
1429 void wl_unload_all_anim_instances()
1430 {
1431         // stop any weapon anim instances
1432         for ( int i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1433                 if ( Wl_icons[i].anim_instance ) {
1434                         anim_release_render_instance(Wl_icons[i].anim_instance);
1435                         Wl_icons[i].anim_instance = NULL;
1436                 }
1437         }
1438
1439         // stop any overhead anim instances
1440         for (int i = 0; i < MAX_SHIP_TYPES; i++ ) {
1441                 if ( Wl_ships[i].anim_instance ) {
1442                         anim_release_render_instance(Wl_ships[i].anim_instance);
1443                         Wl_ships[i].anim_instance = NULL;
1444                 }
1445         }
1446 }
1447
1448 // free source anim data if allocated
1449 void wl_unload_all_anims()
1450 {
1451         int i;
1452
1453         // unload overhead anim instances
1454         for ( i = 0; i < MAX_SHIP_TYPES; i++ ) {
1455                 if ( Wl_ships[i].anim ) {
1456                         anim_free(Wl_ships[i].anim);
1457                         Wl_ships[i].anim = NULL;
1458                 }
1459         }
1460
1461         // unload weapon anim instances
1462         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1463                 if ( Wl_icons[i].anim ) {
1464                         anim_free(Wl_icons[i].anim);
1465                         Wl_icons[i].anim = NULL;
1466                 }
1467         }
1468 }
1469
1470 // load all the icons for weapons in the pool
1471 void wl_load_all_icons()
1472 {
1473         #ifndef DEMO // not for FS2_DEMO
1474
1475         int i, j;
1476
1477         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1478                 // clear out data
1479                 Wl_icons[i].anim = NULL;
1480                 Wl_icons[i].anim_instance = NULL;
1481                 for ( j = 0; j < NUM_ICON_FRAMES; j++ ) {
1482                         Wl_icons[i].icon_bmaps[j] = -1;
1483                 }
1484
1485                 if ( Wl_pool[i] > 0 ) {
1486                         wl_load_icons(i);
1487                 }
1488         }
1489
1490         #endif
1491 }
1492
1493 //      wl_unload_icons() frees the bitmaps used for weapon icons 
1494 void wl_unload_icons()
1495 {
1496         int                                     i,j;
1497         wl_icon_info            *icon;
1498
1499         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1500                 icon = &Wl_icons[i];
1501
1502                 for ( j = 0; j < NUM_ICON_FRAMES; j++ ) {
1503                         if ( icon->icon_bmaps[j] >= 0 ) {
1504                                 bm_release(icon->icon_bmaps[j]);
1505                                 icon->icon_bmaps[j] = -1;
1506                         }
1507                 }
1508         }
1509 }
1510
1511 // init ship-class specific data
1512 void wl_init_ship_class_data()
1513 {
1514         int i;
1515         wl_ship_class_info      *wl_ship;
1516
1517         for ( i=0; i<MAX_SHIP_TYPES; i++ ) {
1518                 wl_ship = &Wl_ships[i];
1519                 wl_ship->overhead_bitmap = -1;
1520                 wl_ship->anim = NULL;
1521                 wl_ship->anim_instance = NULL;
1522         }
1523 }
1524
1525 // free any allocated ship-class specific data
1526 void wl_free_ship_class_data()
1527 {
1528         int i;
1529         wl_ship_class_info      *wl_ship;
1530
1531         for ( i=0; i<MAX_SHIP_TYPES; i++ ) {
1532                 wl_ship = &Wl_ships[i];
1533
1534                 if ( wl_ship->overhead_bitmap != -1 ) {
1535                         bm_release(wl_ship->overhead_bitmap);
1536                         wl_ship->overhead_bitmap = -1;
1537                 }
1538
1539                 if ( wl_ship->anim != NULL ) {
1540                         wl_ship->anim = NULL;
1541                 }
1542
1543                 if ( wl_ship->anim_instance != NULL ) {
1544                         wl_ship->anim_instance = NULL;
1545                 }
1546         }
1547 }
1548
1549 // Set selected slot to first placed ship
1550 void wl_reset_selected_slot()
1551 {
1552         int i;
1553         Selected_wl_slot = -1;
1554
1555         // in multiplayer, select the slot of the player's ship by default
1556         if((Game_mode & GM_MULTIPLAYER) && !MULTI_PERM_OBSERVER(Net_players[MY_NET_PLAYER_NUM]) && (Wss_slots[Net_player->p_info.ship_index].ship_class >= 0)){
1557                 wl_set_selected_slot(Net_player->p_info.ship_index);
1558                 return;
1559         }
1560
1561         for ( i=0; i<MAX_WSS_SLOTS; i++ ) {
1562                 if ( !ss_disabled_slot(i) ) {
1563                         if ( ss_wing_slot_is_console_player(i) && (Wss_slots[i].ship_class >= 0) ) {
1564                                 wl_set_selected_slot(i);
1565                                 return;
1566                         }
1567                 }
1568         }
1569
1570         // Didn't locate player ship, so just select the first ship we find
1571         for ( i=0; i<MAX_WSS_SLOTS; i++ ) {
1572                 if ( Wss_slots[i].ship_class >=  0 ) {
1573                         wl_set_selected_slot(i);
1574                         break;
1575                 }
1576         }
1577 }
1578
1579 // called whenever it is possible that the current selected slot has had it's ship disappear
1580 void wl_maybe_reset_selected_slot()
1581 {
1582         int reset=0;
1583
1584         if ( Selected_wl_slot == -1 ) {
1585                 reset = 1;
1586         }
1587
1588         if ( Wss_slots[Selected_wl_slot].ship_class < 0 ) {
1589                 reset = 1;
1590         }
1591
1592         if ( reset ) {
1593                 wl_reset_selected_slot();
1594         }
1595 }
1596
1597 // If Selected_wl_class is -1, choose the first weapon available from the pool for an animation
1598 //  - on second thought, choose the first weapon that is oin the ship, then go to the pools
1599 void wl_maybe_reset_selected_weapon_class()
1600 {
1601         int i;
1602
1603         if ( Selected_wl_class >= 0 ) 
1604                 return;
1605
1606         // try to locate a weapon class to show animation for
1607         // first check for a weapon on the ship
1608         for (i=0; i<MAX_WL_WEAPONS; i++) {
1609                 // if alpha 1 has a weapon in bank i, set it as the selected type
1610                 if (Wss_slots[0].wep_count[i] >= 0) {
1611                         Selected_wl_class = Wss_slots[0].wep[i];
1612                         return;
1613                 }
1614         }
1615
1616         // then check for a primary weapon in the pool
1617         for ( i = 0; i < Plist_size; i++ ) {
1618                 if ( Plist[i] >= 0 ) {
1619                         Selected_wl_class = Plist[i];
1620                         return;
1621                 }
1622         }
1623
1624         // finally, if no others found yet, check for a secondary weapon in the pool
1625         for ( i = 0; i < Slist_size; i++ ) {
1626                 if ( Slist[i] >= 0 ) {
1627                         Selected_wl_class = Slist[i];
1628                         return;
1629                 }
1630         }
1631 }
1632
1633 // start an overhead animation, since selected slot has changed
1634 void wl_start_slot_animation(int n)
1635 {
1636         #ifndef DEMO // not for FS2_DEMO
1637
1638         // don't use ani's
1639         // fallback code in wl_render_overhead_view() will 
1640         // use the .pcx files
1641         // should prolly scrub out the 1e06 lines of dead code this leaves
1642         return;
1643
1644         /*
1645
1646         int                                             ship_class;
1647         wl_ship_class_info      *wl_ship;
1648         anim_play_struct                aps;
1649
1650         if ( n < 0 ) {
1651                 return;
1652         }
1653
1654         ship_class = Wss_slots[n].ship_class;
1655         
1656         if ( ship_class < 0 ) {
1657                 Int3();
1658                 return;
1659         }
1660
1661         wl_ship = &Wl_ships[ship_class];
1662
1663         // maybe this animation is already playing?
1664         if ( wl_ship->anim_instance ) {
1665                 anim_stop_playing(wl_ship->anim_instance);
1666                 wl_ship->anim_instance = NULL;
1667         }
1668         
1669         // maybe we have to load this animation
1670         if ( wl_ship->anim == NULL ) {
1671                 wl_ship->anim = anim_load(Ship_info[ship_class].overhead_filename, 1);
1672                 if ( wl_ship->anim == NULL ) {
1673                         Int3();         // couldn't load anim filename.. get Alan
1674                         return;
1675                 }
1676         }
1677
1678         anim_play_init(&aps, wl_ship->anim, Wl_overhead_coords[gr_screen.res][0], Wl_overhead_coords[gr_screen.res][1]);
1679         aps.screen_id = ON_WEAPON_SELECT;
1680         aps.framerate_independent = 1;
1681         aps.skip_frames = 0;
1682         wl_ship->anim_instance = anim_play(&aps);
1683 */
1684         #endif
1685 }
1686
1687 // Call when Selected_wl_slot needs to be changed
1688 void wl_set_selected_slot(int slot_num)
1689 {
1690         if ( (slot_num >= 0) && (slot_num != Selected_wl_slot) ) {
1691                 // slot has changed.... start an animation
1692                 wl_start_slot_animation(slot_num);
1693 /*
1694                 if ( Current_screen == ON_WEAPON_SELECT ) {
1695                         gamesnd_play_iface(SND_OVERHEAD_SHIP_ANIM);
1696                 }
1697 */
1698   }
1699
1700         Selected_wl_slot = slot_num;
1701         if ( Selected_wl_slot >= 0 ) {
1702                 wl_set_disabled_weapons(Wss_slots[slot_num].ship_class);
1703         }
1704 }
1705
1706 // determine how many missiles of type 'wi_index' will fit into capacity
1707 int wl_calc_missile_fit(int wi_index, int capacity)
1708 {
1709         if ( wi_index < 0 ) {
1710                 return 0;
1711         }
1712
1713         Assert(Weapon_info[wi_index].subtype == WP_MISSILE);
1714         return fl2i( capacity / Weapon_info[wi_index].cargo_size + 0.5f );
1715 }
1716
1717 // fill out the weapons for this ship_class
1718 void wl_get_ship_class_weapons(int ship_class, int *wep, int *wep_count)
1719 {
1720         ship_info       *sip;
1721         int i;
1722
1723         Assert(ship_class >= 0 && ship_class < MAX_SHIP_TYPES);
1724         sip = &Ship_info[ship_class];
1725
1726         // reset weapons arrays
1727         for ( i=0; i < MAX_WL_WEAPONS; i++ ) {
1728                 wep[i] = -1;
1729                 wep_count[i] = -1;      // -1 means weapon bank doesn't exist.. 0 just means it is empty
1730         }
1731
1732         for ( i = 0; i < sip->num_primary_banks; i++ ) {
1733                 wep[i] = sip->primary_bank_weapons[i];
1734                 wep_count[i] = 1;
1735         }
1736
1737         for ( i = 0; i < sip->num_secondary_banks; i++ ) {
1738                 wep[i+MAX_WL_PRIMARY] = sip->secondary_bank_weapons[i];
1739                 wep_count[i+MAX_WL_PRIMARY] = wl_calc_missile_fit(sip->secondary_bank_weapons[i], sip->secondary_bank_ammo_capacity[i]);
1740         }
1741 }
1742
1743 // fill out the wep[] and wep_count[] arrays for a ship
1744 void wl_get_ship_weapons(int ship_index, int *wep, int *wep_count)
1745 {
1746         int                     i;
1747         wing                    *wp;
1748         ship_weapon     *swp;
1749
1750         Assert(ship_index >= 0);
1751
1752         Assert(Ships[ship_index].wingnum >= 0);
1753         wp = &Wings[Ships[ship_index].wingnum];
1754         swp = &Ships[ship_index].weapons;
1755
1756         for ( i = 0; i < swp->num_primary_banks; i++ ) {
1757                 wep[i] = swp->primary_bank_weapons[i];
1758                 wep_count[i] = 1;
1759                 if ( wep[i] == -1 ) {
1760                         wep_count[i] = 0;
1761                 }
1762         }
1763
1764         for ( i = 0; i < swp->num_secondary_banks; i++ ) {
1765                 wep[i+MAX_WL_PRIMARY] = swp->secondary_bank_weapons[i];
1766                 wep_count[i+MAX_WL_PRIMARY] = swp->secondary_bank_ammo[i];
1767                 if ( wep[i+MAX_WL_PRIMARY] == -1 ) {
1768                         wep_count[i+MAX_WL_PRIMARY] = 0;
1769                 }
1770         }
1771 }
1772
1773 // set wep and wep_count from a ship which sits in the ship_arrivals[] list at index sa_index
1774 void wl_get_parseobj_weapons(int sa_index, int ship_class, int *wep, int *wep_count)
1775 {
1776         int                             i,      pilot_index;
1777         subsys_status   *ss;
1778         ship_info               *sip;
1779         p_object                        *pobjp;
1780
1781         pobjp = &ship_arrivals[sa_index];
1782         sip = &Ship_info[ship_class];
1783
1784         pilot_index = wl_get_pilot_subsys_index(pobjp);
1785
1786         if ( pilot_index == -1 )
1787                 return;
1788
1789         ss = &Subsys_status[pilot_index];
1790
1791         if ( ss->primary_banks[0] != SUBSYS_STATUS_NO_CHANGE ) {
1792                 for ( i=0; i < MAX_PRIMARY_BANKS; i++ ) {
1793                         wep[i] = ss->primary_banks[i];          
1794                 } // end for
1795         }
1796
1797         if ( ss->secondary_banks[0] != SUBSYS_STATUS_NO_CHANGE ) {
1798                 for ( i=0; i < MAX_SECONDARY_BANKS; i++ ) {
1799                         wep[i+MAX_WL_PRIMARY] = ss->secondary_banks[i]; 
1800                 } // end for
1801         }
1802
1803         // ammo counts could still be modified
1804         for ( i=0; i < MAX_SECONDARY_BANKS; i++ ) {
1805                 if ( wep[i+MAX_WL_PRIMARY] >= 0 ) {
1806                         wep_count[i+MAX_WL_PRIMARY] = wl_calc_missile_fit(wep[i+MAX_WL_PRIMARY], fl2i(ss->secondary_ammo[i]/100.0f * sip->secondary_bank_ammo_capacity[i] + 0.5f));
1807                 }
1808         }
1809 }
1810
1811 // ensure that there aren't any bogus weapons assigned by default
1812 void wl_cull_illegal_weapons(int ship_class, int *wep, int *wep_count)
1813 {
1814         int i;
1815         for ( i=0; i < MAX_WL_WEAPONS; i++ ) {
1816                 if ( wep[i] < 0 ) {
1817                         continue;
1818                 }
1819
1820                 if ( !weapon_allowed_for_game_type(Ship_info[ship_class].allowed_weapons[wep[i]]) ) {
1821 //                      wep[i] = -1;
1822                         wep_count[i] = 0;
1823                 }
1824         }
1825 }
1826
1827 // get the weapons info that should be on ship by default
1828 void wl_get_default_weapons(int ship_class, int slot_num, int *wep, int *wep_count)
1829 {
1830         int original_ship_class, i;
1831
1832         Assert(slot_num >= 0 && slot_num < MAX_WSS_SLOTS);
1833
1834         // clear out wep and wep_count
1835         for ( i = 0; i < MAX_WL_WEAPONS; i++ ) {
1836                 wep[i] = -1;
1837                 wep_count[i] = -1;
1838         }
1839
1840         if ( ship_class < 0 )
1841                 return;
1842
1843         original_ship_class = ss_return_original_ship_class(slot_num);
1844
1845         if ( original_ship_class != ship_class ) {
1846                 wl_get_ship_class_weapons(ship_class, wep, wep_count);
1847         } else {
1848                 int sa_index;   // ship arrival index
1849                 sa_index = ss_return_saindex(slot_num);
1850
1851                 if ( sa_index >= 0 ) {
1852                         // still a parse object
1853                         wl_get_ship_class_weapons(ship_class, wep, wep_count);
1854                         wl_get_parseobj_weapons(sa_index, ship_class, wep, wep_count);
1855                 } else {
1856                         // ship has been created
1857 //                      wl_get_ship_weapons(slot_num/4, slot_num%4, wep, wep_count);
1858                         int ship_index = -1;
1859                         p_object *pobjp;
1860                         ss_return_ship(slot_num/4, slot_num%4, &ship_index, &pobjp);
1861                         Assert(ship_index != -1);
1862                         wl_get_ship_weapons(ship_index, wep, wep_count);
1863                 }
1864         }
1865
1866         // ensure that there aren't any bogus weapons assigned by default
1867         wl_cull_illegal_weapons(ship_class, wep, wep_count);    
1868 }
1869
1870 // function to add a weapon_class to ui lists
1871 void wl_add_index_to_list(int wi_index)
1872 {
1873         int i;
1874         if ( Weapon_info[wi_index].subtype == WP_MISSILE ) {
1875
1876                 for ( i=0; i<Slist_size; i++ ) {
1877                         if ( Slist[i] == wi_index )
1878                                 break;
1879                 }
1880
1881                 if ( i == Slist_size ) 
1882                         Slist[Slist_size++] = wi_index;
1883
1884         } else {
1885                 for ( i=0; i<Plist_size; i++ ) {
1886                         if ( Plist[i] == wi_index )
1887                                 break;
1888                 }
1889
1890                 if ( i == Plist_size ) 
1891                         Plist[Plist_size++] = wi_index;
1892         }
1893 }
1894
1895 // remove the weapons specificed by wep[] and wep_count[] from Wl_pool[].
1896 void wl_remove_weps_from_pool(int *wep, int *wep_count, int ship_class)
1897 {
1898         int i, wi_index;
1899
1900         for ( i = 0; i < MAX_WL_WEAPONS; i++ ) {
1901                 wi_index = wep[i];
1902                 if ( wi_index >= 0 ) {
1903                         if ( (wep_count[i] > 0) && ((Wl_pool[wi_index] - wep_count[i]) >= 0) ) {
1904                                 Wl_pool[wi_index] -= wep_count[i];
1905                         } else {
1906                                 // not enough weapons in pool
1907                                 // TEMP HACK: FRED doesn't fill in a weapons pool if there are no starting wings... so
1908                                 //            add to the pool.  This should be fixed.
1909                                 if ( Wss_num_wings <= 0 ) {
1910                                         wl_add_index_to_list(wi_index);
1911                                 } else {
1912         
1913                                         if ( (Wl_pool[wi_index] <= 0) || (wep_count[i] == 0) ) {
1914                                                 // fresh out of this weapon, pick an alternate pool weapon if we can
1915                                                 int wep_pool_index, wep_precedence_index, new_wi_index = -1;
1916                                                 for ( wep_pool_index = 0; wep_pool_index < MAX_WEAPON_TYPES; wep_pool_index++ ) {
1917
1918                                                         if ( Wl_pool[wep_pool_index] <= 0 ) {
1919                                                                 continue;
1920                                                         }
1921
1922                                                         // AL 3-31-98: Only pick another primary if primary, etc
1923                                                         if ( Weapon_info[wi_index].subtype != Weapon_info[wep_pool_index].subtype ) {
1924                                                                 continue;
1925                                                         }
1926
1927                                                         if ( !weapon_allowed_for_game_type(Ship_info[ship_class].allowed_weapons[wep_pool_index]) ) {
1928                                                                 continue;
1929                                                         }
1930
1931
1932                                                         for ( wep_precedence_index = 0; wep_precedence_index < Num_player_weapon_precedence; wep_precedence_index++ ) {
1933                                                                 if ( wep_pool_index == Player_weapon_precedence[wep_precedence_index] ) {
1934                                                                         new_wi_index = wep_pool_index;
1935                                                                         break;
1936                                                                 }
1937                                                         }
1938
1939                                                         if ( new_wi_index >= 0 ) {
1940                                                                 break;
1941                                                         }
1942                                                 }
1943
1944                                                 if ( new_wi_index >= 0 ) {
1945                                                         wep[i] = new_wi_index;
1946                                                         wi_index = new_wi_index;
1947                                                 }
1948                                         }
1949
1950                                         int new_wep_count = wep_count[i];
1951                                         if ( Weapon_info[wi_index].subtype == WP_MISSILE ) {
1952                                                 int secondary_bank_index;
1953                                                 secondary_bank_index = i-3;
1954                                                 if ( secondary_bank_index < 0 ) {
1955                                                         Int3();
1956                                                         secondary_bank_index = 0;
1957                                                 }
1958                                                 new_wep_count = wl_calc_missile_fit(wi_index, Ship_info[ship_class].secondary_bank_ammo_capacity[secondary_bank_index]);
1959                                         }
1960
1961                                         wep_count[i] = min(new_wep_count, Wl_pool[wi_index]);
1962                                         Assert(wep_count[i] >= 0);
1963                                         Wl_pool[wi_index] -= wep_count[i];
1964                                         if ( wep_count[i] <= 0 ) {
1965                                                 wep[i] = -1;
1966                                         }
1967                                 }
1968                         }
1969                 }
1970         }
1971 }
1972
1973 // Init the weapons portion of Wss_slots[] and the ui data in Wl_slots[]
1974 // NOTE: it is assumed that Wl_pool[] has been initialized, and Wss_slots[].ship_class is correctly set
1975 void wl_fill_slots()
1976 {
1977         int i, j;       
1978         int wep[MAX_WL_WEAPONS];
1979         int wep_count[MAX_WL_WEAPONS];
1980         
1981         for ( i = 0; i < MAX_WSS_SLOTS; i++ ) {
1982                 if ( Wss_slots[i].ship_class < 0 ){
1983                         continue;
1984                 }
1985
1986                 // get the weapons info that should be on ship by default
1987                 wl_get_default_weapons(Wss_slots[i].ship_class, i, wep, wep_count);
1988                 wl_remove_weps_from_pool(wep, wep_count, Wss_slots[i].ship_class);
1989
1990                 // copy to Wss_slots[]
1991                 for ( j = 0; j < MAX_WL_WEAPONS; j++ ) {
1992                         Wss_slots[i].wep[j] = wep[j];
1993                         Wss_slots[i].wep_count[j] = wep_count[j];
1994                 }
1995         }       
1996 }
1997
1998 // set up the primary and secondary icons lists that hold the weapons the player can choose from
1999 void wl_init_icon_lists()
2000 {
2001         int i;
2002
2003         Plist_start = 0;                // offset into Plist[]
2004         Slist_start = 0;
2005
2006         Plist_size = 0;         // number of active elements in Plist[]
2007         Slist_size = 0;
2008
2009         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
2010                 Plist[i] = -1;
2011                 Slist[i] = -1;
2012         }
2013
2014         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
2015                 if ( Wl_pool[i] > 0 ) {
2016                         if ( Weapon_info[i].subtype == WP_MISSILE ) {
2017                                 Slist[Slist_size++] = i;
2018                         } else {
2019                                 Plist[Plist_size++] = i;
2020                         }
2021                 }
2022         }
2023 }
2024
2025 // initialize team specific weapon select data structures
2026 void weapon_select_init_team(int team_num)
2027 {
2028         Wl_icons = Wl_icons_teams[team_num];
2029         ss_set_team_pointers(team_num);
2030
2031         wl_init_pool(&Team_data[team_num]);
2032         wl_init_icon_lists();
2033         wl_init_ship_class_data();
2034
2035         wl_load_all_icons();
2036         wl_load_all_anims();
2037
2038         wl_fill_slots();
2039 }
2040
2041 // This init is called even before the weapons loadout screen is entered.  It is called when the
2042 // briefing state is entered.
2043 void weapon_select_common_init()
2044 {
2045         int idx;
2046         
2047         if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
2048                 // initialize for all teams
2049                 for(idx=0;idx<MULTI_TS_MAX_TEAMS;idx++){
2050                         weapon_select_init_team(idx);
2051                 }
2052
2053                 // re-initialize for me specifically
2054                 weapon_select_init_team(Common_team);
2055         } else {        
2056                 // initialize for my own team
2057                 weapon_select_init_team(Common_team);
2058         }
2059
2060         wl_reset_selected_slot();
2061         wl_reset_carried_icon();
2062         wl_maybe_reset_selected_weapon_class();
2063 }
2064
2065 // ---------------------------------------------------------------------------------
2066 // weapon_select_init() is called to load the bitmaps and set up the mask regions for
2067 //      the weapon loadout screen.  common_select_init() is called to load the animations
2068 // and bitmaps which are in common with the ship select and briefing screens.
2069 //
2070 // The Weapon_select_open flag is set to 1 when weapon_select_init() completes successfully
2071 //
2072 void weapon_select_init()
2073 {
2074         common_set_interface_palette("WeaponPalette");
2075         common_flash_button_init();
2076
2077         // for multiplayer, change the state in my netplayer structure
2078         if ( Game_mode & GM_MULTIPLAYER )
2079                 Net_player->state = NETPLAYER_STATE_WEAPON_SELECT;
2080
2081         ship_stop_animation();
2082         stop_weapon_animation();
2083         Weapon_anim_class = -1;
2084
2085         set_active_ui(&Weapon_ui_window);
2086         Current_screen = ON_WEAPON_SELECT;
2087         Last_wl_ship_class = -1;
2088
2089         wl_maybe_reset_selected_slot();
2090         wl_set_disabled_weapons(Wss_slots[Selected_wl_slot].ship_class);
2091
2092         help_overlay_set_state(WL_OVERLAY,0);
2093
2094         if ( Weapon_select_open ) {
2095                 wl_maybe_reset_selected_weapon_class();
2096                 wl_start_slot_animation(Selected_wl_slot);
2097                 common_buttons_maybe_reload(&Weapon_ui_window); // AL 11-21-97: this is necessary since we may returning from the hotkey
2098                                                                                                                                                 // screen, which can release common button bitmaps.
2099                 common_reset_buttons();
2100                 nprintf(("Alan","weapon_select_init() returning without doing anything\n"));
2101
2102                 // if we're in multiplayer always select the player's ship
2103                 wl_reset_selected_slot();
2104
2105                 return;
2106         }
2107
2108         nprintf(("Alan","entering weapon_select_init()\n"));
2109         common_select_init();
2110         
2111         WeaponSelectMaskBitmap = bm_load(Wl_loadout_select_mask[gr_screen.res]);
2112         if (WeaponSelectMaskBitmap < 0) {
2113                 if (gr_screen.res == GR_640) {
2114                         Error(LOCATION,"Could not load in 'weaponloadout-m'!");
2115                 } else if (gr_screen.res == GR_1024) {
2116                         Error(LOCATION,"Could not load in '2_weaponloadout-m'!");
2117                 } else {
2118                         Error(LOCATION,"Could not load in 'weaponloadout-m'!");
2119                 }
2120         }
2121
2122         Weaponselect_mask_w = -1;
2123         Weaponselect_mask_h = -1;
2124
2125         // get a pointer to bitmap by using bm_lock()
2126         WeaponSelectMaskPtr = bm_lock(WeaponSelectMaskBitmap, 8, BMP_AABITMAP);
2127         WeaponSelectMaskData = (ubyte*)WeaponSelectMaskPtr->data;
2128         Assert(WeaponSelectMaskData != NULL);
2129         bm_get_info(WeaponSelectMaskBitmap, &Weaponselect_mask_w, &Weaponselect_mask_h);
2130
2131
2132         // Set up the mask regions
2133    // initialize the different regions of the menu that will react when the mouse moves over it
2134         Num_weapon_select_regions = 0;
2135         
2136         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  COMMON_BRIEFING_REGION,                         0);
2137         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  COMMON_SS_REGION,                                               0);
2138         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  COMMON_WEAPON_REGION,                           0);
2139         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  COMMON_COMMIT_REGION,                           0);
2140         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  COMMON_HELP_REGION,                                     0);
2141         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  COMMON_OPTIONS_REGION,                          0);
2142
2143         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_0_SHIP_0,          0);
2144         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_0_SHIP_1,          0);
2145         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_0_SHIP_2,          0);
2146         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_0_SHIP_3,          0);
2147         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_1_SHIP_0,          0);
2148         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_1_SHIP_1,          0);
2149         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_1_SHIP_2,          0);
2150         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_1_SHIP_3,          0);
2151         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_2_SHIP_0,          0);
2152         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_2_SHIP_1,          0);
2153         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_2_SHIP_2,          0);
2154         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  WING_2_SHIP_3,          0);
2155
2156         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_PRIMARY_0,         0);
2157         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_PRIMARY_1,         0);
2158         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_PRIMARY_2,         0);
2159         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_PRIMARY_3,         0);
2160         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SECONDARY_0,               0);
2161         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SECONDARY_1,               0);
2162         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SECONDARY_2,               0);
2163         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SECONDARY_3,               0);
2164
2165         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SHIP_PRIMARY_0,            0);
2166         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SHIP_PRIMARY_1,            0);
2167         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SHIP_PRIMARY_2,            0);
2168         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SHIP_SECONDARY_0,          0);
2169         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SHIP_SECONDARY_1,          0);
2170         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SHIP_SECONDARY_2,          0);
2171         snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "",  ICON_SHIP_SECONDARY_3,          0);
2172
2173         // init common UI
2174         Weapon_ui_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
2175
2176         if(Game_mode & GM_MULTIPLAYER){
2177                 Weapon_ui_window.set_mask_bmap(Wl_mask_multi[gr_screen.res]);
2178         } else {
2179                 Weapon_ui_window.set_mask_bmap(Wl_mask_single[gr_screen.res]);
2180         }
2181
2182         // initialize background bitmap
2183         if(Game_mode & GM_MULTIPLAYER) {
2184                 Weapon_select_background_bitmap = bm_load(Weapon_select_multi_background_fname[gr_screen.res]);
2185         } else {
2186                 Weapon_select_background_bitmap = bm_load(Weapon_select_background_fname[gr_screen.res]);
2187         }
2188
2189         Weapon_ui_window.tooltip_handler = wl_tooltip_handler;
2190         common_buttons_init(&Weapon_ui_window);
2191         weapon_buttons_init();
2192         Weapon_select_open = 1;
2193
2194         // if we're in multiplayer always select the player's ship
2195         wl_reset_selected_slot();
2196 }
2197
2198 // ----------------------------------------------------------------
2199 // wl_dump_carried_icon()
2200 void wl_dump_carried_icon()
2201 {
2202         if ( wl_icon_being_carried() ) {
2203                 // Add back into the weapon pool
2204                 if ( Carried_wl_icon.from_bank >= 0 ) {
2205                         // return to list
2206                         wl_drop(Carried_wl_icon.from_bank, -1, -1, Carried_wl_icon.weapon_class, Carried_wl_icon.from_slot);
2207                 } else {
2208                         if ( wl_carried_icon_moved() ) {
2209                                 gamesnd_play_iface(SND_ICON_DROP);
2210                         }                       
2211                 }
2212
2213                 wl_reset_carried_icon();
2214         }
2215 }
2216
2217 // ----------------------------------------------------------------
2218 // drop_icon_on_slot()
2219 //
2220 // Drop the Carried_wl_icon onto the specified slot.  The slot numbering is:
2221 //
2222 // 0->2: primary weapons
2223 // 3-6: secondary weapons
2224 //
2225 // These are the slots that exist beside the overhead view of the ship.
2226 // on the weapons loadout screen.
2227 //
2228 int drop_icon_on_slot(int bank_num)
2229 {
2230         if ( Selected_wl_slot == -1 ) {
2231                 return 0;
2232         }
2233
2234         if(Game_mode & GM_MULTIPLAYER){
2235                 if(multi_ts_disabled_slot(Selected_wl_slot)){
2236                         return 0;
2237                 }
2238         } else {
2239                 if ( ss_disabled_slot( Selected_wl_slot ) ){
2240                         return 0;
2241                 }
2242         }
2243
2244         // check if slot exists
2245         if ( Wss_slots[Selected_wl_slot].wep_count[bank_num] < 0 ) {
2246                 return 0;
2247         }
2248
2249         if ( !wl_carried_icon_moved() ) {
2250                 wl_reset_carried_icon();
2251                 return 0;
2252         }
2253
2254         wl_drop(Carried_wl_icon.from_bank, Carried_wl_icon.weapon_class, bank_num, -1, Selected_wl_slot);
2255         return 1;
2256 }
2257
2258 // ----------------------------------------------------------------
2259 // maybe_drop_icon_on_slot()
2260 //
2261 void maybe_drop_icon_on_slot(int bank_num)
2262 {
2263         int dropped=0;
2264         if ( !mouse_down(MOUSE_LEFT_BUTTON) ) {
2265                 if ( wl_icon_being_carried() )
2266                         dropped = drop_icon_on_slot(bank_num);
2267
2268                 if ( dropped ) {
2269                         wl_reset_carried_icon();
2270                 }
2271         }
2272 }               
2273
2274 // ----------------------------------------------------------------
2275 // wl_check_for_stopped_ship_anims()
2276 //
2277 void wl_check_for_stopped_ship_anims()
2278 {
2279         int i;
2280         anim_instance *ai;
2281         for ( i = 0; i < MAX_SHIP_TYPES; i++ ) {
2282                 ai = Wl_ships[i].anim_instance;
2283                 if ( ai != NULL ) {
2284                         if ( !anim_playing(ai) ) {
2285                                 Wl_ships[i].anim_instance = NULL;
2286                         }
2287                 }
2288         }
2289 }
2290
2291 // ---------------------------------------------------------------------------------
2292 // do_mouse_over_list_weapon()
2293 //
2294 void do_mouse_over_list_weapon(int index)
2295 {
2296         Hot_weapon_icon = index;
2297
2298         int region_index = ICON_PRIMARY_0+index;
2299         if ( index > 3 ) {
2300                 region_index = ICON_SECONDARY_0 + (index - 4);
2301         }
2302         
2303         if ( Wl_mouse_down_on_region != region_index ){
2304                 return;
2305         }
2306
2307         if ( mouse_down(MOUSE_LEFT_BUTTON) )
2308                 wl_pick_icon_from_list(index);
2309 }
2310
2311 // ---------------------------------------------------------------------------------
2312 // do_mouse_over_ship_weapon()
2313 //
2314 //
2315 // input: index -> bank index on ship (0..6)
2316 //
2317 // returns: 
2318 //          0 -> icon was not dropped on a slot
2319 //                              1 -> icon was dropped on a slot
2320 int do_mouse_over_ship_weapon(int index)
2321 {
2322         int dropped_on_slot, is_moved, mx, my;
2323
2324         dropped_on_slot = 0;
2325         Assert(Selected_wl_slot >= 0);
2326
2327         if ( ss_disabled_slot( Selected_wl_slot ) )
2328                 return 0;
2329
2330         Hot_weapon_bank_icon = index;   // bank icon will be drawn highlighted
2331
2332         if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
2333                 if ( Wl_mouse_down_on_region == (ICON_SHIP_PRIMARY_0+index) ){
2334                         pick_from_ship_slot(index);
2335                 }
2336         } else {
2337                 int was_carried = wl_icon_being_carried();
2338                 maybe_drop_icon_on_slot(index);
2339                 if ( was_carried && !wl_icon_being_carried() ) {
2340                         mouse_get_pos( &mx, &my );
2341                         if ( Carried_wl_icon.from_x != mx || Carried_wl_icon.from_y != my) {
2342                                 dropped_on_slot = 1;
2343                         }
2344                 }
2345         }
2346
2347         // set Hot_weapon_bank if a droppable icon is being held over a slot that
2348         // can accept that icon
2349         is_moved = 0;
2350         mouse_get_pos( &mx, &my );
2351         if ( Carried_wl_icon.from_x != mx || Carried_wl_icon.from_y != my) {
2352                 is_moved = 1;
2353         }
2354
2355         if ( wl_icon_being_carried() && is_moved ) {
2356                 if ( Weapon_info[Carried_wl_icon.weapon_class].subtype != WP_MISSILE ) {
2357                         if ( (index < 3) && (Wss_slots[Selected_wl_slot].wep_count[index] >= 0) ) 
2358                                 Hot_weapon_bank = index;
2359                 } else {
2360                         if ( index >= 3 && ( Wss_slots[Selected_wl_slot].wep_count[index] >= 0) ) 
2361                                 Hot_weapon_bank = index;
2362                 }
2363         }
2364
2365         return dropped_on_slot;
2366 }
2367
2368
2369 // maybe flash a button if player hasn't done anything for a while
2370 void wl_maybe_flash_button()
2371 {
2372         if ( common_flash_bright() ) {
2373                 // commit button
2374                 if ( Common_buttons[Current_screen-1][gr_screen.res][3].button.button_hilighted() ) {
2375                         common_flash_button_init();
2376                 } else {
2377                         Common_buttons[Current_screen-1][gr_screen.res][3].button.draw_forced(1);
2378                 }
2379         }
2380 }
2381
2382
2383 void weapon_select_render(float frametime)
2384 {
2385         if ( !Background_playing ) {
2386                 gr_set_bitmap(Weapon_select_background_bitmap);
2387                 gr_bitmap(0, 0);
2388         }
2389
2390         anim_render_all(0, frametime);
2391         anim_render_all(ON_SHIP_SELECT, frametime);
2392 }
2393
2394 // draw the weapon description text
2395 // this wipes in
2396 void wl_render_weapon_desc(float frametime)
2397 {
2398         int *weapon_desc_coords;
2399         int *weapon_title_coords;
2400
2401         // retrieve the correct set of text coordinates
2402         if (Game_mode & GM_MULTIPLAYER) {
2403                 weapon_desc_coords = Wl_new_weapon_desc_coords_multi[gr_screen.res];
2404                 weapon_title_coords = Wl_new_weapon_title_coords_multi[gr_screen.res];
2405         } else {
2406                 weapon_desc_coords = Wl_new_weapon_desc_coords[gr_screen.res];
2407                 weapon_title_coords = Wl_new_weapon_title_coords[gr_screen.res];
2408         }
2409
2410         // render the normal version of the weapom desc
2411         char bright_char[WEAPON_DESC_MAX_LINES];                        // one bright char per line
2412         if (!Weapon_desc_wipe_done) {
2413                 // draw mid-wipe version
2414                 // decide which char is last (and bright)
2415                 int bright_char_index = (int)(Weapon_desc_wipe_time_elapsed * WEAPON_DESC_MAX_LENGTH / WEAPON_DESC_WIPE_TIME);
2416                 int i, w, h, curr_len;
2417                 
2418                 // draw weapon title (above weapon anim)
2419                 for (i=0; i<2; i++) {
2420                         curr_len = strlen(Weapon_desc_lines[i]);
2421
2422                         if (bright_char_index < curr_len) {
2423                                 // save bright char and plunk in some nulls to shorten string
2424                                 bright_char[i] = Weapon_desc_lines[i][bright_char_index];
2425                                 Weapon_desc_lines[i][bright_char_index] = '\0';
2426
2427                                 // draw the strings
2428                                 gr_set_color_fast(&Color_white);                        
2429                                 gr_string(weapon_title_coords[0], weapon_title_coords[1]+(10*i), Weapon_desc_lines[i]);
2430
2431                                 // draw the bright letters
2432                                 gr_set_color_fast(&Color_bright_white);
2433                                 gr_get_string_size(&w, &h, Weapon_desc_lines[i], curr_len);
2434                                 gr_printf(weapon_title_coords[0]+w, weapon_title_coords[1]+(10*i), "%c", bright_char[i]);
2435
2436                                 // restore the bright char to the string
2437                                 Weapon_desc_lines[i][bright_char_index] = bright_char[i];
2438
2439                         } else {
2440                                 // draw the string
2441                                 gr_set_color_fast(&Color_white);
2442                                 gr_string(weapon_title_coords[0], weapon_title_coords[1]+(10*i), Weapon_desc_lines[i]);
2443                         }
2444                 }
2445
2446                 // draw weapon desc (below weapon anim)
2447                 for (i=2; i<WEAPON_DESC_MAX_LINES; i++) {
2448                         curr_len = strlen(Weapon_desc_lines[i]);
2449
2450                         if (bright_char_index < curr_len) {
2451                                 // save bright char and plunk in some nulls to shorten string
2452                                 bright_char[i] = Weapon_desc_lines[i][bright_char_index];
2453                                 Weapon_desc_lines[i][bright_char_index] = '\0';
2454
2455                                 // draw the string
2456                                 gr_set_color_fast(&Color_white);
2457                                 gr_string(weapon_desc_coords[0], weapon_desc_coords[1]+(10*(i-2)), Weapon_desc_lines[i]);
2458
2459                                 // draw the bright letters
2460                                 gr_set_color_fast(&Color_bright_white);
2461                                 gr_get_string_size(&w, &h, Weapon_desc_lines[i], curr_len);
2462                                 gr_printf(weapon_desc_coords[0]+w, weapon_desc_coords[1]+(10*(i-2)), "%c", bright_char[i]);
2463
2464                                 // restore the bright char to the string
2465                                 Weapon_desc_lines[i][bright_char_index] = bright_char[i];
2466
2467                         } else {
2468                                 // draw the string
2469                                 gr_set_color_fast(&Color_white);
2470                                 gr_string(weapon_desc_coords[0], weapon_desc_coords[1]+(10*(i-2)), Weapon_desc_lines[i]);
2471                         }
2472                 }
2473
2474                 // update time
2475                 Weapon_desc_wipe_time_elapsed += frametime;
2476                 if (Weapon_desc_wipe_time_elapsed >= WEAPON_DESC_WIPE_TIME) {
2477                         // wipe is done,set flag and stop sound
2478                         Weapon_desc_wipe_done = 1;
2479                 }
2480
2481         } else {
2482
2483                 // draw full version
2484                 // FIXME - change to use a for loop 
2485                 gr_set_color_fast(&Color_white);
2486                 gr_string(weapon_title_coords[0], weapon_title_coords[1], Weapon_desc_lines[0]);
2487                 gr_string(weapon_title_coords[0], weapon_title_coords[1] + 10, Weapon_desc_lines[1]);
2488                 gr_string(weapon_desc_coords[0], weapon_desc_coords[1], Weapon_desc_lines[2]);
2489                 gr_string(weapon_desc_coords[0], weapon_desc_coords[1] + 10, Weapon_desc_lines[3]);
2490                 gr_string(weapon_desc_coords[0], weapon_desc_coords[1] + 20, Weapon_desc_lines[4]);
2491                 gr_string(weapon_desc_coords[0], weapon_desc_coords[1] + 30, Weapon_desc_lines[5]);
2492         }
2493 }
2494
2495
2496
2497 // re-inits wiping vars and causes the current text to wipe in again
2498 void wl_weapon_desc_start_wipe()
2499 {
2500         int currchar_src = 0, currline_dest = 2, currchar_dest = 0, i;
2501         int w, h;
2502         int title_len = strlen(Weapon_info[Selected_wl_class].title);
2503
2504         // init wipe vars
2505         Weapon_desc_wipe_time_elapsed = 0.0f;
2506         Weapon_desc_wipe_done = 0;
2507
2508         // break title into two lines if too long
2509         strcpy(Weapon_desc_lines[0], Weapon_info[Selected_wl_class].title);
2510         gr_get_string_size(&w, &h, Weapon_info[Selected_wl_class].title, title_len);
2511         if (w > Weapon_title_max_width[gr_screen.res]) {
2512                 // split
2513                 currchar_src = (int)(((float)title_len / (float)w) * Weapon_title_max_width[gr_screen.res]);                    // char to start space search at
2514                 while (Weapon_desc_lines[0][currchar_src] != ' ') {
2515                         currchar_src--;
2516                         if (currchar_src <= 0) {
2517                                 currchar_src = title_len;
2518                                 break;
2519                         }
2520                 }
2521
2522                 Weapon_desc_lines[0][currchar_src] = '\0';                                                                              // shorten line 0
2523                 strcpy(Weapon_desc_lines[1], &(Weapon_desc_lines[0][currchar_src+1]));          // copy remainder into line 1
2524         } else {
2525                 // entire title in line 0, thus line 1 is empty
2526                 Weapon_desc_lines[1][0] = '\0';
2527         }
2528         
2529         // break current description into lines (break at the /n's)
2530         currchar_src = 0;
2531         while (Weapon_info[Selected_wl_class].desc[currchar_src] != '\0') {
2532                 if (Weapon_info[Selected_wl_class].desc[currchar_src] == '\n') {
2533                         // break here
2534                         if (currchar_src != 0) {                                        // protect against leading /n's
2535                                 Weapon_desc_lines[currline_dest][currchar_dest] = '\0';
2536                                 currline_dest++;
2537                                 currchar_dest = 0;
2538                         }
2539                 } else {
2540                         // straight copy
2541                         Weapon_desc_lines[currline_dest][currchar_dest] = Weapon_info[Selected_wl_class].desc[currchar_src];
2542                         currchar_dest++;
2543                 }
2544
2545                 currchar_src++;
2546
2547                 Assert(currline_dest < WEAPON_DESC_MAX_LINES);
2548                 Assert(currchar_dest < WEAPON_DESC_MAX_LENGTH);
2549         }
2550
2551         // wrap up the line processing
2552         Weapon_desc_lines[currline_dest][currchar_dest] = '\0';
2553         for (i=currline_dest+1; i<WEAPON_DESC_MAX_LINES; i++) {
2554                 Weapon_desc_lines[i][0] = '\0';
2555         }
2556 }
2557
2558
2559
2560 // ---------------------------------------------------------------------------------
2561 // weapon_select_do() is called once per frame while in the weapon loadout screen.  
2562 //
2563 // Calls to common_ functions are made for those functions which are common to the
2564 // ship select and briefing screens.
2565 //
2566 void weapon_select_do(float frametime)
2567 {
2568         int k, wl_choice, snazzy_action;
2569         //char buf[256];
2570
2571         if ( !Weapon_select_open )
2572                 weapon_select_init();
2573
2574         wl_choice = snazzy_menu_do(WeaponSelectMaskData, Weaponselect_mask_w, Weaponselect_mask_h, Num_weapon_select_regions, Weapon_select_region, &snazzy_action, 0);
2575
2576         if ( wl_choice >= 0 ) {
2577                 if ( snazzy_action == SNAZZY_CLICKED ) {
2578                         nprintf(("Alan","got one\n"));
2579                 } 
2580         }
2581
2582         Hot_wl_slot = -1;
2583         Hot_weapon_icon = -1;
2584         Hot_weapon_bank = -1;
2585         Hot_weapon_bank_icon = -1;
2586
2587         k = common_select_do(frametime);
2588         
2589         if ( help_overlay_active(WL_OVERLAY) ) {
2590                 if ( Weapon_anim_class >= 0 && Wl_icons[Weapon_anim_class].anim_instance ) {
2591                         anim_pause(Wl_icons[Weapon_anim_class].anim_instance);
2592                 }
2593         }
2594         else {
2595                 if ( Weapon_anim_class >= 0 && Wl_icons[Weapon_anim_class].anim_instance ) {
2596                         anim_unpause(Wl_icons[Weapon_anim_class].anim_instance);
2597                 }
2598         }
2599
2600         // Check common keypresses
2601         common_check_keys(k);
2602
2603         if ( Mouse_down_last_frame ) {
2604                 Wl_mouse_down_on_region = wl_choice;
2605         }
2606
2607         if ( wl_choice > -1 ) {
2608                 switch(wl_choice) {
2609                         case ICON_PRIMARY_0:
2610                                 do_mouse_over_list_weapon(0);
2611                                 break;
2612                         case ICON_PRIMARY_1:
2613                                 do_mouse_over_list_weapon(1);
2614                                 break;
2615                         case ICON_PRIMARY_2:
2616                                 do_mouse_over_list_weapon(2);
2617                                 break;
2618                         case ICON_PRIMARY_3:
2619                                 do_mouse_over_list_weapon(3);
2620                                 break;
2621                         case ICON_SECONDARY_0:
2622                                 do_mouse_over_list_weapon(4);
2623                                 break;
2624                         case ICON_SECONDARY_1:
2625                                 do_mouse_over_list_weapon(5);
2626                                 break;
2627                         case ICON_SECONDARY_2:
2628                                 do_mouse_over_list_weapon(6);
2629                                 break;
2630                         case ICON_SECONDARY_3:
2631                                 do_mouse_over_list_weapon(7);
2632                                 break;
2633                         case ICON_SHIP_PRIMARY_0:
2634                                 if ( do_mouse_over_ship_weapon(0) )
2635                                         wl_choice = -1;
2636                                 break;
2637                         case ICON_SHIP_PRIMARY_1:
2638                                 if ( do_mouse_over_ship_weapon(1) )
2639                                         wl_choice = -1;
2640                                 break;
2641                         case ICON_SHIP_PRIMARY_2:
2642                                 if ( do_mouse_over_ship_weapon(2) )
2643                                         wl_choice = -1;
2644                                 break;
2645                         case ICON_SHIP_SECONDARY_0:
2646                                 if ( do_mouse_over_ship_weapon(3) )
2647                                         wl_choice = -1;
2648                                 break;
2649                         case ICON_SHIP_SECONDARY_1:
2650                                 if ( do_mouse_over_ship_weapon(4) )
2651                                         wl_choice = -1;
2652                                 break;
2653                         case ICON_SHIP_SECONDARY_2:
2654                                 if ( do_mouse_over_ship_weapon(5) )
2655                                         wl_choice = -1;
2656                                 break;
2657                         case ICON_SHIP_SECONDARY_3:
2658                                 if ( do_mouse_over_ship_weapon(6) )
2659                                         wl_choice = -1;
2660                                 break;
2661                         case WING_0_SHIP_0:
2662                                 Hot_wl_slot = 0;
2663                                 break;
2664                         case WING_0_SHIP_1:
2665                                 Hot_wl_slot = 1;
2666                                 break;
2667                         case WING_0_SHIP_2:
2668                                 Hot_wl_slot = 2;
2669                                 break;
2670                         case WING_0_SHIP_3:
2671                                 Hot_wl_slot = 3;
2672                                 break;
2673                         case WING_1_SHIP_0:
2674                                 Hot_wl_slot = 4;
2675                                 break;
2676                         case WING_1_SHIP_1:
2677                                 Hot_wl_slot = 5;
2678                                 break;
2679                         case WING_1_SHIP_2:
2680                                 Hot_wl_slot = 6;
2681                                 break;
2682                         case WING_1_SHIP_3:
2683                                 Hot_wl_slot = 7;
2684                                 break;
2685                         case WING_2_SHIP_0:
2686                                 Hot_wl_slot = 8;
2687                                 break;
2688                         case WING_2_SHIP_1:
2689                                 Hot_wl_slot = 9;
2690                                 break;
2691                         case WING_2_SHIP_2:
2692                                 Hot_wl_slot = 10;
2693                                 break;
2694                         case WING_2_SHIP_3:
2695                                 Hot_wl_slot = 11;
2696                                 break;
2697
2698                         default:
2699                                 break;
2700                 }       // end switch
2701         }
2702
2703         if ( !mouse_down(MOUSE_LEFT_BUTTON) )  {
2704                 wl_dump_carried_icon();
2705         }
2706
2707         // Check for a mouse click on buttons
2708         common_check_buttons();
2709         weapon_check_buttons();
2710
2711         // Check for the mouse clicks over a region
2712         if ( wl_choice > -1 && snazzy_action == SNAZZY_CLICKED ) {
2713                 switch (wl_choice) {
2714                                 case ICON_PRIMARY_0:
2715                                         maybe_select_new_weapon(0);
2716                                         break;
2717                                 case ICON_PRIMARY_1:
2718                                         maybe_select_new_weapon(1);
2719                                         break;
2720                                 case ICON_PRIMARY_2:
2721                                         maybe_select_new_weapon(2);
2722                                         break;
2723                                 case ICON_PRIMARY_3:
2724                                         maybe_select_new_weapon(3);
2725                                         break;
2726                                 case ICON_SECONDARY_0:
2727                                         maybe_select_new_weapon(4);
2728                                         break;
2729                                 case ICON_SECONDARY_1:
2730                                         maybe_select_new_weapon(5);
2731                                         break;
2732                                 case ICON_SECONDARY_2:
2733                                         maybe_select_new_weapon(6);
2734                                         break;
2735                                 case ICON_SECONDARY_3:
2736                                         maybe_select_new_weapon(7);
2737                                         break;
2738                                 case ICON_SHIP_PRIMARY_0:
2739                                         maybe_select_new_ship_weapon(0);
2740                                         break;
2741                                 case ICON_SHIP_PRIMARY_1:
2742                                         maybe_select_new_ship_weapon(1);
2743                                         break;
2744                                 case ICON_SHIP_PRIMARY_2:
2745                                         maybe_select_new_ship_weapon(2);
2746                                         break;
2747                                 case ICON_SHIP_SECONDARY_0:
2748                                         maybe_select_new_ship_weapon(3);
2749                                         break;
2750                                 case ICON_SHIP_SECONDARY_1:
2751                                         maybe_select_new_ship_weapon(4);
2752                                         break;
2753                                 case ICON_SHIP_SECONDARY_2:
2754                                         maybe_select_new_ship_weapon(5);
2755                                         break;
2756                                 case ICON_SHIP_SECONDARY_3:
2757                                         maybe_select_new_ship_weapon(6);
2758                                         break;
2759                                 case WING_0_SHIP_0:
2760                                         maybe_select_wl_slot(0,0);
2761                                         break;
2762                                 case WING_0_SHIP_1:
2763                                         maybe_select_wl_slot(0,1);
2764                                         break;
2765                                 case WING_0_SHIP_2:
2766                                         maybe_select_wl_slot(0,2);
2767                                         break;
2768                                 case WING_0_SHIP_3:
2769                                         maybe_select_wl_slot(0,3);
2770                                         break;
2771                                 case WING_1_SHIP_0:
2772                                         maybe_select_wl_slot(1,0);
2773                                         break;
2774                                 case WING_1_SHIP_1:
2775                                         maybe_select_wl_slot(1,1);
2776                                         break;
2777                                 case WING_1_SHIP_2:
2778                                         maybe_select_wl_slot(1,2);
2779                                         break;
2780                                 case WING_1_SHIP_3:
2781                                         maybe_select_wl_slot(1,3);
2782                                         break;
2783                                 case WING_2_SHIP_0:
2784                                         maybe_select_wl_slot(2,0);
2785                                         break;
2786                                 case WING_2_SHIP_1:
2787                                         maybe_select_wl_slot(2,1);
2788                                         break;
2789                                 case WING_2_SHIP_2:
2790                                         maybe_select_wl_slot(2,2);
2791                                         break;
2792                                 case WING_2_SHIP_3:
2793                                         maybe_select_wl_slot(2,3);
2794                                         break;
2795
2796                                 default:
2797                                         break;
2798
2799                         }       // end switch
2800                 }
2801
2802         gr_reset_clip();
2803
2804         if ( Weapon_anim_class != -1 && ( Selected_wl_class == Weapon_anim_class ) ) {
2805                 wl_icon_info *icon;
2806                 Assert(Selected_wl_class >= 0 && Selected_wl_class < MAX_WEAPON_TYPES );
2807                 if ( Weapon_anim_class != Selected_wl_class ) 
2808                         start_weapon_animation(Selected_wl_class);      
2809
2810                 Assert(Weapon_anim_class == Selected_wl_class);
2811                 icon = &Wl_icons[Selected_wl_class];
2812                 if ( icon->anim_instance ) {
2813                         if ( icon->anim_instance->frame_num == icon->anim_instance->stop_at ) {
2814                                 anim_play_struct aps;
2815                                 int *weapon_ani_coords;
2816
2817                                 // get the correct weapon animations coords
2818                                 if (Game_mode & GM_MULTIPLAYER) {
2819                                         weapon_ani_coords = Wl_weapon_ani_coords_multi[gr_screen.res];
2820                                 } else {
2821                                         weapon_ani_coords = Wl_weapon_ani_coords[gr_screen.res];
2822                                 }
2823
2824                                 anim_release_render_instance(icon->anim_instance);
2825                                 anim_play_init(&aps, icon->anim, weapon_ani_coords[0], weapon_ani_coords[1]);
2826                                 aps.start_at = WEAPON_ANIM_LOOP_FRAME-1;
2827                                 aps.screen_id = ON_WEAPON_SELECT;
2828                                 aps.framerate_independent = 1;
2829                                 aps.skip_frames = 0;
2830                                 icon->anim_instance = anim_play(&aps);
2831                         }
2832                 }
2833         }
2834
2835         weapon_select_render(frametime);
2836         if ( !Background_playing ) {            
2837                 Weapon_ui_window.draw();
2838                 wl_redraw_pressed_buttons();
2839                 draw_wl_icons();
2840                 anim_render_all(ON_WEAPON_SELECT, frametime);
2841                 wl_check_for_stopped_ship_anims();
2842                 wl_render_overhead_view(frametime);
2843                 wl_draw_ship_weapons(Selected_wl_slot);
2844                 for ( int i = 0; i < MAX_WING_BLOCKS; i++ ) {
2845                         draw_wing_block(i, Hot_wl_slot, Selected_wl_slot, -1);
2846                 }
2847                 common_render_selected_screen_button();
2848         }
2849
2850         // maybe blit the multiplayer "locked" button
2851         if((Game_mode & GM_MULTIPLAYER) && multi_ts_is_locked()){
2852                 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.draw_forced(2);
2853         }
2854
2855
2856         if ( wl_icon_being_carried() ) {
2857                 int mx, my, sx, sy;
2858                 Assert(Carried_wl_icon.weapon_class < MAX_WEAPON_TYPES);
2859                 mouse_get_pos( &mx, &my );
2860                 sx = mx + Wl_delta_x;
2861                 sy = my + Wl_delta_y;
2862
2863
2864                 if ( Wl_icons[Carried_wl_icon.weapon_class].can_use > 0) {
2865                         gr_set_color_fast(&Color_blue);
2866                         gr_set_bitmap(Wl_icons[Carried_wl_icon.weapon_class].icon_bmaps[WEAPON_ICON_FRAME_SELECTED]);
2867                         gr_bitmap(sx, sy);
2868                 }
2869
2870                 // draw number to prevent it from disappearing on clicks
2871                 if ( Carried_wl_icon.from_bank >= MAX_WL_PRIMARY ) {
2872                         if ( mx == Carried_wl_icon.from_x && my == Carried_wl_icon.from_y ) {
2873                                 int num_missiles = Wss_slots[Carried_wl_icon.from_slot].wep_count[Carried_wl_icon.from_bank];
2874                                 //sprintf(buf, "%d", num_missiles);
2875                                 //gr_set_color_fast(&Color_white);
2876
2877                                 //int x_offset = wl_fury_missile_offset_hack(Carried_wl_icon.weapon_class, num_missiles);
2878                                 //gr_string(sx-19-x_offset, sy+8, buf);
2879
2880
2881                                 wl_render_icon_count(num_missiles, Wl_bank_coords[gr_screen.res][Carried_wl_icon.from_bank][0], Wl_bank_coords[gr_screen.res][Carried_wl_icon.from_bank][1]);
2882                         }
2883                 }
2884
2885                 // check so see if this is really a legal weapon to carry away
2886                 if ( !Wl_icons[Carried_wl_icon.weapon_class].can_use ) {
2887                         int diffx, diffy;
2888                         diffx = abs(Carried_wl_icon.from_x-mx);
2889                         diffy = abs(Carried_wl_icon.from_y-my);
2890                         if ( (diffx > 2) || (diffy > 2) ) {
2891                                 int ship_class = Wss_slots[Selected_wl_slot].ship_class;
2892                                 wl_pause_anim();
2893                                 if (Lcl_gr) {
2894                                         // might have to get weapon name translation
2895                                         char display_name[128];
2896                                         strncpy(display_name, Weapon_info[Carried_wl_icon.weapon_class].name, 128);
2897                                         lcl_translate_wep_name(display_name);
2898                                         popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "A %s is unable to carry %s weaponry", 633), Ship_info[ship_class].name, display_name);
2899                                 } else {
2900                                         popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "A %s is unable to carry %s weaponry", 633), Ship_info[ship_class].name, Weapon_info[Carried_wl_icon.weapon_class].name);
2901                                 }
2902                                 wl_unpause_anim();
2903                                 wl_dump_carried_icon();
2904                         }
2905                 }
2906         }
2907
2908         if ( Weapon_anim_class != Selected_wl_class ) {
2909                 start_weapon_animation(Selected_wl_class);
2910         }
2911
2912         // render weapon description text
2913         wl_render_weapon_desc(frametime);
2914
2915         wl_maybe_flash_button();
2916
2917         // should render the chatbox as close to the end as possible so it overlaps all controls
2918         if(!Background_playing){
2919
2920                 // render some extra stuff in multiplayer
2921                 if(Game_mode & GM_MULTIPLAYER){                         
2922                         // render the chatbox
2923                         chatbox_render();
2924
2925                         // draw tooltips
2926                         Weapon_ui_window.draw_tooltip();
2927
2928                         // render the status indicator for the voice system
2929                         multi_common_voice_display_status();
2930
2931                         // blit the "ships/players" locked button
2932                         // multi_ts_blit_locked_button();
2933                 }
2934         }
2935
2936         // blit help overlay if active
2937         help_overlay_maybe_blit(WL_OVERLAY);
2938         gr_flip();      
2939
2940         // If the commit button was pressed, do the commit button actions.  Done at the end of the
2941         // loop so there isn't a skip in the animation (since ship_create() can take a long time if
2942         // the ship model is not in memory
2943         if ( Commit_pressed ) {
2944                 if(Game_mode & GM_MULTIPLAYER){
2945                         multi_ts_commit_pressed();                      
2946                 } else {
2947                         commit_pressed();
2948                 }               
2949                 Commit_pressed = 0;
2950         }
2951 }
2952
2953 // -------------------------------------------------------------------------------
2954 // weapon_select_close() will free the bitmap slot and memory that was allocated
2955 // to store the mask bitmap.
2956 //
2957 // Weapon_select_open is cleared when this function completes.
2958 //
2959 void weapon_select_close()
2960 {
2961         if ( !Weapon_select_open ) {
2962                 nprintf(("Alan","weapon_select_close() returning without doing anything\n"));
2963                 return;
2964         }
2965
2966         nprintf(("Alan", "Entering weapon_select_close()\n"));
2967
2968         stop_weapon_animation();
2969
2970         // done with the bitmaps, so unlock it
2971         bm_unlock(WeaponSelectMaskBitmap);
2972
2973         Weapon_ui_window.destroy();
2974
2975         // unload bitmaps
2976         help_overlay_unload(WL_OVERLAY);
2977
2978         bm_unload(WeaponSelectMaskBitmap);
2979
2980         wl_unload_icons();
2981         wl_unload_all_anim_instances();
2982         wl_unload_all_anims();
2983
2984         Selected_wl_class = -1;
2985         Weapon_select_open = 0;
2986 }
2987
2988
2989 // ------------------------------------------------------------------------
2990 //      wl_render_icon_count()
2991 //              renders the number next to the weapon icon
2992 //
2993 // input:       x,y                     =>              x,y screen position OF THE ICON (NOT where u want the text, 
2994 //                                                                              this is calculated to prevent overlapping)
2995 //                              num                     =>              the actual count to be printed
2996 //
2997 void wl_render_icon_count(int num, int x, int y)
2998 {
2999         char buf[32];
3000         int num_w, num_h;
3001         int number_to_draw = (num > 1000) ? 999 : num;          // cap count @ 999
3002         Assert(number_to_draw >= 0);
3003
3004         sprintf(buf, "%d", number_to_draw);
3005         gr_get_string_size(&num_w, &num_h, buf, strlen(buf));
3006
3007         // render
3008         gr_set_color_fast(&Color_white);
3009         gr_string(x-num_w-4, y+8, buf);
3010 }
3011
3012
3013 // ------------------------------------------------------------------------
3014 //      wl_render_icon()
3015 //
3016 // input:       index                   =>              index into Wl_icons[], identifying which weapon to draw
3017 //                              x,y                     =>              x,y screen position to draw icon at
3018 //                              num                     =>              count for weapon
3019 //                              draw_num_flag =>        0 if not to draw count for weapon, nonzero otherwise
3020 //                              hot_mask                =>              value that should match Hot_weapon_icon to show mouse is over
3021 //                              hot_bank_mask =>        value that should match Hot_weapon_bank_icon to show mouse is over
3022 //                              select_mask     =>              value that should match Selected_wl_class to show icon is selected
3023 //
3024 void wl_render_icon(int index, int x, int y, int num, int draw_num_flag, int hot_mask, int hot_bank_mask, int select_mask)
3025 {
3026         int                             bitmap_id;
3027         wl_icon_info    *icon;
3028
3029         if ( Selected_wl_slot == -1 )
3030                 return;
3031
3032         icon = &Wl_icons[index];
3033
3034         if ( icon->icon_bmaps[0] == -1 ) {
3035                 wl_load_icons(index);
3036         }
3037                 
3038         // assume default bitmap is to be used
3039         bitmap_id = icon->icon_bmaps[WEAPON_ICON_FRAME_NORMAL]; // normal frame
3040
3041         if ( bitmap_id < 0 ) {
3042                 Int3();
3043                 return;
3044         }
3045
3046         // next check if ship has mouse over it
3047         if ( !wl_icon_being_carried() ) {
3048                 if ( Hot_weapon_icon > -1 && Hot_weapon_icon == hot_mask )
3049                         bitmap_id = icon->icon_bmaps[WEAPON_ICON_FRAME_HOT];
3050
3051                 if ( Hot_weapon_bank_icon > -1 && Hot_weapon_bank_icon == hot_bank_mask )
3052                         bitmap_id = icon->icon_bmaps[WEAPON_ICON_FRAME_HOT];
3053         }
3054
3055         // if icon is selected
3056         if ( Selected_wl_class > -1 ) {
3057                 if ( Selected_wl_class == select_mask)
3058                         bitmap_id = icon->icon_bmaps[WEAPON_ICON_FRAME_SELECTED];       // selected icon
3059         }
3060
3061         // if icon is disabled
3062         if ( !icon->can_use ) {
3063                 bitmap_id = icon->icon_bmaps[WEAPON_ICON_FRAME_DISABLED];       // disabled icon
3064         }
3065
3066         gr_set_color_fast(&Color_blue);
3067         gr_set_bitmap(bitmap_id);
3068         gr_bitmap(x, y);
3069
3070         // draw the number of the item
3071         // now, right justified
3072         if ( draw_num_flag != 0 ) {
3073                 wl_render_icon_count(num, x, y);
3074         }
3075 }
3076
3077 // ------------------------------------------------------------------------
3078 //      wl_draw_ship_weapons()
3079 //
3080 // Draw the icons for the weapons that are currently on the selected ship
3081 //
3082 // input:       slot_num                =>              Slot to draw weapons for
3083 //
3084 void wl_draw_ship_weapons(int index)
3085 {
3086         int             i;
3087         int             *wep, *wep_count;
3088
3089         if ( index == -1 )
3090                 return;
3091
3092         Assert(index >= 0 && index < MAX_WSS_SLOTS);
3093         wep = Wss_slots[index].wep;
3094         wep_count = Wss_slots[index].wep_count;
3095
3096         for ( i = 0; i < MAX_WL_WEAPONS; i++ ) {
3097
3098                 if ( Carried_wl_icon.from_bank == i && Carried_wl_icon.from_slot == index ) {
3099                         continue;
3100                 }
3101
3102                 if ( (wep[i] != -1) && (wep_count[i] > 0) ) {
3103                         int x_offset = wl_fury_missile_offset_hack(wep[i], wep_count[i]);
3104                         x_offset =0;
3105                         wl_render_icon( wep[i], Wl_bank_coords[gr_screen.res][i][0]+x_offset, Wl_bank_coords[gr_screen.res][i][1], wep_count[i], Wl_bank_count_draw_flags[i], -1, i, wep[i]);
3106                 }
3107         }
3108 }
3109
3110 // ------------------------------------------------------------------------
3111 //      draw_wl_icon_with_number()
3112 //
3113 // input:       list_count                      =>              list position on screen (0-7)
3114 //                              weapon_class            =>              class of weapon
3115 //
3116 void draw_wl_icon_with_number(int list_count, int weapon_class)
3117 {
3118         Assert( list_count >= 0 && list_count < 8 );    
3119
3120         wl_render_icon(weapon_class, Wl_weapon_icon_coords[gr_screen.res][list_count][0], Wl_weapon_icon_coords[gr_screen.res][list_count][1],
3121                                            Wl_pool[weapon_class], 1, list_count, -1, weapon_class);
3122 }
3123
3124 // ------------------------------------------------------------------------
3125 //      draw_wl_icons()
3126 //
3127 // Draw the weapon icons that are available
3128 void draw_wl_icons()
3129 {
3130         int i, count;
3131
3132         count=0;
3133         for ( i = Plist_start; i < Plist_size; i++ ) {
3134                 draw_wl_icon_with_number(count, Plist[i]);
3135                 if ( ++count > 3 )
3136                         break;
3137         }
3138
3139         count=0;
3140         for ( i = Slist_start; i < Slist_size; i++ ) {
3141                 draw_wl_icon_with_number(count+4, Slist[i]);
3142                 if ( ++count > 3 )
3143                         break;
3144         }
3145 }
3146
3147 // ------------------------------------------------------------------------
3148 // wl_pick_icon_from_list()
3149 //
3150 // determine if an icon from the scrollable weapon list can be picked up 
3151 // (for drag and drop).  It calculates the difference in x & y between the icon
3152 // and the mouse, so we can move the icon with the mouse in a realistic way
3153 // input: index (0..7) 
3154 void wl_pick_icon_from_list(int index)
3155 {
3156         int weapon_class, mx, my;
3157
3158         // if this is a multiplayer game and the player is an observer, he can never pick any weapons up
3159         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
3160                 return;
3161         }
3162
3163         // if a weapon is being carried, do nothing
3164         if ( wl_icon_being_carried() ) {
3165                 return;
3166         }
3167
3168         if ( index < 4 ) {
3169                 weapon_class = Plist[Plist_start+index];
3170         } else {
3171                 weapon_class = Slist[Slist_start+index-4];
3172         }
3173
3174         // there isn't a weapon there at all!
3175         if ( weapon_class < 0 ) 
3176                 return;
3177
3178         // no weapons left of that class
3179         if ( Wl_pool[weapon_class] <= 0 ) {
3180                 return;
3181         }
3182
3183 /*
3184         // some are available, but weapon cannot be used on current ship class
3185         if ( !Wl_icons[weapon_class].can_use ) {
3186                 wl_pause_anim();
3187
3188                 int ship_class = Wss_slots[Selected_wl_slot].ship_class;
3189                 popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, "A %s is unable to carry %s weaponry", Ship_info[ship_class].name, Weapon_info[weapon_class].name);
3190
3191                 wl_unpause_anim();
3192                 return;
3193         }
3194 */
3195
3196         wl_set_carried_icon(-1, -1, weapon_class);
3197         common_flash_button_init();
3198
3199         mouse_get_pos( &mx, &my );
3200         Wl_delta_x = Wl_weapon_icon_coords[gr_screen.res][index][0] - mx;
3201         Wl_delta_y = Wl_weapon_icon_coords[gr_screen.res][index][1] - my;
3202 }
3203
3204 // ------------------------------------------------------------------------
3205 //      pick_from_ship_slot()
3206 //
3207 // input: num   ->      index into shipb banks (0..2 primary, 3..6 secondary)
3208 void pick_from_ship_slot(int num)
3209 {
3210         int mx, my, *wep, *wep_count;
3211                 
3212         Assert(num < 7);
3213
3214         if ( Selected_wl_slot == -1 )
3215                 return;
3216
3217         if ( wl_icon_being_carried() )
3218                 return;
3219
3220         if ( ss_disabled_slot( Selected_wl_slot ) )
3221                 return;
3222
3223         wep = Wss_slots[Selected_wl_slot].wep;
3224         wep_count = Wss_slots[Selected_wl_slot].wep_count;
3225
3226         // check if a weapon even exists in that slot
3227         if ( (wep[num] < 0) || (wep_count[num] <= 0) ) {
3228                 return;
3229         }
3230
3231         Assert(Wl_icons[wep[num]].can_use);
3232
3233         wl_set_carried_icon(num, Selected_wl_slot, wep[num]);
3234         common_flash_button_init();
3235                         
3236         mouse_get_pos( &mx, &my );
3237
3238         int x_offset = wl_fury_missile_offset_hack(wep[num], wep_count[num]);
3239         Wl_delta_x = Wl_bank_coords[gr_screen.res][num][0] - mx + x_offset;
3240         Wl_delta_y = Wl_bank_coords[gr_screen.res][num][1] - my;
3241
3242         Carried_wl_icon.from_x = mx;
3243         Carried_wl_icon.from_y = my;
3244 }
3245
3246 // determine if this slot has no weapons
3247 int wl_slots_all_empty(wss_unit *slot)
3248 {
3249         int                     i;
3250
3251         for ( i = 0; i < MAX_WL_WEAPONS; i++ ) {
3252                 if ( (slot->wep_count[i] > 0) && (slot->wep[i] >= 0) ) 
3253                         return 0;
3254         }
3255
3256         return 1;
3257 }
3258
3259 // ------------------------------------------------------------------------
3260 //      wl_update_ship_weapons()
3261 //
3262 // Change a ship's weapons based on the information contained in the
3263 // Weapon_data[] structure that is filled in during weapon loadout
3264 //
3265 // returns: -1  =>      if the playre ship has no weapons
3266 //                              0       =>      function finished without errors        
3267 int wl_update_ship_weapons(int objnum, wss_unit *slot )
3268 {
3269         // AL 11-15-97: Ensure that the player ship hasn't removed all 
3270         //                                       weapons from their ship.  This will cause a warning to appear.
3271         if ( objnum == OBJ_INDEX(Player_obj) && Weapon_select_open ) {
3272                 if ( wl_slots_all_empty(slot) ) {
3273                         return -1;
3274                 }
3275         }
3276
3277         wl_bash_ship_weapons(&Ships[Objects[objnum].instance].weapons, slot);
3278         return 0;
3279 }
3280
3281
3282 // ------------------------------------------------------------------------
3283 //      wl_update_parse_object_weapons()
3284 //
3285 // Set the Pilot subsystem of a parse_object to the weapons that are setup
3286 // for the wing_block,wing_slot ship
3287 //
3288 // input:       pobjp   =>      pointer to parse object that references Pilot subsystem
3289 //
3290 void wl_update_parse_object_weapons(p_object *pobjp, wss_unit *slot)
3291 {
3292         int                             i,      j, sidx, pilot_index, max_count;
3293         subsys_status   *ss;
3294         ship_info               *sip;
3295
3296         Assert(slot->ship_class >= 0);
3297         sip = &Ship_info[slot->ship_class];
3298
3299         pilot_index = wl_get_pilot_subsys_index(pobjp);
3300
3301         if ( pilot_index == -1 ) 
3302                 return;
3303                                                 
3304         ss = &Subsys_status[pilot_index];
3305
3306         for ( i = 0; i < MAX_PRIMARY_BANKS; i++ ) {
3307                 ss->primary_banks[i] = -1;              
3308         }
3309
3310         for ( i = 0; i < MAX_SECONDARY_BANKS; i++ ) {
3311                 ss->secondary_banks[i] = -1;            
3312         }
3313
3314         j = 0;
3315         for ( i = 0; i < MAX_WL_PRIMARY; i++ ) {
3316                 if ( (slot->wep_count[i] > 0) && (slot->wep[i] >= 0) ) {
3317                         ss->primary_banks[j] = slot->wep[i];
3318                         j++;
3319                 }
3320         }
3321
3322         j = 0;
3323         for ( i = 0; i < MAX_WL_SECONDARY; i++ ) {
3324                 sidx = i+MAX_WL_PRIMARY;
3325                 if ( (slot->wep_count[sidx] > 0) && (slot->wep[sidx] >= 0) ) {
3326                         ss->secondary_banks[j] = slot->wep[sidx];
3327                         // Important: the secondary_ammo[] value is a percentage of max capacity!
3328                         max_count = wl_calc_missile_fit(slot->wep[sidx], Ship_info[slot->ship_class].secondary_bank_ammo_capacity[j]);
3329                         ss->secondary_ammo[j] = fl2i( i2fl(slot->wep_count[sidx]) / max_count * 100.0f + 0.5f);
3330                         j++;
3331                 }
3332         }
3333 }
3334
3335 // ------------------------------------------------------------------------
3336 // stop_weapon_animation()
3337 //
3338 // Stop the current weapon animation from playing.
3339 //
3340 void stop_weapon_animation()
3341 {
3342         if ( Weapon_anim_class < 0 )
3343                 return;
3344
3345         if ( anim_playing(Wl_icons[Weapon_anim_class].anim_instance) )
3346                 anim_release_render_instance(Wl_icons[Weapon_anim_class].anim_instance);
3347
3348         Wl_icons[Weapon_anim_class].anim_instance = NULL;
3349         Weapon_anim_class = -1;
3350 }
3351
3352 // ------------------------------------------------------------------------
3353 // start_weapon_animation()
3354 //
3355 // Start the current weapon animation from playing.
3356 //
3357 void start_weapon_animation(int weapon_class) 
3358 {
3359         wl_icon_info    *icon;
3360         int *weapon_ani_coords;
3361
3362         if ( weapon_class < 0 )
3363                 return;
3364
3365         if ( weapon_class == Weapon_anim_class ) 
3366                 return;
3367
3368         // get the correct weapon animations coords
3369         if (Game_mode & GM_MULTIPLAYER) {
3370                 weapon_ani_coords = Wl_weapon_ani_coords_multi[gr_screen.res];
3371         } else {
3372                 weapon_ani_coords = Wl_weapon_ani_coords[gr_screen.res];
3373         }
3374
3375         icon = &Wl_icons[weapon_class];
3376
3377         // stop current animation playing
3378         stop_weapon_animation();
3379
3380         // see if we need to load in the animation from disk
3381         if ( icon->anim == NULL ) {
3382                 wl_load_anim(weapon_class);
3383                 /*
3384                 icon->anim = anim_load(Weapon_info[weapon_class].anim_filename, 1);
3385                 if ( icon->anim == NULL ) {
3386                         Int3(); // could not open the weapon animation
3387                         return;
3388                 }
3389                 */
3390         }
3391
3392         // see if we need to get an instance
3393         if ( icon->anim_instance == NULL ) {
3394                 anim_play_struct aps;
3395
3396                 anim_play_init(&aps, icon->anim, weapon_ani_coords[0], weapon_ani_coords[1]);
3397                 aps.screen_id = ON_WEAPON_SELECT;
3398                 aps.framerate_independent = 1;
3399                 aps.skip_frames = 0;
3400                 icon->anim_instance = anim_play(&aps);
3401                 gamesnd_play_iface(SND_WEAPON_ANIM_START);
3402         }
3403
3404         Weapon_anim_class = weapon_class;
3405
3406         // start the text wipe
3407         wl_weapon_desc_start_wipe();
3408 }
3409
3410 // reset the weapons loadout to the defaults in the mission
3411 void wl_reset_to_defaults()
3412 {
3413         // don't reset of weapons pool in multiplayer
3414         if(Game_mode & GM_MULTIPLAYER){
3415                 return;
3416         }
3417
3418         wl_init_pool(&Team_data[Common_team]);
3419         wl_init_icon_lists();
3420         wl_fill_slots();
3421         wl_reset_selected_slot();
3422         wl_reset_carried_icon();
3423         wl_maybe_reset_selected_weapon_class();
3424 }
3425
3426 // Bash ship weapons, based on what is stored in the stored weapons loadout
3427 // NOTE: Wss_slots[] is assumed to be correctly set
3428 void wl_bash_ship_weapons(ship_weapon *swp, wss_unit *slot)
3429 {
3430         int             i, j, sidx;
3431         
3432         for ( i = 0; i < MAX_PRIMARY_BANKS; i++ ) {
3433                 swp->primary_bank_weapons[i] = -1;              
3434         }
3435
3436         for ( i = 0; i < MAX_SECONDARY_BANKS; i++ ) {
3437                 swp->secondary_bank_weapons[i] = -1;            
3438         }
3439
3440         j = 0;
3441         for ( i = 0; i < MAX_WL_PRIMARY; i++ ) {
3442                 if ( (slot->wep_count[i] > 0) && (slot->wep[i] >= 0) ) {
3443                         swp->primary_bank_weapons[j] = slot->wep[i];                    
3444                         j++;
3445                 }
3446         }
3447         swp->num_primary_banks = j;
3448
3449         j = 0;
3450         for ( i = 0; i < MAX_WL_SECONDARY; i++ ) {
3451                 sidx = i+MAX_WL_PRIMARY;
3452                 if ( (slot->wep_count[sidx] > 0) && (slot->wep[sidx] >= 0) ) {
3453                         swp->secondary_bank_weapons[j] = slot->wep[sidx];
3454                         swp->secondary_bank_ammo[j] = slot->wep_count[sidx];
3455                         j++;
3456                 }
3457         }
3458         swp->num_secondary_banks = j;
3459 }
3460
3461 // utility function for swapping two banks
3462 void wl_swap_weapons(int ship_slot, int from_bank, int to_bank)
3463 {
3464         wss_unit        *slot;
3465         int     tmp;
3466         slot = &Wss_slots[ship_slot];
3467
3468         if ( from_bank == to_bank ) {
3469                 return;
3470         }
3471
3472         // swap weapon type
3473         tmp = slot->wep[from_bank];
3474         slot->wep[from_bank] = slot->wep[to_bank];
3475         slot->wep[to_bank] = tmp;
3476
3477         // swap weapon count
3478         tmp = slot->wep_count[from_bank];
3479         slot->wep_count[from_bank] = slot->wep_count[to_bank];
3480         slot->wep_count[to_bank] = tmp;
3481 }
3482
3483 // utility function used to put back overflow into the weapons pool
3484 void wl_saturate_bank(int ship_slot, int bank)
3485 {
3486         wss_unit        *slot;
3487         int             max_count, overflow;
3488
3489         slot = &Wss_slots[ship_slot];
3490
3491         if ( (slot->wep[bank] < 0) || (slot->wep_count <= 0) ) {
3492                 return;
3493         }
3494
3495         max_count = wl_calc_missile_fit(slot->wep[bank], Ship_info[slot->ship_class].secondary_bank_ammo_capacity[bank-3]);
3496         overflow = slot->wep_count[bank] - max_count;
3497         if ( overflow > 0 ) {
3498                 slot->wep_count[bank] -= overflow;
3499                 // add overflow back to pool
3500                 Wl_pool[slot->wep[bank]] += overflow;
3501         }
3502 }
3503
3504 // exit: 0 -> no data changed
3505 //                      1 -> data changed
3506 //       sound => gets filled with sound id to play
3507 int wl_swap_slot_slot(int from_bank, int to_bank, int ship_slot, int *sound)
3508 {
3509         wss_unit        *slot;
3510         slot = &Wss_slots[ship_slot];
3511
3512         if ( slot->ship_class == -1 ) {
3513                 Int3(); // should not be possible
3514                 return 0;
3515         }
3516         
3517         // do nothing if swapping with self
3518         if ( from_bank == to_bank ) {
3519                 *sound=SND_ICON_DROP_ON_WING;
3520                 return 0;       // no update
3521         }
3522
3523         // ensure that source bank exists and has something to pick from
3524         if ( slot->wep[from_bank] == -1 || slot->wep_count[from_bank] <= 0 ) {
3525                 return 0;
3526         }
3527
3528         // ensure that the dest bank exists
3529         if ( slot->wep_count[to_bank] < 0 ) {
3530                 return 0;
3531         }
3532
3533         // ensure that the banks are both of the same class
3534         if ( (IS_BANK_PRIMARY(from_bank) && IS_BANK_SECONDARY(to_bank)) || (IS_BANK_SECONDARY(from_bank) && IS_BANK_PRIMARY(to_bank)) ) {
3535                 // put from_bank back into list
3536                 Wl_pool[slot->wep[from_bank]] += slot->wep_count[from_bank];;           // return to list
3537                 slot->wep[from_bank] = -1;                                                                                                              // remove from slot
3538                 slot->wep_count[from_bank] = 0;
3539                 *sound=SND_ICON_DROP;
3540                 return 1;
3541         }
3542
3543         // case 1: primaries (easy)
3544         if ( IS_BANK_PRIMARY(from_bank) && IS_BANK_PRIMARY(to_bank) ) {
3545                 wl_swap_weapons(ship_slot, from_bank, to_bank);
3546                 *sound=SND_ICON_DROP_ON_WING;
3547                 return 1;
3548         }
3549
3550         // case 2: secondaries (harder)
3551         if ( IS_BANK_SECONDARY(from_bank) && IS_BANK_SECONDARY(to_bank) ) {
3552
3553                 // case 2a: secondaries are the same type
3554                 if ( slot->wep[from_bank] == slot->wep[to_bank] ) {
3555                         int dest_max, dest_can_fit, source_can_give;
3556                         dest_max = wl_calc_missile_fit(slot->wep[to_bank], Ship_info[slot->ship_class].secondary_bank_ammo_capacity[to_bank-3]);
3557
3558                         dest_can_fit = dest_max - slot->wep_count[to_bank];
3559
3560                         if ( dest_can_fit <= 0 ) {
3561                                 // dest bank is already full.. nothing to do here
3562                                 return 0;
3563                         }
3564
3565                         // see how much source can give
3566                         source_can_give = min(dest_can_fit, slot->wep_count[from_bank]);
3567
3568                         if ( source_can_give > 0 ) {                    
3569                                 slot->wep_count[to_bank] += source_can_give;            // add to dest
3570                                 slot->wep_count[from_bank] -= source_can_give;  // take from source
3571                                 *sound=SND_ICON_DROP_ON_WING;
3572                                 return 1;
3573                         } else {
3574                                 return 0;
3575                         }
3576                 }
3577
3578                 // case 2b: secondaries are different types
3579                 if ( slot->wep[from_bank] != slot->wep[to_bank] ) {
3580
3581                         // swap 'em 
3582                         wl_swap_weapons(ship_slot, from_bank, to_bank);
3583
3584                         // put back some on list if required
3585                         wl_saturate_bank(ship_slot, from_bank);
3586                         wl_saturate_bank(ship_slot, to_bank);
3587                         *sound=SND_ICON_DROP_ON_WING;
3588                         return 1;
3589                 }
3590         }
3591
3592         Int3();         // should never get here
3593         return 0;
3594 }
3595
3596 // exit: 0 -> no data changed
3597 //                      1 -> data changed
3598 //       sound => gets filled with sound id to play
3599 int wl_dump_to_list(int from_bank, int to_list, int ship_slot, int *sound)
3600 {
3601         wss_unit        *slot;
3602         slot = &Wss_slots[ship_slot];
3603
3604         // ensure that source bank exists and has something to pick from
3605         if ( slot->wep[from_bank] == -1 || slot->wep_count[from_bank] <= 0 ) {
3606                 return 0;
3607         }
3608
3609         // put weapon bank to the list
3610         Wl_pool[to_list] += slot->wep_count[from_bank];                 // return to list
3611         slot->wep[from_bank] = -1;                                                                              // remove from slot
3612         slot->wep_count[from_bank] = 0;
3613         *sound=SND_ICON_DROP;
3614
3615         return 1;
3616 }
3617
3618 // exit: 0 -> no data changed
3619 //                      1 -> data changed
3620 //       sound => gets filled with sound id to play
3621 int wl_grab_from_list(int from_list, int to_bank, int ship_slot, int *sound)
3622 {
3623         wss_unit        *slot;
3624         slot = &Wss_slots[ship_slot];
3625         int max_fit;
3626
3627         // ensure that the banks are both of the same class
3628         if ( (IS_LIST_PRIMARY(from_list) && IS_BANK_SECONDARY(to_bank)) || (IS_LIST_SECONDARY(from_list) && IS_BANK_PRIMARY(to_bank)) ) {
3629                 // do nothing
3630                 *sound=SND_ICON_DROP;
3631                 return 0;
3632         }
3633
3634         // ensure that dest bank exists
3635         if ( slot->wep_count[to_bank] < 0 ) {
3636                 *sound=SND_ICON_DROP;
3637                 return 0;
3638         }
3639
3640         // bank should be empty:
3641         Assert(slot->wep_count[to_bank] == 0);
3642         Assert(slot->wep[to_bank] < 0);
3643
3644         // ensure that pool has weapon
3645         if ( Wl_pool[from_list] <= 0 ) {
3646                 return 0;
3647         }
3648
3649         // find how much dest bank can fit
3650         if ( to_bank < MAX_WL_PRIMARY ) {
3651                 max_fit = 1;
3652         } else {
3653                 max_fit = wl_calc_missile_fit(from_list, Ship_info[slot->ship_class].secondary_bank_ammo_capacity[to_bank-MAX_WL_PRIMARY]);
3654         }
3655
3656         // take weapon from list
3657         if ( Wl_pool[from_list] < max_fit ) {
3658                 max_fit = Wl_pool[from_list];
3659         }
3660         Wl_pool[from_list] -= max_fit;
3661
3662         // put on the slot
3663         slot->wep[to_bank] = from_list;
3664         slot->wep_count[to_bank] = max_fit;
3665
3666         *sound=SND_ICON_DROP_ON_WING;
3667         return 1;
3668 }
3669
3670 // exit: 0 -> no data changed
3671 //                      1 -> data changed
3672 //       sound => gets filled with sound id to play
3673 int wl_swap_list_slot(int from_list, int to_bank, int ship_slot, int *sound)
3674 {
3675         wss_unit        *slot;
3676         slot = &Wss_slots[ship_slot];
3677         int max_fit;
3678
3679         // ensure that the banks are both of the same class
3680         if ( (IS_LIST_PRIMARY(from_list) && IS_BANK_SECONDARY(to_bank)) || (IS_LIST_SECONDARY(from_list) && IS_BANK_PRIMARY(to_bank)) ) {
3681                 // do nothing
3682                 *sound=SND_ICON_DROP;
3683                 return 0;
3684         }
3685
3686         // ensure that dest bank exists
3687         if ( slot->wep_count[to_bank] < 0 ) {
3688                 return 0;
3689         }
3690
3691         // bank should have something in it
3692         Assert(slot->wep_count[to_bank] > 0);
3693         Assert(slot->wep[to_bank] >= 0);
3694
3695         // ensure that pool has weapon
3696         if ( Wl_pool[from_list] <= 0 ) {
3697                 return 0;
3698         }
3699
3700         // dump slot weapon back into list
3701         Wl_pool[slot->wep[to_bank]] += slot->wep_count[to_bank];
3702         slot->wep_count[to_bank] = 0;
3703         slot->wep[to_bank] = -1;
3704
3705         // put weapon on ship from list
3706         
3707         // find how much dest bank can fit
3708         if ( to_bank < MAX_WL_PRIMARY ) {
3709                 max_fit = 1;
3710         } else {
3711                 max_fit = wl_calc_missile_fit(from_list, Ship_info[slot->ship_class].secondary_bank_ammo_capacity[to_bank-MAX_WL_PRIMARY]);
3712         }
3713
3714         // take weapon from list
3715         if ( Wl_pool[from_list] < max_fit ) {
3716                 max_fit = Wl_pool[from_list];
3717         }
3718         Wl_pool[from_list] -= max_fit;
3719
3720         // put on the slot
3721         slot->wep[to_bank] = from_list;
3722         slot->wep_count[to_bank] = max_fit;
3723
3724         *sound=SND_ICON_DROP_ON_WING;
3725         return 1;
3726 }
3727
3728 // update any interface data that may be dependent on Wss_slots[] 
3729 void wl_synch_interface()
3730 {
3731 }
3732
3733 void wl_apply(int mode,int from_bank,int from_list,int to_bank,int to_list,int ship_slot,int player_index)
3734 {
3735         int update=0;
3736         int sound=-1;
3737         net_player *pl;
3738
3739         // get the appropriate net player
3740         if(Game_mode & GM_MULTIPLAYER){
3741                 if(player_index == -1){
3742                         pl = Net_player;
3743                 } else {
3744                         pl = &Net_players[player_index];
3745                 }
3746         } else {
3747                 pl = NULL;
3748         }
3749
3750         switch(mode){
3751         case WSS_SWAP_SLOT_SLOT:
3752                 update = wl_swap_slot_slot(from_bank, to_bank, ship_slot, &sound);
3753                 break;
3754         case WSS_DUMP_TO_LIST:
3755                 update = wl_dump_to_list(from_bank, to_list, ship_slot, &sound);
3756                 break;
3757         case WSS_GRAB_FROM_LIST:
3758                 update = wl_grab_from_list(from_list, to_bank, ship_slot, &sound);
3759                 break;
3760         case WSS_SWAP_LIST_SLOT:
3761                 update = wl_swap_list_slot(from_list, to_bank, ship_slot, &sound);
3762                 break;
3763         }
3764
3765         // only play this sound if the move was done locally (by the host in other words)
3766         if ( (sound >= 0) && (player_index == -1) ) {   
3767                 gamesnd_play_iface(sound);      
3768         }       
3769
3770         if ( update ) {
3771                 if ( MULTIPLAYER_HOST ) {
3772                         int size;
3773                         ubyte wss_data[MAX_PACKET_SIZE-20];
3774
3775                         size = store_wss_data(wss_data, MAX_PACKET_SIZE-20,sound,player_index);                 
3776                         Assert(pl != NULL);
3777                         send_wss_update_packet(pl->p_info.team,wss_data, size);
3778                 }
3779
3780                 if(Game_mode & GM_MULTIPLAYER){
3781                         Assert(pl != NULL);
3782
3783                         // if the pool we're using has changed, synch stuff up
3784                         if(pl->p_info.team == Net_player->p_info.team){
3785                                 wl_synch_interface();                   
3786                         }
3787                 } else {
3788                         wl_synch_interface();
3789                 }
3790         }               
3791 }
3792
3793 void wl_drop(int from_bank,int from_list,int to_bank,int to_list, int ship_slot, int player_index)
3794 {
3795         int mode;
3796         net_player *pl;
3797
3798         // get the appropriate net player
3799         if(Game_mode & GM_MULTIPLAYER){
3800                 if(player_index == -1){
3801                         pl = Net_player;
3802                 } else {
3803                         pl = &Net_players[player_index];
3804                 }
3805         } else {
3806                 pl = NULL;
3807         }
3808
3809         common_flash_button_init();
3810         if ( !(Game_mode & GM_MULTIPLAYER) || MULTIPLAYER_HOST ) {
3811                 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
3812                         // set the global pointers to the right pools
3813                         ss_set_team_pointers(pl->p_info.team);
3814                 }
3815
3816
3817                 mode = wss_get_mode(from_bank, from_list, to_bank, to_list, ship_slot);
3818                 if ( mode >= 0 ) {
3819                         wl_apply(mode, from_bank, from_list, to_bank, to_list, ship_slot, player_index);
3820                 }               
3821
3822                 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
3823                         // set the global pointers to the right pools
3824                         ss_set_team_pointers(Net_player->p_info.team);
3825                 }
3826         } else {
3827                 send_wss_request_packet(Net_player->player_id, from_bank, from_list, to_bank, to_list, ship_slot, -1, WSS_WEAPON_SELECT);
3828         }
3829 }
3830