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