2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/MissionUI/MissionWeaponChoice.cpp $
15 * C module for the weapon loadout screen
18 * Revision 1.8 2005/03/29 02:18:47 taylor
19 * Various 64-bit platform fixes
20 * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
21 * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
22 * Streaming audio support (big thanks to Pierre Willenbrock!!)
23 * Removed dependance on strings.tbl for FS1 since we don't actually need it now
25 * Revision 1.7 2004/09/20 01:31:44 theoddone33
28 * Revision 1.6 2003/06/11 18:30:33 taylor
31 * Revision 1.5 2003/05/25 02:30:43 taylor
34 * Revision 1.4 2002/06/16 01:43:23 relnev
35 * fixed demo dogfight multiplayer mission
39 * Revision 1.3 2002/06/09 04:41:23 relnev
40 * added copyright header
42 * Revision 1.2 2002/05/07 03:16:46 theoddone33
43 * The Great Newline Fix
45 * Revision 1.1.1.1 2002/05/03 03:28:10 root
49 * 40 11/01/99 11:22a Jefff
50 * some weapon name translations
52 * 39 9/10/99 10:26a Jefff
53 * default weapon anim selection fix
55 * 38 9/06/99 3:30p Mikek
56 * Added system for restricting weapon choices based on ship class for
59 * 37 8/27/99 11:59a Jefff
60 * fixed unnecessary sound playing
62 * 36 8/05/99 3:40p Jefff
63 * hi-res text adjustments
65 * 35 8/05/99 11:32a Jefff
66 * fixed hi-res weapon anims not loading from packfile
68 * 34 7/30/99 4:35p Andsager
69 * Clean up change ship sound
71 * 33 7/30/99 4:22p Andsager
72 * restored ship and weapon anim sounds for demo. Added sound for
73 * changing ship in weapon loadout screen.
75 * 32 7/27/99 7:34p Jefff
76 * Lotsa clean up, moving stuff around, generally making the whole damn
79 * 31 7/27/99 3:01p Jefff
80 * crippled wl_start_slot_animation to prevent loading of overhead ship
81 * .anis. also began modifications for multiplayer interface.
83 * 30 7/25/99 5:49p Jefff
84 * initial weapon ani is now one of the ship's weapons. this will fall
85 * back to the original search if the ship should be weaponless.
87 * 29 7/24/99 6:03p Jefff
88 * Added "lock" text to multiplayer lock button
90 * 28 7/21/99 6:02p Jefff
91 * fixed weapon counts running into weapon icons
93 * 27 7/21/99 3:24p Andsager
94 * Modify demo to use 2 frame ship and weapon select anis and cut sounds
97 * 26 7/20/99 7:07p Jefff
98 * added "reset" text above reset button
100 * 25 7/20/99 1:48p Jefff
101 * Long weapon titles now wrap to next line
103 * 24 7/20/99 10:44a Jefff
104 * increased WEAPON_DESC_MAX_LINES to 6
106 * 23 7/20/99 12:26a Jefff
109 * 22 7/19/99 5:08p Jefff
110 * Added text descriptions for selected weapons, complete with wipe
113 * 21 7/16/99 1:50p Dave
114 * 8 bit aabitmaps. yay.
116 * 20 7/15/99 9:20a Andsager
117 * FS2_DEMO initial checkin
119 * 19 7/11/99 3:20p Kellys
120 * Make sure we load high-res weapon rotations in 1024
122 * 18 7/09/99 5:54p Dave
123 * Seperated cruiser types into individual types. Added tons of new
124 * briefing icons. Campaign screen.
126 * 17 7/09/99 12:21a Dave
127 * Change weapon loop anim frame.
129 * 16 3/25/99 2:45p Neilk
132 * 15 3/23/99 9:23p Neilk
133 * fixed various multiplayer lock button problems
135 * 14 3/10/99 6:21p Neilk
136 * Added new artwork for hires
138 * 13 2/21/99 6:01p Dave
139 * Fixed standalone WSS packets.
141 * 12 2/18/99 11:46a Neilk
142 * hires interface coord support
144 * 11 2/11/99 3:08p Dave
145 * PXO refresh button. Very preliminary squad war support.
147 * 10 2/01/99 5:55p Dave
148 * Removed the idea of explicit bitmaps for buttons. Fixed text
149 * highlighting for disabled gadgets.
151 * 9 1/30/99 1:29a Dave
152 * Fixed nebula thumbnail problem. Full support for 1024x768 choose pilot
153 * screen. Fixed beam weapon death messages.
155 * 8 1/29/99 4:17p Dave
156 * New interface screens.
158 * 7 1/27/99 9:56a Dave
159 * Temporary checkin of beam weapons for Dan to make cool sounds.
161 * 6 12/18/98 1:13a Dave
162 * Rough 1024x768 support for Direct3D. Proper detection and usage through
165 * 5 11/30/98 1:07p Dave
166 * 16 bit conversion, first run.
168 * 4 11/17/98 11:12a Dave
169 * Removed player identification by address. Now assign explicit id #'s.
171 * 3 10/13/98 9:29a Dave
172 * Started neatening up freespace.h. Many variables renamed and
173 * reorganized. Added AlphaColors.[h,cpp]
175 * 2 10/07/98 10:53a Dave
178 * 1 10/07/98 10:50a Dave
180 * 119 6/17/98 11:06a Lawrance
181 * put in weapon description tooltip
183 * 118 6/13/98 6:01p Hoffoss
184 * Externalized all new (or forgot to be added) strings to all the code.
186 * 117 6/01/98 11:43a John
187 * JAS & MK: Classified all strings for localization.
189 * 116 5/19/98 8:35p Dave
190 * Revamp PXO channel listing system. Send campaign goals/events to
191 * clients for evaluation. Made lock button pressable on all screens.
193 * 115 5/18/98 2:49p Lawrance
194 * Put in weapon animation sound hook
196 * 114 5/08/98 7:52p Lawrance
197 * Add code to loop new weapon animations
199 * 113 5/06/98 11:50p Lawrance
200 * Clean up help overlay code for loadout screens
202 * 112 5/04/98 5:27p Johnson
203 * Fixed a team vs. team weapons loadout bug.
205 * 111 5/03/98 1:55a Lawrance
206 * Fix some sound problems with loadout screens
208 * 110 4/30/98 6:03p Lawrance
209 * Make drag and drop work better.
211 * 109 4/27/98 6:02p Dave
212 * Modify how missile scoring works. Fixed a team select ui bug. Speed up
213 * multi_lag system. Put in new main hall.
215 * 108 4/24/98 2:17a Lawrance
216 * repositioin ship name in weapons loadout
218 * 107 4/22/98 7:24p Dave
219 * Made sure the "player/ships" locked button for multiplayer appears on
220 * all briefing screens.
222 * 106 4/21/98 6:45p Dave
223 * AL: Fix bug with replacement weapons on ships
225 * 105 4/17/98 5:27p Dave
226 * More work on the multi options screen. Fixed many minor ui todo bugs.
228 * 104 4/16/98 8:05p Lawrance
229 * fix some bugs with numbers over-writing weapon icons
231 * 103 4/10/98 4:51p Hoffoss
232 * Made several changes related to tooltips.
234 * 102 4/08/98 1:18a Lawrance
235 * Fix bug that could occur when picking alternate weapons (ie count could
236 * have been wrong due to missile size)
238 * 101 4/07/98 5:42p Dave
239 * Put in support for ui display of voice system status (recording,
240 * playing back, etc). Make sure main hall music is stopped before
241 * entering a multiplayer game via ingame join.
243 * 100 4/02/98 11:40a Lawrance
244 * check for #ifdef DEMO instead of #ifdef DEMO_RELEASE
246 * 99 3/31/98 1:50p Duncan
247 * ALAN: fix bugs with selecting alternate weapons
249 * 98 3/30/98 12:18a Lawrance
250 * change some DEMO_RELEASE code to not compile code rather than return
253 * 97 3/29/98 1:24p Dave
254 * Make chatbox not clear between multiplayer screens. Select player ship
255 * as default in mp team select and weapons select screens. Made create
256 * game mission list use 2 fixed size columns.
258 * 96 3/29/98 12:55a Lawrance
259 * Get demo build working with limited set of data.
261 * 95 3/26/98 5:47p Lawrance
262 * Implement default weapon picking if default weapons not available in
265 * 94 3/25/98 8:43p Hoffoss
266 * Changed anim_play() to not be so damn complex when you try and call it.
268 * 93 3/25/98 11:23a Mike
269 * Fix stack overwrite due to async between MAX_SECONDARY_WEAPONS and
272 * 92 3/21/98 2:47p Dave
273 * Fixed chat packet routing problem on standalone. Fixed wss_request
274 * packet routing on standalone.
276 * 91 3/19/98 5:34p Lawrance
277 * Tweak drag/drop behavior in weapons loadout
279 * 90 3/14/98 2:48p Dave
280 * Cleaned up observer joining code. Put in support for file xfers to
281 * ingame joiners (observers or not). Revamped and reinstalled pseudo
284 * 89 3/12/98 4:03p Lawrance
285 * don't press buttons when icon dropped on them
287 * 88 3/10/98 1:35p Lawrance
288 * Fix default selected weapon bug
290 * 87 3/09/98 9:55p Lawrance
291 * Move secondary icons to the right to avoid overlap with numbers
293 * 86 3/09/98 11:13a Lawrance
294 * Fix up drop sound effects used in loadout screens.
296 * 85 3/06/98 5:36p Dave
297 * Finished up first rev of team vs team. Probably needs to be debugged
300 * 84 3/05/98 5:03p Dave
301 * More work on team vs. team support for multiplayer. Need to fix bugs in
304 * 83 3/01/98 3:26p Dave
305 * Fixed a few team select bugs. Put in multiplayer intertface sounds.
306 * Corrected how ships are disabled/enabled in team select/weapon select
309 * 82 2/28/98 7:04p Lawrance
310 * Don't show reset button in multiplayer
312 * 81 2/27/98 11:32a Andsager
313 * AL: Fix bug with showing valid weapon slots for ships that arrive late.
315 * 80 2/26/98 4:59p Allender
316 * groundwork for team vs team briefings. Moved weaponry pool into the
317 * Team_data structure. Added team field into the p_info structure.
318 * Allow for mutliple structures in the briefing code.
320 * 79 2/24/98 6:21p Lawrance
321 * Integrate new reset button into loadout screens
323 * 78 2/22/98 4:17p John
324 * More string externalization classification... 190 left to go!
326 * 77 2/22/98 12:19p John
327 * Externalized some strings
329 * 76 2/19/98 6:26p Dave
330 * Fixed a few file xfer bugs. Tweaked mp team select screen. Put in
331 * initial support for player data uploading.
333 * 75 2/18/98 10:37p Dave
334 * Fixed a mp team select bug which allowed players to commit at
335 * inappropriate times.
337 * 74 2/18/98 3:56p Dave
338 * Several bugs fixed for mp team select screen. Put in standalone packet
339 * routing for team select.
341 * 73 2/16/98 10:27a Lawrance
342 * Fix bug in wl_cull_illegal_weapons()
344 * 72 2/15/98 11:28p Allender
345 * allow increase in MAX_WEAPON_TYPES by chaning all bitfield references
347 * 71 2/13/98 5:15p Lawrance
348 * Fix help overlay bug in weapons loadout.
350 * 70 2/13/98 3:46p Dave
351 * Put in dynamic chatbox sizing. Made multiplayer file lookups use cfile
354 * 69 2/09/98 11:24p Lawrance
355 * Allow player to click on disallowed weapons, but don't let them drag
356 * them away from the list.
358 * 68 2/07/98 5:47p Lawrance
359 * reset flashing if a button gets highlighted
361 * 67 2/06/98 5:15p Jasen
362 * AL: Allow up to 10000 of any given missile in the pool
364 * 66 2/05/98 11:21p Lawrance
365 * When flashing buttons, use highlight frame
367 * 65 2/02/98 3:36p Jasen
368 * AL: remove weapon debug name, and allow for 2 frame weapon anis
370 * 64 2/02/98 3:21p Jasen
371 * Updated coords for weapon anim location.
373 * 63 1/20/98 5:52p Lawrance
374 * account for no player ship when moving to weapons loadout
376 * 62 1/20/98 2:23p Dave
377 * Removed optimized build warnings. 99% done with ingame join fixes.
379 * 61 1/20/98 11:08a Lawrance
380 * Fix sound error when clicking on a weapon.
382 * 60 1/19/98 2:17p Lawrance
383 * Fix bug that was not recognizing non-default weapons on late-arriving
386 * 59 1/15/98 4:09p Lawrance
387 * fix weapon scrolling bug
389 * 58 1/14/98 6:44p Lawrance
390 * Take out unnecessary instance checking when freeing anims.
392 * 57 1/12/98 5:17p Dave
393 * Put in a bunch of multiplayer sequencing code. Made weapon/ship select
394 * work through the standalone.
396 * 56 1/10/98 12:47a Lawrance
397 * update some comments
399 * 55 1/09/98 6:06p Dave
400 * Put in network sound support for multiplayer ship/weapon select
401 * screens. Made clients exit game correctly through warp effect. Fixed
402 * main hall menu help overlay bug.
404 * 54 1/09/98 4:08p John
405 * Fixed a bug loading too many icon frames
407 * 53 1/08/98 10:55p Lawrance
408 * Fix bug where forbidden weapons were not updated when a ship was
409 * changed before weapons loadout is entered.
411 * 52 1/08/98 5:19p Sandeep
412 * Alan made a change which fixed missions with more than 4 types of
415 * 51 1/08/98 11:38a Lawrance
418 * 50 1/08/98 11:36a Lawrance
419 * Get ship select and weapons loadout icon dropping sound effects working
420 * for single and multiplayer
422 * 49 1/02/98 9:10p Lawrance
423 * Big changes to how colors get set on the HUD.
425 * 48 12/30/97 6:08p Lawrance
426 * Fix bug where player discarded ship before entering weapon select
428 * 47 12/29/97 4:21p Lawrance
429 * Flash buttons on briefing/ship select/weapons loadout when enough time
430 * has elapsed without activity.
432 * 46 12/29/97 10:11a Lawrance
433 * Don't play drop sound when a weapon is clicked on in a slot.
435 * 45 12/24/97 8:54p Lawrance
436 * Integrating new popup code
438 * 44 12/24/97 1:19p Lawrance
439 * fix some bugs with the multiplayer ship/weapons loadout
441 * 43 12/23/97 5:25p Allender
442 * more fixes to multiplayer ship selection. Fixed strange reentrant
443 * problem with cf_callback when loading freespace data
445 * 42 12/23/97 11:59a Allender
446 * changes to ship/wespon selection for multplayer. added sounds to some
447 * interface screens. Update and modiied end-of-briefing packets -- yet
450 * 41 12/23/97 11:48a Lawrance
451 * fix bug that could cause assert when swapping secondary weapons
453 * 40 12/22/97 6:18p Lawrance
454 * Get save/restore of player loadout working with new code
456 * 39 12/22/97 1:40a Lawrance
457 * Re-write ship select/weapons loadout to be multiplayer friendly
459 * 38 12/19/97 1:23p Dave
460 * Put in multiplayer groundwork for new weapon/ship select screens.
462 * 37 12/19/97 12:44p Dave
463 * Put in final touches on ship/weapon select. However, this is all going
469 #include "missionscreencommon.h"
470 #include "missionweaponchoice.h"
471 #include "missionshipchoice.h"
477 #include "snazzyui.h"
478 #include "animplay.h"
479 #include "freespace.h"
480 #include "gamesequence.h"
482 #include "missionbrief.h"
485 #include "animplay.h"
486 #include "contexthelp.h"
488 #include "linklist.h"
489 #include "multimsgs.h"
491 #include "multiteamselect.h"
493 #include "alphacolors.h"
494 #include "localize.h"
496 //#define MAX_PRIMARY_BANKS 3
497 //#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.
499 #define IS_BANK_PRIMARY(x) (x<3?1:0)
500 #define IS_BANK_SECONDARY(x) (x>2?1:0)
502 #define IS_LIST_PRIMARY(x) (Weapon_info[x].subtype==WP_MISSILE?0:1)
503 #define IS_LIST_SECONDARY(x) (Weapon_info[x].subtype==WP_MISSILE?1:0)
506 #if (MAX_PRIMARY_BANKS > MAX_WL_PRIMARY)
507 #error "Illegal: MAX_PRIMARY_BANKS greater than MAX_WL_PRIMARY"
510 #if (MAX_SECONDARY_BANKS > MAX_WL_SECONDARY)
511 #error "Illegal: MAX_SECONDARY_BANKS greater than MAX_WL_SECONDARY"
515 //////////////////////////////////////////////////////////////////
517 //////////////////////////////////////////////////////////////////
519 // This game-wide global flag is set to 1 to indicate that the weapon
520 // select screen has been opened and memory allocated. This flag
521 // is needed so we can know if weapon_select_close() needs to called if
522 // restoring a game from the Options screen invoked from weapon select
523 int Weapon_select_open = 0;
525 //////////////////////////////////////////////////////////////////
527 //////////////////////////////////////////////////////////////////
529 typedef struct wl_bitmap_group
535 #if defined(FS2_DEMO) || defined(FS1_DEMO)
536 #define WEAPON_ANIM_LOOP_FRAME 1
538 #define WEAPON_ANIM_LOOP_FRAME 32
540 #define WEAPON_ANIM_LOOP_FRAME 52 // frame (from 0) to loop weapon anim
543 #define WEAPON_ICON_FRAME_NORMAL 0
544 #define WEAPON_ICON_FRAME_HOT 1
545 #define WEAPON_ICON_FRAME_SELECTED 2
546 #define WEAPON_ICON_FRAME_DISABLED 3
548 // Weapn loadout specific buttons
549 #define NUM_WEAPON_BUTTONS 7
550 #define WL_BUTTON_SCROLL_PRIMARY_UP 0
551 #define WL_BUTTON_SCROLL_PRIMARY_DOWN 1
552 #define WL_BUTTON_SCROLL_SECONDARY_UP 2
553 #define WL_BUTTON_SCROLL_SECONDARY_DOWN 3
554 #define WL_BUTTON_RESET 4
555 #define WL_BUTTON_DUMMY 5
556 #define WL_BUTTON_MULTI_LOCK 6
557 UI_WINDOW Weapon_ui_window;
558 //UI_BUTTON Weapon_buttons[NUM_WEAPON_BUTTONS];
560 static const char *Wl_mask_single[GR_NUM_RESOLUTIONS] = {
565 static const char *Wl_mask_multi[GR_NUM_RESOLUTIONS] = {
566 "weaponloadoutmulti-m",
567 "2_weaponloadoutmulti-m"
570 static const char *Wl_loadout_select_mask[GR_NUM_RESOLUTIONS] = {
576 static const char *Weapon_select_background_fname[GR_NUM_RESOLUTIONS] = {
586 static const char *Weapon_select_multi_background_fname[GR_NUM_RESOLUTIONS] = {
591 "WeaponLoadoutMulti",
592 "2_WeaponLoadoutMulti"
596 int Weapon_select_background_bitmap; // bitmap for weapon select brackground
598 static MENU_REGION Weapon_select_region[NUM_WEAPON_REGIONS];
599 static int Num_weapon_select_regions;
601 // Mask bitmap pointer and Mask bitmap_id
602 static bitmap* WeaponSelectMaskPtr; // bitmap pointer to the weapon select mask bitmap
603 static ubyte* WeaponSelectMaskData; // pointer to actual bitmap data
604 static int Weaponselect_mask_w, Weaponselect_mask_h;
605 static int WeaponSelectMaskBitmap; // bitmap id of the weapon select mask bitmap
608 // convenient struct for handling all button controls
610 const char *filename;
613 UI_BUTTON button; // because we have a class inside this struct, we need the constructor below..
615 wl_buttons(const char *name, int x1, int y1, int xt1, int yt1, int h) : filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h) {}
618 static wl_buttons Buttons[GR_NUM_RESOLUTIONS][NUM_WEAPON_BUTTONS] = {
621 wl_buttons("WLB_26", 0, 123, -1, -1, 26),
622 wl_buttons("WLB_27", 0, 272, -1, -1, 27),
623 wl_buttons("WLB_26", 0, 302, -1, -1, 8),
624 wl_buttons("WLB_27", 0, 452, -1, -1, 9),
625 wl_buttons("ssb_39", 566, 317, -1, -1, 39),
626 wl_buttons("ssb_39", 0, 0, -1, -1, 99),
627 wl_buttons("TSB_34", 601, 344, -1, -1, 50)
629 wl_buttons("WLB_26", 24, 125, -1, -1, 26),
630 wl_buttons("WLB_27", 24, 276, -1, -1, 27),
631 wl_buttons("WLB_08", 24, 303, -1, -1, 8),
632 wl_buttons("WLB_09", 24, 454, -1, -1, 9),
633 wl_buttons("ssb_39", 571, 347, -1, -1, 39),
634 wl_buttons("ssb_39", 0, 0, -1, -1, 99),
635 wl_buttons("TSB_34", 603, 374, -1, -1, 34)
639 wl_buttons("2_WLB_26", 39, 200, -1, -1, 26),
640 wl_buttons("2_WLB_27", 39, 442, -1, -1, 27),
641 wl_buttons("2_WLB_08", 39, 485, -1, -1, 8),
642 wl_buttons("2_WLB_09", 39, 727, -1, -1, 9),
643 wl_buttons("2_ssb_39", 913, 556, -1, -1, 39),
644 wl_buttons("2_ssb_39", 0, 0, -1, -1, 99),
645 wl_buttons("2_TSB_34", 966, 599, -1, -1, 34)
649 //static wl_bitmap_group wl_button_bitmaps[NUM_WEAPON_BUTTONS];
651 static int Weapon_button_scrollable[NUM_WEAPON_BUTTONS] = {0, 0, 0, 0, 0, 0, 0};
653 #define MAX_WEAPON_ICONS_ON_SCREEN 8
655 // X and Y locations of the weapon icons in the scrollable lists
656 //int Weapon_icon_x[MAX_WEAPON_ICONS_ON_SCREEN] = {27, 27, 27, 27, 36, 36, 36, 36};
657 //int Weapon_icon_y[MAX_WEAPON_ICONS_ON_SCREEN] = {152, 182, 212, 242, 331, 361, 391, 421};
658 static int Wl_weapon_icon_coords[GR_NUM_RESOLUTIONS][MAX_WEAPON_ICONS_ON_SCREEN][2] = {
682 static int Wl_bank_coords[GR_NUM_RESOLUTIONS][MAX_WL_WEAPONS][2] = {
713 static int Wl_bank_count_draw_flags[MAX_WL_WEAPONS] = {
714 0, 0, 0, // primaries -- dont draw counts
715 1, 1, 1, 1 // secondaries -- do draw counts
719 static int Weapon_anim_class = -1;
720 static int Last_wl_ship_class;
722 static int Wl_overhead_coords[GR_NUM_RESOLUTIONS][2] = {
737 static int Wl_weapon_ani_coords[GR_NUM_RESOLUTIONS][2] = {
750 static int Wl_weapon_ani_coords_multi[GR_NUM_RESOLUTIONS][2] = {
764 static int Wl_weapon_desc_coords[GR_NUM_RESOLUTIONS][2] = {
773 static int Wl_delta_x, Wl_delta_y;
775 static int Wl_ship_name_coords[GR_NUM_RESOLUTIONS][2] = {
785 ///////////////////////////////////////////////////////////////////////
787 ///////////////////////////////////////////////////////////////////////
788 typedef struct wl_ship_class_info
792 anim_instance_t *anim_instance;
793 } wl_ship_class_info;
795 wl_ship_class_info Wl_ships[MAX_SHIP_TYPES];
797 typedef struct wl_icon_info
799 int icon_bmaps[NUM_ICON_FRAMES];
800 int current_icon_bmap;
803 anim_instance_t *anim_instance;
806 wl_icon_info Wl_icons_teams[MAX_TEAMS][MAX_WEAPON_TYPES];
807 wl_icon_info *Wl_icons;
809 int Plist[MAX_WEAPON_TYPES]; // used to track scrolling of primary icon list
810 int Plist_start, Plist_size;
812 int Slist[MAX_WEAPON_TYPES]; // used to track scrolling of primary icon list
813 int Slist_start, Slist_size;
815 static int Selected_wl_slot = -1; // Currently selected ship slot
816 static int Selected_wl_class = -1; // Class of weapon that is selected
817 static int Hot_wl_slot = -1; // Ship slot that mouse is over (0..11)
818 static int Hot_weapon_icon = -1; // Icon number (0-7) which has mouse over it
819 static int Hot_weapon_bank = -1; // index (0-7) for weapon slot on ship that has a droppable icon over it
820 static int Hot_weapon_bank_icon = -1;
822 static int Wl_mouse_down_on_region = -1;
827 #define WEAPON_DESC_WIPE_TIME 1.5f // time in seconds for wipe to occur (over WEAPON_DESC_MAX_LENGTH number of chars)
828 #define WEAPON_DESC_MAX_LINES 7 // max lines in the description incl. title
829 #define WEAPON_DESC_MAX_LENGTH 50 // max chars per line of description text
830 static int Weapon_desc_wipe_done = 0;
831 static float Weapon_desc_wipe_time_elapsed = 0.0f;
832 static char Weapon_desc_lines[WEAPON_DESC_MAX_LINES][WEAPON_DESC_MAX_LENGTH]; // 1st 2 lines are title, rest are desc
834 // maximum width the weapon title can be -- used in the line breaking
835 int Weapon_title_max_width[GR_NUM_RESOLUTIONS] = { 200, 320 };
837 static int Wl_new_weapon_title_coords[GR_NUM_RESOLUTIONS][2] = {
846 static int Wl_new_weapon_title_coords_multi[GR_NUM_RESOLUTIONS][2] = {
855 static int Wl_new_weapon_desc_coords[GR_NUM_RESOLUTIONS][2] = {
864 static int Wl_new_weapon_desc_coords_multi[GR_NUM_RESOLUTIONS][2] = {
876 #define WEAPON_SELECT_NUM_TEXT 2
878 UI_XSTR Weapon_select_text[GR_NUM_RESOLUTIONS][WEAPON_SELECT_NUM_TEXT] = {
880 { "Reset", 1337, 580, 337, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][WL_BUTTON_RESET].button },
881 { "Lock", 1270, 602, 364, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][WL_BUTTON_MULTI_LOCK].button }
884 { "Reset", 1337, 938, 546, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][WL_BUTTON_RESET].button },
885 { "Lock", 1270, 964, 584, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][WL_BUTTON_MULTI_LOCK].button }
891 ///////////////////////////////////////////////////////////////////////
893 ///////////////////////////////////////////////////////////////////////
894 typedef struct carried_icon
896 int weapon_class; // index Wl_icons[] for carried icon (-1 if carried from bank)
897 int num; // number of units of weapon
898 int from_bank; // bank index that icon came from (0..2 primary, 3..6 secondary). -1 if from list
899 int from_slot; // ship slot that weapon is part of
903 static carried_icon Carried_wl_icon;
905 // forward declarations
906 void draw_wl_icons();
907 void wl_draw_ship_weapons(int index);
908 void wl_pick_icon_from_list(int index);
909 void pick_from_ship_slot(int num);
910 void start_weapon_animation(int weapon_class);
911 void stop_weapon_animation();
912 void wl_start_slot_animation(int n);
913 int wl_get_pilot_subsys_index(p_object *pobjp);
915 void wl_reset_to_defaults();
917 void wl_set_selected_slot(int slot_num);
918 void wl_maybe_reset_selected_slot();
919 void wl_maybe_reset_selected_weapon_class();
921 void wl_render_icon_count(int num, int x, int y);
922 void wl_render_weapon_desc();
926 // carry icon functions
927 void wl_reset_carried_icon();
928 int wl_icon_being_carried();
929 void wl_set_carried_icon(int from_bank, int from_slot, int weapon_class);
932 // Determine hack offset for how to draw fury missile icon.
933 int wl_fury_missile_offset_hack(int weapon_class, int num_missiles)
935 if ( weapon_class < 0 ) {
939 if ( num_missiles < 100 ) {
943 if ( !SDL_strncasecmp(Weapon_info[weapon_class].name, NOX("fury"), 4) ) {
950 const char *wl_tooltip_handler(const char *str)
952 if (Selected_wl_class < 0)
955 if (!SDL_strcasecmp(str, "@weapon_desc")) {
959 str = Weapon_info[Selected_wl_class].desc;
960 gr_get_string_size(&w, &h, str);
961 x = Wl_weapon_desc_coords[gr_screen.res][0] - w / 2;
962 y = Wl_weapon_desc_coords[gr_screen.res][1] - h / 2;
964 gr_set_color_fast(&Color_black);
965 gr_rect(x - 5, y - 5, w + 10, h + 10);
967 gr_set_color_fast(&Color_bright_white);
968 gr_string(x, y, str);
975 // reset the data inside the Carried_wl_icon
976 void wl_reset_carried_icon()
978 Carried_wl_icon.weapon_class = -1;
979 Carried_wl_icon.num = 0;
980 Carried_wl_icon.from_bank = -1;
981 Carried_wl_icon.from_slot = -1;
984 // Is an icon being carried?
985 int wl_icon_being_carried()
987 if ( Carried_wl_icon.weapon_class >= 0 ) {
994 // Set carried icon data
995 void wl_set_carried_icon(int from_bank, int from_slot, int weapon_class)
999 Carried_wl_icon.from_bank = from_bank;
1000 Carried_wl_icon.from_slot = from_slot;
1001 Carried_wl_icon.weapon_class = weapon_class;
1003 mouse_get_pos( &mx, &my );
1004 Carried_wl_icon.from_x=mx;
1005 Carried_wl_icon.from_y=my;
1007 Buttons[gr_screen.res][WL_BUTTON_DUMMY].button.capture_mouse();
1010 // determine if the carried icon has moved
1011 int wl_carried_icon_moved()
1014 mouse_get_pos( &mx, &my );
1015 if ( Carried_wl_icon.from_x != mx || Carried_wl_icon.from_y != my) {
1022 // return the index for the pilot subsystem in the parse object
1023 int wl_get_pilot_subsys_index(p_object *pobjp)
1025 int pilot_index, start_index, end_index, i;
1027 // see if there is a PILOT subystem
1028 start_index = pobjp->subsys_index;
1029 end_index = start_index + pobjp->subsys_count;
1031 for ( i = start_index; i < end_index; i++ ) {
1032 if ( !SDL_strcasecmp(Subsys_status[i].name, NOX("pilot") ) ) {
1038 if ( pilot_index == -1 ) {
1039 Error(LOCATION,"Parse object doesn't have a pilot subsystem\n");
1046 // Pause the current weapon animation
1047 void wl_pause_anim()
1049 if ( Weapon_anim_class >= 0 && Wl_icons[Weapon_anim_class].anim_instance ) {
1050 anim_pause(Wl_icons[Weapon_anim_class].anim_instance);
1054 // Unpause the current weapon animation
1055 void wl_unpause_anim()
1057 if ( Weapon_anim_class >= 0 && Wl_icons[Weapon_anim_class].anim_instance ) {
1058 anim_unpause(Wl_icons[Weapon_anim_class].anim_instance);
1062 // ---------------------------------------------------------------------------------
1063 // weapon_button_do()
1065 void weapon_button_do(int i)
1068 case PRIMARY_SCROLL_UP:
1069 if ( common_scroll_up_pressed(&Plist_start, Plist_size, 4) ) {
1070 gamesnd_play_iface(SND_SCROLL);
1072 gamesnd_play_iface(SND_GENERAL_FAIL);
1076 case PRIMARY_SCROLL_DOWN:
1077 if ( common_scroll_down_pressed(&Plist_start, Plist_size, 4) ) {
1078 gamesnd_play_iface(SND_SCROLL);
1080 gamesnd_play_iface(SND_GENERAL_FAIL);
1084 case SECONDARY_SCROLL_UP:
1085 if ( common_scroll_up_pressed(&Slist_start, Slist_size, 4) ) {
1086 gamesnd_play_iface(SND_SCROLL);
1088 gamesnd_play_iface(SND_GENERAL_FAIL);
1092 case SECONDARY_SCROLL_DOWN:
1093 if ( common_scroll_down_pressed(&Slist_start, Slist_size, 4) ) {
1094 gamesnd_play_iface(SND_SCROLL);
1096 gamesnd_play_iface(SND_GENERAL_FAIL);
1100 case WL_RESET_BUTTON_MASK:
1101 wl_reset_to_defaults();
1104 case WL_BUTTON_MULTI_LOCK:
1105 SDL_assert(Game_mode & GM_MULTIPLAYER);
1106 // the "lock" button has been pressed
1107 multi_ts_lock_pressed();
1109 // disable the button if it is now locked
1110 if(multi_ts_is_locked()){
1111 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.disable();
1120 // -------------------------------------------------------------------
1121 // weapon_check_buttons()
1123 // Check if any weapons loadout screen buttons have been pressed, and
1124 // call weapon_button_do() if they have.
1126 void weapon_check_buttons()
1131 for ( i = 0; i < NUM_WEAPON_BUTTONS; i++ ) {
1132 b = &Buttons[gr_screen.res][i];
1134 if ( b->button.pressed() ) {
1135 if(i == WL_BUTTON_MULTI_LOCK){
1136 weapon_button_do(i);
1138 weapon_button_do(b->hotspot);
1144 // -------------------------------------------------------------------
1145 // wl_redraw_pressed_buttons()
1147 // Redraw any weapon loadout buttons that are pressed down. This function is needed
1148 // since we sometimes need to draw pressed buttons last to ensure the entire
1149 // button gets drawn (and not overlapped by other buttons)
1151 void wl_redraw_pressed_buttons()
1156 common_redraw_pressed_buttons();
1158 for ( i = 0; i < NUM_WEAPON_BUTTONS; i++ ) {
1159 b = &Buttons[gr_screen.res][i];
1160 if ( b->button.button_down() ) {
1161 b->button.draw_forced(2);
1166 // ---------------------------------------------------------------------------------
1167 // weapon_buttons_init()
1169 void weapon_buttons_init()
1174 for ( i = 0; i < NUM_WEAPON_BUTTONS; i++ ) {
1175 b = &Buttons[gr_screen.res][i];
1176 b->button.create( &Weapon_ui_window, "", Buttons[gr_screen.res][i].x, Buttons[gr_screen.res][i].y, 60, 30, Weapon_button_scrollable[i]);
1177 // set up callback for when a mouse first goes over a button
1178 b->button.set_highlight_action( common_play_highlight_sound );
1179 b->button.set_bmaps(Buttons[gr_screen.res][i].filename);
1180 b->button.link_hotspot(Buttons[gr_screen.res][i].hotspot);
1183 if ( Game_mode & GM_MULTIPLAYER ) {
1184 Buttons[gr_screen.res][WL_BUTTON_RESET].button.hide();
1185 Buttons[gr_screen.res][WL_BUTTON_RESET].button.disable();
1187 // if we're not the host of the game (or a team captain in team vs. team mode), disable the lock button
1188 if(Netgame.type_flags & NG_TYPE_TEAM){
1189 if(!(Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN)){
1190 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.disable();
1193 if(!(Net_player->flags & NETINFO_FLAG_GAME_HOST)){
1194 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.disable();
1198 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.hide();
1199 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.disable();
1204 for(i=0; i<WEAPON_SELECT_NUM_TEXT; i++) {
1205 Weapon_ui_window.add_XSTR(&Weapon_select_text[gr_screen.res][i]);
1209 Buttons[gr_screen.res][WL_BUTTON_DUMMY].button.hide();
1210 Buttons[gr_screen.res][WL_BUTTON_DUMMY].button.disable();
1213 // ---------------------------------------------------------------------------------
1214 // wl_render_overhead_view()
1216 void wl_render_overhead_view(float frametime)
1218 char name[NAME_LENGTH + CALLSIGN_LEN];
1219 wl_ship_class_info *wl_ship;
1222 if ( Selected_wl_slot == -1 ) {
1226 ship_class = Wss_slots[Selected_wl_slot].ship_class;
1228 // check if ship class has changed and maybe play sound
1229 if (Last_wl_ship_class != ship_class) {
1230 if (Last_wl_ship_class != -1) {
1231 gamesnd_play_iface(SND_ICON_DROP);
1233 Last_wl_ship_class = ship_class;
1236 wl_ship = &Wl_ships[ship_class];
1238 if ( wl_ship->anim_instance == NULL ) {
1239 if ( wl_ship->overhead_bitmap < 0 ) {
1241 if (gr_screen.res == GR_640)
1244 wl_ship->overhead_bitmap = bm_load(Ship_info[ship_class].overhead_filename);
1247 char filename[NAME_LENGTH+2] = "2_";
1248 SDL_strlcat(filename, Ship_info[ship_class].overhead_filename, sizeof(filename));
1249 wl_ship->overhead_bitmap = bm_load(filename);
1251 if ( wl_ship->overhead_bitmap < 0 ) {
1252 Int3(); // bad things happened
1256 gr_set_bitmap(wl_ship->overhead_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1257 gr_bitmap(Wl_overhead_coords[gr_screen.res][0], Wl_overhead_coords[gr_screen.res][1]);
1260 ss_return_name(Selected_wl_slot/4, Selected_wl_slot%4, name, sizeof(name));
1261 gr_set_color_fast(&Color_normal);
1262 gr_string(Wl_ship_name_coords[gr_screen.res][0], Wl_ship_name_coords[gr_screen.res][1], name);
1265 // ---------------------------------------------------------------------------------
1266 // wl_get_ship_class()
1269 int wl_get_ship_class(int wl_slot)
1271 return Wss_slots[wl_slot].ship_class;
1274 // Return true if weapon_flags indicates a weapon that is legal for use in current game type.
1275 // Function added by MK on 9/6/99 to support separate legal loadouts for dogfight missions.
1276 int weapon_allowed_for_game_type(int weapon_flags)
1280 /* disable check for demo since it doesn't have "$Allowed Dogfight PBanks" */
1281 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
1282 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)) {
1283 if (weapon_flags & (1 << 1))
1287 if (weapon_flags & (1 << 0))
1293 // go through the possible weapons to choose from, and flag some as disabled since
1294 // that ship class cannot use that kind of weapon. The weapon filter is specified
1295 // in ships.tbl, where each ship has a list of all the possible weapons it can use.
1296 void wl_set_disabled_weapons(int ship_class)
1301 if ( ship_class == - 1 )
1304 SDL_assert(ship_class >= 0 && ship_class < MAX_SHIP_TYPES);
1306 sip = &Ship_info[ship_class];
1308 for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1309 // Determine whether weapon #i is allowed on this ship class in the current type of mission.
1310 // As of 9/6/99, the only difference is dogfight missions have a different list of legal weapons.
1311 Wl_icons[i].can_use = weapon_allowed_for_game_type(sip->allowed_weapons[i]);
1315 // ---------------------------------------------------------------------------------
1316 // maybe_select_wl_slot()
1318 // A slot index was clicked on, mabye change Selected_wl_slot
1319 void maybe_select_wl_slot(int block, int slot)
1323 if ( Wss_num_wings <= 0 )
1326 sidx = block*4 + slot;
1327 if ( Wss_slots[sidx].ship_class < 0 ) {
1331 wl_set_selected_slot(sidx);
1334 // ---------------------------------------------------------------------------------
1335 // maybe_select_new_weapon()
1337 // Change to the weapon that corresponds to index in the weapon list
1339 // input: index => weapon icon index (0-7)
1341 void maybe_select_new_weapon(int index)
1345 // if a weapon is being carried, do nothing
1346 if ( wl_icon_being_carried() ) {
1350 int region_index = ICON_PRIMARY_0+index;
1352 region_index = ICON_SECONDARY_0 + (index - 4);
1355 if ( Wl_mouse_down_on_region != region_index ) {
1360 weapon_class = Plist[Plist_start+index];
1362 weapon_class = Slist[Slist_start+index-4];
1365 if ( weapon_class >= 0 ) {
1366 Selected_wl_class = weapon_class;
1367 wl_pick_icon_from_list(index);
1371 // ---------------------------------------------------------------------------------
1372 // maybe_select_new_ship_weapon()
1374 // Change to the weapon that corresponds to the ship weapon slot
1376 // input: index -> index of bank (0..2 primary, 0..6 secondary)
1377 void maybe_select_new_ship_weapon(int index)
1379 int *wep, *wep_count;
1381 if ( Selected_wl_slot == -1 )
1384 if ( wl_icon_being_carried() ) {
1388 wep = Wss_slots[Selected_wl_slot].wep;
1389 wep_count = Wss_slots[Selected_wl_slot].wep_count;
1391 if ( wep[index] < 0 || wep_count[index] <= 0 ) {
1395 if ( Wl_mouse_down_on_region != (ICON_SHIP_PRIMARY_0+index) ) {
1400 Selected_wl_class = wep[index];
1403 // Initialize Wl_pool[] to mission deafult
1404 void wl_init_pool(team_data *td)
1408 for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1412 for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1413 Wl_pool[i] = td->weaponry_pool[i]; // read from mission
1417 // load the icons for a specific ship class
1418 void wl_load_icons(int weapon_class)
1421 int first_frame, num_frames, i;
1423 icon = &Wl_icons[weapon_class];
1425 first_frame = bm_load_animation(Weapon_info[weapon_class].icon_filename, &num_frames);
1426 if ( first_frame == -1 ) {
1427 Int3(); // Could not load in icon frames.. get Alan
1431 for ( i = 0; i < num_frames ; i++ ) {
1432 icon->icon_bmaps[i] = first_frame+i;
1436 // Load in a specific weapon animation. The data is loaded as a memory-mapped file since these animations
1438 void wl_load_anim(int weapon_class)
1440 char animation_filename[CF_MAX_FILENAME_LENGTH+4];
1443 icon = &Wl_icons[weapon_class];
1444 SDL_assert( icon->anim == NULL );
1447 // If we are in 1024x768, we first want to append "2_" in front of the filename
1448 if (gr_screen.res == GR_1024) {
1449 SDL_assert(strlen(Weapon_info[weapon_class].anim_filename) <= 30);
1450 SDL_strlcpy(animation_filename, "2_", sizeof(animation_filename));
1451 SDL_strlcat(animation_filename, Weapon_info[weapon_class].anim_filename, sizeof(animation_filename));
1453 // now check if file exists
1454 // GRR must add a .ANI at the end for detection
1455 SDL_strlcat(animation_filename,".ani", sizeof(animation_filename));
1456 icon->anim = anim_load(animation_filename);
1458 if (icon->anim == NULL) {
1459 mprintf(("Weapon ANI: Can not find %s, using lowres version instead.\n",animation_filename));
1460 SDL_strlcpy(animation_filename, Weapon_info[weapon_class].anim_filename, sizeof(animation_filename));
1461 icon->anim = anim_load(animation_filename);
1465 if (!cf_exist(animation_filename, CF_TYPE_INTERFACE)) {
1466 // file does not exist, use original low res version
1467 mprintf(("Weapon ANI: Can not find %s, using lowres version instead.\n",animation_filename));
1468 strcpy(animation_filename, Weapon_info[weapon_class].anim_filename);
1470 animation_filename[strlen(animation_filename) - 4] = '\0';
1471 mprintf(("Weapon ANI: Found hires version of %s\n",animation_filename));
1475 SDL_strlcpy(animation_filename, Weapon_info[weapon_class].anim_filename, sizeof(animation_filename));
1476 // load the compressed ship animation into memory
1477 icon->anim = anim_load(animation_filename);
1480 if ( icon->anim == NULL ) {
1481 Int3(); // couldn't load anim filename.. get Alan
1485 // Load in any weapon animations. This function assumes that Wl_pool has been inited.
1486 void wl_load_all_anims()
1488 #ifndef DEMO // not for FS2_DEMO
1492 // init anim members for weapon animations
1493 for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1494 Wl_icons[i].anim = NULL;
1495 Wl_icons[i].anim_instance = NULL;
1498 // init anim member for overhead ship animations
1499 for ( i = 0; i < MAX_SHIP_TYPES; i++ ) {
1500 Wl_ships[i].anim = NULL;
1501 Wl_ships[i].anim_instance = NULL;
1504 // load up the animations used for weapons (they are memory-mapped)
1505 for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1506 if ( Wl_pool[i] > 0 ) {
1514 // release any anim instances
1515 void wl_unload_all_anim_instances()
1517 // stop any weapon anim instances
1518 for ( int i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1519 if ( Wl_icons[i].anim_instance ) {
1520 anim_release_render_instance(Wl_icons[i].anim_instance);
1521 Wl_icons[i].anim_instance = NULL;
1525 // stop any overhead anim instances
1526 for (int i = 0; i < MAX_SHIP_TYPES; i++ ) {
1527 if ( Wl_ships[i].anim_instance ) {
1528 anim_release_render_instance(Wl_ships[i].anim_instance);
1529 Wl_ships[i].anim_instance = NULL;
1534 // free source anim data if allocated
1535 void wl_unload_all_anims()
1539 // unload overhead anim instances
1540 for ( i = 0; i < MAX_SHIP_TYPES; i++ ) {
1541 if ( Wl_ships[i].anim ) {
1542 anim_free(Wl_ships[i].anim);
1543 Wl_ships[i].anim = NULL;
1547 // unload weapon anim instances
1548 for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1549 if ( Wl_icons[i].anim ) {
1550 anim_free(Wl_icons[i].anim);
1551 Wl_icons[i].anim = NULL;
1556 // load all the icons for weapons in the pool
1557 void wl_load_all_icons()
1559 #ifndef DEMO // not for FS2_DEMO
1563 for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1565 Wl_icons[i].anim = NULL;
1566 Wl_icons[i].anim_instance = NULL;
1567 for ( j = 0; j < NUM_ICON_FRAMES; j++ ) {
1568 Wl_icons[i].icon_bmaps[j] = -1;
1571 if ( Wl_pool[i] > 0 ) {
1579 // wl_unload_icons() frees the bitmaps used for weapon icons
1580 void wl_unload_icons()
1585 for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1586 icon = &Wl_icons[i];
1588 for ( j = 0; j < NUM_ICON_FRAMES; j++ ) {
1589 if ( icon->icon_bmaps[j] >= 0 ) {
1590 bm_release(icon->icon_bmaps[j]);
1591 icon->icon_bmaps[j] = -1;
1597 // init ship-class specific data
1598 void wl_init_ship_class_data()
1601 wl_ship_class_info *wl_ship;
1603 for ( i=0; i<MAX_SHIP_TYPES; i++ ) {
1604 wl_ship = &Wl_ships[i];
1605 wl_ship->overhead_bitmap = -1;
1606 wl_ship->anim = NULL;
1607 wl_ship->anim_instance = NULL;
1611 // free any allocated ship-class specific data
1612 void wl_free_ship_class_data()
1615 wl_ship_class_info *wl_ship;
1617 for ( i=0; i<MAX_SHIP_TYPES; i++ ) {
1618 wl_ship = &Wl_ships[i];
1620 if ( wl_ship->overhead_bitmap != -1 ) {
1621 bm_release(wl_ship->overhead_bitmap);
1622 wl_ship->overhead_bitmap = -1;
1625 if ( wl_ship->anim != NULL ) {
1626 wl_ship->anim = NULL;
1629 if ( wl_ship->anim_instance != NULL ) {
1630 wl_ship->anim_instance = NULL;
1635 // Set selected slot to first placed ship
1636 void wl_reset_selected_slot()
1639 Selected_wl_slot = -1;
1641 // in multiplayer, select the slot of the player's ship by default
1642 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)){
1643 wl_set_selected_slot(Net_player->p_info.ship_index);
1647 for ( i=0; i<MAX_WSS_SLOTS; i++ ) {
1648 if ( !ss_disabled_slot(i) ) {
1649 if ( ss_wing_slot_is_console_player(i) && (Wss_slots[i].ship_class >= 0) ) {
1650 wl_set_selected_slot(i);
1656 // Didn't locate player ship, so just select the first ship we find
1657 for ( i=0; i<MAX_WSS_SLOTS; i++ ) {
1658 if ( Wss_slots[i].ship_class >= 0 ) {
1659 wl_set_selected_slot(i);
1665 // called whenever it is possible that the current selected slot has had it's ship disappear
1666 void wl_maybe_reset_selected_slot()
1670 if ( Selected_wl_slot == -1 ) {
1674 if ( Wss_slots[Selected_wl_slot].ship_class < 0 ) {
1679 wl_reset_selected_slot();
1683 // If Selected_wl_class is -1, choose the first weapon available from the pool for an animation
1684 // - on second thought, choose the first weapon that is oin the ship, then go to the pools
1685 void wl_maybe_reset_selected_weapon_class()
1689 if ( Selected_wl_class >= 0 )
1692 // try to locate a weapon class to show animation for
1693 // first check for a weapon on the ship
1694 for (i=0; i<MAX_WL_WEAPONS; i++) {
1695 // if alpha 1 has a weapon in bank i, set it as the selected type
1696 if (Wss_slots[0].wep_count[i] >= 0) {
1697 Selected_wl_class = Wss_slots[0].wep[i];
1702 // then check for a primary weapon in the pool
1703 for ( i = 0; i < Plist_size; i++ ) {
1704 if ( Plist[i] >= 0 ) {
1705 Selected_wl_class = Plist[i];
1710 // finally, if no others found yet, check for a secondary weapon in the pool
1711 for ( i = 0; i < Slist_size; i++ ) {
1712 if ( Slist[i] >= 0 ) {
1713 Selected_wl_class = Slist[i];
1719 // start an overhead animation, since selected slot has changed
1720 void wl_start_slot_animation(int n)
1722 #ifndef DEMO // not for FS2_DEMO
1725 // fallback code in wl_render_overhead_view() will
1726 // use the .pcx files
1727 // should prolly scrub out the 1e06 lines of dead code this leaves
1732 wl_ship_class_info *wl_ship;
1733 anim_play_struct aps;
1739 ship_class = Wss_slots[n].ship_class;
1741 if ( ship_class < 0 ) {
1746 wl_ship = &Wl_ships[ship_class];
1748 // maybe this animation is already playing?
1749 if ( wl_ship->anim_instance ) {
1750 anim_stop_playing(wl_ship->anim_instance);
1751 wl_ship->anim_instance = NULL;
1754 // maybe we have to load this animation
1755 if ( wl_ship->anim == NULL ) {
1756 wl_ship->anim = anim_load(Ship_info[ship_class].overhead_filename, 1);
1757 if ( wl_ship->anim == NULL ) {
1758 Int3(); // couldn't load anim filename.. get Alan
1763 anim_play_init(&aps, wl_ship->anim, Wl_overhead_coords[gr_screen.res][0], Wl_overhead_coords[gr_screen.res][1]);
1764 aps.screen_id = ON_WEAPON_SELECT;
1765 aps.framerate_independent = 1;
1766 aps.skip_frames = 0;
1767 wl_ship->anim_instance = anim_play(&aps);
1772 // Call when Selected_wl_slot needs to be changed
1773 void wl_set_selected_slot(int slot_num)
1775 if ( (slot_num >= 0) && (slot_num != Selected_wl_slot) ) {
1776 // slot has changed.... start an animation
1777 wl_start_slot_animation(slot_num);
1779 if ( Current_screen == ON_WEAPON_SELECT ) {
1780 gamesnd_play_iface(SND_OVERHEAD_SHIP_ANIM);
1785 Selected_wl_slot = slot_num;
1786 if ( Selected_wl_slot >= 0 ) {
1787 wl_set_disabled_weapons(Wss_slots[slot_num].ship_class);
1791 // determine how many missiles of type 'wi_index' will fit into capacity
1792 int wl_calc_missile_fit(int wi_index, int capacity)
1794 if ( wi_index < 0 ) {
1798 SDL_assert(Weapon_info[wi_index].subtype == WP_MISSILE);
1799 return fl2i( capacity / Weapon_info[wi_index].cargo_size + 0.5f );
1802 // fill out the weapons for this ship_class
1803 void wl_get_ship_class_weapons(int ship_class, int *wep, int *wep_count)
1808 SDL_assert(ship_class >= 0 && ship_class < MAX_SHIP_TYPES);
1809 sip = &Ship_info[ship_class];
1811 // reset weapons arrays
1812 for ( i=0; i < MAX_WL_WEAPONS; i++ ) {
1814 wep_count[i] = -1; // -1 means weapon bank doesn't exist.. 0 just means it is empty
1817 for ( i = 0; i < sip->num_primary_banks; i++ ) {
1818 wep[i] = sip->primary_bank_weapons[i];
1822 for ( i = 0; i < sip->num_secondary_banks; i++ ) {
1823 wep[i+MAX_WL_PRIMARY] = sip->secondary_bank_weapons[i];
1824 wep_count[i+MAX_WL_PRIMARY] = wl_calc_missile_fit(sip->secondary_bank_weapons[i], sip->secondary_bank_ammo_capacity[i]);
1828 // fill out the wep[] and wep_count[] arrays for a ship
1829 void wl_get_ship_weapons(int ship_index, int *wep, int *wep_count)
1834 SDL_assert(ship_index >= 0);
1836 swp = &Ships[ship_index].weapons;
1838 for ( i = 0; i < swp->num_primary_banks; i++ ) {
1839 wep[i] = swp->primary_bank_weapons[i];
1841 if ( wep[i] == -1 ) {
1846 for ( i = 0; i < swp->num_secondary_banks; i++ ) {
1847 wep[i+MAX_WL_PRIMARY] = swp->secondary_bank_weapons[i];
1848 wep_count[i+MAX_WL_PRIMARY] = swp->secondary_bank_ammo[i];
1849 if ( wep[i+MAX_WL_PRIMARY] == -1 ) {
1850 wep_count[i+MAX_WL_PRIMARY] = 0;
1855 // set wep and wep_count from a ship which sits in the ship_arrivals[] list at index sa_index
1856 void wl_get_parseobj_weapons(int sa_index, int ship_class, int *wep, int *wep_count)
1863 pobjp = &ship_arrivals[sa_index];
1864 sip = &Ship_info[ship_class];
1866 pilot_index = wl_get_pilot_subsys_index(pobjp);
1868 if ( pilot_index == -1 )
1871 ss = &Subsys_status[pilot_index];
1873 if ( ss->primary_banks[0] != SUBSYS_STATUS_NO_CHANGE ) {
1874 for ( i=0; i < MAX_PRIMARY_BANKS; i++ ) {
1875 wep[i] = ss->primary_banks[i];
1879 if ( ss->secondary_banks[0] != SUBSYS_STATUS_NO_CHANGE ) {
1880 for ( i=0; i < MAX_SECONDARY_BANKS; i++ ) {
1881 wep[i+MAX_WL_PRIMARY] = ss->secondary_banks[i];
1885 // ammo counts could still be modified
1886 for ( i=0; i < MAX_SECONDARY_BANKS; i++ ) {
1887 if ( wep[i+MAX_WL_PRIMARY] >= 0 ) {
1888 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));
1893 // ensure that there aren't any bogus weapons assigned by default
1894 void wl_cull_illegal_weapons(int ship_class, int *wep, int *wep_count)
1897 for ( i=0; i < MAX_WL_WEAPONS; i++ ) {
1902 if ( !weapon_allowed_for_game_type(Ship_info[ship_class].allowed_weapons[wep[i]]) ) {
1909 // get the weapons info that should be on ship by default
1910 void wl_get_default_weapons(int ship_class, int slot_num, int *wep, int *wep_count)
1912 int original_ship_class, i;
1914 SDL_assert(slot_num >= 0 && slot_num < MAX_WSS_SLOTS);
1916 // clear out wep and wep_count
1917 for ( i = 0; i < MAX_WL_WEAPONS; i++ ) {
1922 if ( ship_class < 0 )
1925 original_ship_class = ss_return_original_ship_class(slot_num);
1927 if ( original_ship_class != ship_class ) {
1928 wl_get_ship_class_weapons(ship_class, wep, wep_count);
1930 int sa_index; // ship arrival index
1931 sa_index = ss_return_saindex(slot_num);
1933 if ( sa_index >= 0 ) {
1934 // still a parse object
1935 wl_get_ship_class_weapons(ship_class, wep, wep_count);
1936 wl_get_parseobj_weapons(sa_index, ship_class, wep, wep_count);
1938 // ship has been created
1939 // wl_get_ship_weapons(slot_num/4, slot_num%4, wep, wep_count);
1940 int ship_index = -1;
1942 ss_return_ship(slot_num/4, slot_num%4, &ship_index, &pobjp);
1943 SDL_assert(ship_index != -1);
1944 wl_get_ship_weapons(ship_index, wep, wep_count);
1948 // ensure that there aren't any bogus weapons assigned by default
1949 wl_cull_illegal_weapons(ship_class, wep, wep_count);
1952 // function to add a weapon_class to ui lists
1953 void wl_add_index_to_list(int wi_index)
1956 if ( Weapon_info[wi_index].subtype == WP_MISSILE ) {
1958 for ( i=0; i<Slist_size; i++ ) {
1959 if ( Slist[i] == wi_index )
1963 if ( i == Slist_size )
1964 Slist[Slist_size++] = wi_index;
1967 for ( i=0; i<Plist_size; i++ ) {
1968 if ( Plist[i] == wi_index )
1972 if ( i == Plist_size )
1973 Plist[Plist_size++] = wi_index;
1977 // remove the weapons specificed by wep[] and wep_count[] from Wl_pool[].
1978 void wl_remove_weps_from_pool(int *wep, int *wep_count, int ship_class)
1982 for ( i = 0; i < MAX_WL_WEAPONS; i++ ) {
1984 if ( wi_index >= 0 ) {
1985 if ( (wep_count[i] > 0) && ((Wl_pool[wi_index] - wep_count[i]) >= 0) ) {
1986 Wl_pool[wi_index] -= wep_count[i];
1988 // not enough weapons in pool
1989 // TEMP HACK: FRED doesn't fill in a weapons pool if there are no starting wings... so
1990 // add to the pool. This should be fixed.
1991 if ( Wss_num_wings <= 0 ) {
1992 wl_add_index_to_list(wi_index);
1995 if ( (Wl_pool[wi_index] <= 0) || (wep_count[i] == 0) ) {
1996 // fresh out of this weapon, pick an alternate pool weapon if we can
1997 int wep_pool_index, wep_precedence_index, new_wi_index = -1;
1998 for ( wep_pool_index = 0; wep_pool_index < MAX_WEAPON_TYPES; wep_pool_index++ ) {
2000 if ( Wl_pool[wep_pool_index] <= 0 ) {
2004 // AL 3-31-98: Only pick another primary if primary, etc
2005 if ( Weapon_info[wi_index].subtype != Weapon_info[wep_pool_index].subtype ) {
2009 if ( !weapon_allowed_for_game_type(Ship_info[ship_class].allowed_weapons[wep_pool_index]) ) {
2014 for ( wep_precedence_index = 0; wep_precedence_index < Num_player_weapon_precedence; wep_precedence_index++ ) {
2015 if ( wep_pool_index == Player_weapon_precedence[wep_precedence_index] ) {
2016 new_wi_index = wep_pool_index;
2021 if ( new_wi_index >= 0 ) {
2026 if ( new_wi_index >= 0 ) {
2027 wep[i] = new_wi_index;
2028 wi_index = new_wi_index;
2032 int new_wep_count = wep_count[i];
2033 if ( Weapon_info[wi_index].subtype == WP_MISSILE ) {
2034 int secondary_bank_index;
2035 secondary_bank_index = i-3;
2036 if ( secondary_bank_index < 0 ) {
2038 secondary_bank_index = 0;
2040 new_wep_count = wl_calc_missile_fit(wi_index, Ship_info[ship_class].secondary_bank_ammo_capacity[secondary_bank_index]);
2043 wep_count[i] = min(new_wep_count, Wl_pool[wi_index]);
2044 SDL_assert(wep_count[i] >= 0);
2045 Wl_pool[wi_index] -= wep_count[i];
2046 if ( wep_count[i] <= 0 ) {
2055 // Init the weapons portion of Wss_slots[] and the ui data in Wl_slots[]
2056 // NOTE: it is assumed that Wl_pool[] has been initialized, and Wss_slots[].ship_class is correctly set
2057 void wl_fill_slots()
2060 int wep[MAX_WL_WEAPONS];
2061 int wep_count[MAX_WL_WEAPONS];
2063 for ( i = 0; i < MAX_WSS_SLOTS; i++ ) {
2064 if ( Wss_slots[i].ship_class < 0 ){
2068 // get the weapons info that should be on ship by default
2069 wl_get_default_weapons(Wss_slots[i].ship_class, i, wep, wep_count);
2070 wl_remove_weps_from_pool(wep, wep_count, Wss_slots[i].ship_class);
2072 // copy to Wss_slots[]
2073 for ( j = 0; j < MAX_WL_WEAPONS; j++ ) {
2074 Wss_slots[i].wep[j] = wep[j];
2075 Wss_slots[i].wep_count[j] = wep_count[j];
2080 // set up the primary and secondary icons lists that hold the weapons the player can choose from
2081 void wl_init_icon_lists()
2085 Plist_start = 0; // offset into Plist[]
2088 Plist_size = 0; // number of active elements in Plist[]
2091 for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
2096 for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
2097 if ( Wl_pool[i] > 0 ) {
2098 if ( Weapon_info[i].subtype == WP_MISSILE ) {
2099 Slist[Slist_size++] = i;
2101 Plist[Plist_size++] = i;
2107 // initialize team specific weapon select data structures
2108 void weapon_select_init_team(int team_num)
2110 Wl_icons = Wl_icons_teams[team_num];
2111 ss_set_team_pointers(team_num);
2113 wl_init_pool(&Team_data[team_num]);
2114 wl_init_icon_lists();
2115 wl_init_ship_class_data();
2117 wl_load_all_icons();
2118 wl_load_all_anims();
2123 // close out what weapon_select_init_team() set up but only when we are not acutally
2124 // in the weapon select screen
2125 void weapon_select_close_team()
2127 if (Weapon_select_open)
2130 wl_unload_all_anim_instances();
2131 wl_unload_all_anims();
2134 // This init is called even before the weapons loadout screen is entered. It is called when the
2135 // briefing state is entered.
2136 void weapon_select_common_init()
2140 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
2141 // initialize for all teams
2142 for(idx=0;idx<MULTI_TS_MAX_TEAMS;idx++){
2143 weapon_select_init_team(idx);
2146 // re-initialize for me specifically
2147 weapon_select_init_team(Common_team);
2149 // initialize for my own team
2150 weapon_select_init_team(Common_team);
2153 wl_reset_selected_slot();
2154 wl_reset_carried_icon();
2155 wl_maybe_reset_selected_weapon_class();
2158 // ---------------------------------------------------------------------------------
2159 // weapon_select_init() is called to load the bitmaps and set up the mask regions for
2160 // the weapon loadout screen. common_select_init() is called to load the animations
2161 // and bitmaps which are in common with the ship select and briefing screens.
2163 // The Weapon_select_open flag is set to 1 when weapon_select_init() completes successfully
2165 void weapon_select_init()
2167 common_set_interface_palette("WeaponPalette");
2168 common_flash_button_init();
2170 // for multiplayer, change the state in my netplayer structure
2171 if ( Game_mode & GM_MULTIPLAYER )
2172 Net_player->state = NETPLAYER_STATE_WEAPON_SELECT;
2174 ship_stop_animation();
2175 stop_weapon_animation();
2176 Weapon_anim_class = -1;
2178 set_active_ui(&Weapon_ui_window);
2179 Current_screen = ON_WEAPON_SELECT;
2180 Last_wl_ship_class = -1;
2182 wl_maybe_reset_selected_slot();
2183 wl_set_disabled_weapons(Wss_slots[Selected_wl_slot].ship_class);
2185 help_overlay_set_state(WL_OVERLAY,0);
2187 if ( Weapon_select_open ) {
2188 wl_maybe_reset_selected_weapon_class();
2189 wl_start_slot_animation(Selected_wl_slot);
2190 common_buttons_maybe_reload(&Weapon_ui_window); // AL 11-21-97: this is necessary since we may returning from the hotkey
2191 // screen, which can release common button bitmaps.
2192 common_reset_buttons();
2193 nprintf(("Alan","weapon_select_init() returning without doing anything\n"));
2195 // if we're in multiplayer always select the player's ship
2196 wl_reset_selected_slot();
2201 nprintf(("Alan","entering weapon_select_init()\n"));
2202 common_select_init();
2204 WeaponSelectMaskBitmap = bm_load(Wl_loadout_select_mask[gr_screen.res]);
2205 if (WeaponSelectMaskBitmap < 0) {
2206 if (gr_screen.res == GR_640) {
2207 Error(LOCATION,"Could not load in 'weaponloadout-m'!");
2208 } else if (gr_screen.res == GR_1024) {
2209 Error(LOCATION,"Could not load in '2_weaponloadout-m'!");
2211 Error(LOCATION,"Could not load in 'weaponloadout-m'!");
2215 Weaponselect_mask_w = -1;
2216 Weaponselect_mask_h = -1;
2218 // get a pointer to bitmap by using bm_lock()
2219 WeaponSelectMaskPtr = bm_lock(WeaponSelectMaskBitmap, 8, BMP_AABITMAP);
2220 WeaponSelectMaskData = (ubyte*)WeaponSelectMaskPtr->data;
2221 SDL_assert(WeaponSelectMaskData != NULL);
2222 bm_get_info(WeaponSelectMaskBitmap, &Weaponselect_mask_w, &Weaponselect_mask_h);
2225 // Set up the mask regions
2226 // initialize the different regions of the menu that will react when the mouse moves over it
2227 Num_weapon_select_regions = 0;
2229 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", COMMON_BRIEFING_REGION, 0);
2230 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", COMMON_SS_REGION, 0);
2231 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", COMMON_WEAPON_REGION, 0);
2232 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", COMMON_COMMIT_REGION, 0);
2233 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", COMMON_HELP_REGION, 0);
2234 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", COMMON_OPTIONS_REGION, 0);
2236 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_0_SHIP_0, 0);
2237 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_0_SHIP_1, 0);
2238 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_0_SHIP_2, 0);
2239 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_0_SHIP_3, 0);
2240 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_1_SHIP_0, 0);
2241 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_1_SHIP_1, 0);
2242 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_1_SHIP_2, 0);
2243 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_1_SHIP_3, 0);
2244 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_2_SHIP_0, 0);
2245 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_2_SHIP_1, 0);
2246 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_2_SHIP_2, 0);
2247 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", WING_2_SHIP_3, 0);
2249 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_PRIMARY_0, 0);
2250 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_PRIMARY_1, 0);
2251 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_PRIMARY_2, 0);
2252 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_PRIMARY_3, 0);
2253 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SECONDARY_0, 0);
2254 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SECONDARY_1, 0);
2255 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SECONDARY_2, 0);
2256 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SECONDARY_3, 0);
2258 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SHIP_PRIMARY_0, 0);
2259 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SHIP_PRIMARY_1, 0);
2260 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SHIP_PRIMARY_2, 0);
2261 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SHIP_SECONDARY_0, 0);
2262 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SHIP_SECONDARY_1, 0);
2263 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SHIP_SECONDARY_2, 0);
2264 snazzy_menu_add_region(&Weapon_select_region[Num_weapon_select_regions++], "", ICON_SHIP_SECONDARY_3, 0);
2267 Weapon_ui_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );
2269 if(Game_mode & GM_MULTIPLAYER){
2270 Weapon_ui_window.set_mask_bmap(Wl_mask_multi[gr_screen.res]);
2272 Weapon_ui_window.set_mask_bmap(Wl_mask_single[gr_screen.res]);
2275 // initialize background bitmap
2276 if(Game_mode & GM_MULTIPLAYER) {
2277 Weapon_select_background_bitmap = bm_load(Weapon_select_multi_background_fname[gr_screen.res]);
2279 Weapon_select_background_bitmap = bm_load(Weapon_select_background_fname[gr_screen.res]);
2282 Weapon_ui_window.tooltip_handler = wl_tooltip_handler;
2283 common_buttons_init(&Weapon_ui_window);
2284 weapon_buttons_init();
2285 Weapon_select_open = 1;
2287 // if we're in multiplayer always select the player's ship
2288 wl_reset_selected_slot();
2291 // ----------------------------------------------------------------
2292 // wl_dump_carried_icon()
2293 void wl_dump_carried_icon()
2295 if ( wl_icon_being_carried() ) {
2296 // Add back into the weapon pool
2297 if ( Carried_wl_icon.from_bank >= 0 ) {
2299 wl_drop(Carried_wl_icon.from_bank, -1, -1, Carried_wl_icon.weapon_class, Carried_wl_icon.from_slot);
2301 if ( wl_carried_icon_moved() ) {
2302 gamesnd_play_iface(SND_ICON_DROP);
2306 wl_reset_carried_icon();
2310 // ----------------------------------------------------------------
2311 // drop_icon_on_slot()
2313 // Drop the Carried_wl_icon onto the specified slot. The slot numbering is:
2315 // 0->2: primary weapons
2316 // 3-6: secondary weapons
2318 // These are the slots that exist beside the overhead view of the ship.
2319 // on the weapons loadout screen.
2321 int drop_icon_on_slot(int bank_num)
2323 if ( Selected_wl_slot == -1 ) {
2327 if(Game_mode & GM_MULTIPLAYER){
2328 if(multi_ts_disabled_slot(Selected_wl_slot)){
2332 if ( ss_disabled_slot( Selected_wl_slot ) ){
2337 // check if slot exists
2338 if ( Wss_slots[Selected_wl_slot].wep_count[bank_num] < 0 ) {
2342 if ( !wl_carried_icon_moved() ) {
2343 wl_reset_carried_icon();
2347 wl_drop(Carried_wl_icon.from_bank, Carried_wl_icon.weapon_class, bank_num, -1, Selected_wl_slot);
2351 // ----------------------------------------------------------------
2352 // maybe_drop_icon_on_slot()
2354 void maybe_drop_icon_on_slot(int bank_num)
2357 if ( !mouse_down(MOUSE_LEFT_BUTTON) ) {
2358 if ( wl_icon_being_carried() )
2359 dropped = drop_icon_on_slot(bank_num);
2362 wl_reset_carried_icon();
2367 // ----------------------------------------------------------------
2368 // wl_check_for_stopped_ship_anims()
2370 void wl_check_for_stopped_ship_anims()
2374 for ( i = 0; i < MAX_SHIP_TYPES; i++ ) {
2375 ai = Wl_ships[i].anim_instance;
2377 if ( !anim_playing(ai) ) {
2378 Wl_ships[i].anim_instance = NULL;
2384 // ---------------------------------------------------------------------------------
2385 // do_mouse_over_list_weapon()
2387 void do_mouse_over_list_weapon(int index)
2389 Hot_weapon_icon = index;
2391 int region_index = ICON_PRIMARY_0+index;
2393 region_index = ICON_SECONDARY_0 + (index - 4);
2396 if ( Wl_mouse_down_on_region != region_index ){
2400 if ( mouse_down(MOUSE_LEFT_BUTTON) )
2401 wl_pick_icon_from_list(index);
2404 // ---------------------------------------------------------------------------------
2405 // do_mouse_over_ship_weapon()
2408 // input: index -> bank index on ship (0..6)
2411 // 0 -> icon was not dropped on a slot
2412 // 1 -> icon was dropped on a slot
2413 int do_mouse_over_ship_weapon(int index)
2415 int dropped_on_slot, is_moved, mx, my;
2417 dropped_on_slot = 0;
2418 SDL_assert(Selected_wl_slot >= 0);
2420 if ( ss_disabled_slot( Selected_wl_slot ) )
2423 Hot_weapon_bank_icon = index; // bank icon will be drawn highlighted
2425 if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
2426 if ( Wl_mouse_down_on_region == (ICON_SHIP_PRIMARY_0+index) ){
2427 pick_from_ship_slot(index);
2430 int was_carried = wl_icon_being_carried();
2431 maybe_drop_icon_on_slot(index);
2432 if ( was_carried && !wl_icon_being_carried() ) {
2433 mouse_get_pos( &mx, &my );
2434 if ( Carried_wl_icon.from_x != mx || Carried_wl_icon.from_y != my) {
2435 dropped_on_slot = 1;
2440 // set Hot_weapon_bank if a droppable icon is being held over a slot that
2441 // can accept that icon
2443 mouse_get_pos( &mx, &my );
2444 if ( Carried_wl_icon.from_x != mx || Carried_wl_icon.from_y != my) {
2448 if ( wl_icon_being_carried() && is_moved ) {
2449 if ( Weapon_info[Carried_wl_icon.weapon_class].subtype != WP_MISSILE ) {
2450 if ( (index < 3) && (Wss_slots[Selected_wl_slot].wep_count[index] >= 0) )
2451 Hot_weapon_bank = index;
2453 if ( index >= 3 && ( Wss_slots[Selected_wl_slot].wep_count[index] >= 0) )
2454 Hot_weapon_bank = index;
2458 return dropped_on_slot;
2462 // maybe flash a button if player hasn't done anything for a while
2463 void wl_maybe_flash_button()
2465 if ( common_flash_bright() ) {
2467 if ( Common_buttons[Current_screen-1][gr_screen.res][3].button.button_hilighted() ) {
2468 common_flash_button_init();
2470 Common_buttons[Current_screen-1][gr_screen.res][3].button.draw_forced(1);
2476 void weapon_select_render(float frametime)
2478 if ( !Background_playing ) {
2479 gr_set_bitmap(Weapon_select_background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2483 anim_render_all(0, frametime);
2484 anim_render_all(ON_SHIP_SELECT, frametime);
2487 // draw the weapon description text
2489 void wl_render_weapon_desc(float frametime)
2492 int *weapon_desc_coords;
2493 int *weapon_title_coords;
2495 // retrieve the correct set of text coordinates
2496 if (Game_mode & GM_MULTIPLAYER) {
2497 weapon_desc_coords = Wl_new_weapon_desc_coords_multi[gr_screen.res];
2498 weapon_title_coords = Wl_new_weapon_title_coords_multi[gr_screen.res];
2500 weapon_desc_coords = Wl_new_weapon_desc_coords[gr_screen.res];
2501 weapon_title_coords = Wl_new_weapon_title_coords[gr_screen.res];
2504 // render the normal version of the weapom desc
2505 char bright_char[WEAPON_DESC_MAX_LINES]; // one bright char per line
2506 if (!Weapon_desc_wipe_done) {
2507 // draw mid-wipe version
2508 // decide which char is last (and bright)
2509 int bright_char_index = (int)(Weapon_desc_wipe_time_elapsed * WEAPON_DESC_MAX_LENGTH / WEAPON_DESC_WIPE_TIME);
2510 int i, w, h, curr_len;
2512 // draw weapon title (above weapon anim)
2513 for (i=0; i<2; i++) {
2514 curr_len = strlen(Weapon_desc_lines[i]);
2516 if (bright_char_index < curr_len) {
2517 // save bright char and plunk in some nulls to shorten string
2518 bright_char[i] = Weapon_desc_lines[i][bright_char_index];
2519 Weapon_desc_lines[i][bright_char_index] = '\0';
2522 gr_set_color_fast(&Color_white);
2523 gr_string(weapon_title_coords[0], weapon_title_coords[1]+(10*i), Weapon_desc_lines[i]);
2525 // draw the bright letters
2526 gr_set_color_fast(&Color_bright_white);
2527 gr_get_string_size(&w, &h, Weapon_desc_lines[i], curr_len);
2528 gr_printf(weapon_title_coords[0]+w, weapon_title_coords[1]+(10*i), "%c", bright_char[i]);
2530 // restore the bright char to the string
2531 Weapon_desc_lines[i][bright_char_index] = bright_char[i];
2535 gr_set_color_fast(&Color_white);
2536 gr_string(weapon_title_coords[0], weapon_title_coords[1]+(10*i), Weapon_desc_lines[i]);
2540 // draw weapon desc (below weapon anim)
2541 for (i=2; i<WEAPON_DESC_MAX_LINES; i++) {
2542 curr_len = strlen(Weapon_desc_lines[i]);
2544 if (bright_char_index < curr_len) {
2545 // save bright char and plunk in some nulls to shorten string
2546 bright_char[i] = Weapon_desc_lines[i][bright_char_index];
2547 Weapon_desc_lines[i][bright_char_index] = '\0';
2550 gr_set_color_fast(&Color_white);
2551 gr_string(weapon_desc_coords[0], weapon_desc_coords[1]+(10*(i-2)), Weapon_desc_lines[i]);
2553 // draw the bright letters
2554 gr_set_color_fast(&Color_bright_white);
2555 gr_get_string_size(&w, &h, Weapon_desc_lines[i], curr_len);
2556 gr_printf(weapon_desc_coords[0]+w, weapon_desc_coords[1]+(10*(i-2)), "%c", bright_char[i]);
2558 // restore the bright char to the string
2559 Weapon_desc_lines[i][bright_char_index] = bright_char[i];
2563 gr_set_color_fast(&Color_white);
2564 gr_string(weapon_desc_coords[0], weapon_desc_coords[1]+(10*(i-2)), Weapon_desc_lines[i]);
2569 Weapon_desc_wipe_time_elapsed += frametime;
2570 if (Weapon_desc_wipe_time_elapsed >= WEAPON_DESC_WIPE_TIME) {
2571 // wipe is done,set flag and stop sound
2572 Weapon_desc_wipe_done = 1;
2577 // draw full version
2578 // FIXME - change to use a for loop
2579 gr_set_color_fast(&Color_white);
2580 gr_string(weapon_title_coords[0], weapon_title_coords[1], Weapon_desc_lines[0]);
2581 gr_string(weapon_title_coords[0], weapon_title_coords[1] + 10, Weapon_desc_lines[1]);
2582 gr_string(weapon_desc_coords[0], weapon_desc_coords[1], Weapon_desc_lines[2]);
2583 gr_string(weapon_desc_coords[0], weapon_desc_coords[1] + 10, Weapon_desc_lines[3]);
2584 gr_string(weapon_desc_coords[0], weapon_desc_coords[1] + 20, Weapon_desc_lines[4]);
2585 gr_string(weapon_desc_coords[0], weapon_desc_coords[1] + 30, Weapon_desc_lines[5]);
2592 // re-inits wiping vars and causes the current text to wipe in again
2593 void wl_weapon_desc_start_wipe()
2596 int currchar_src = 0, currline_dest = 2, currchar_dest = 0, i;
2598 int title_len = strlen(Weapon_info[Selected_wl_class].title);
2601 Weapon_desc_wipe_time_elapsed = 0.0f;
2602 Weapon_desc_wipe_done = 0;
2604 // break title into two lines if too long
2605 SDL_strlcpy(Weapon_desc_lines[0], Weapon_info[Selected_wl_class].title, WEAPON_DESC_MAX_LENGTH);
2606 gr_get_string_size(&w, &h, Weapon_info[Selected_wl_class].title, title_len);
2607 if (w > Weapon_title_max_width[gr_screen.res]) {
2609 currchar_src = (int)(((float)title_len / (float)w) * Weapon_title_max_width[gr_screen.res]); // char to start space search at
2610 while (Weapon_desc_lines[0][currchar_src] != ' ') {
2612 if (currchar_src <= 0) {
2613 currchar_src = title_len;
2618 Weapon_desc_lines[0][currchar_src] = '\0'; // shorten line 0
2619 SDL_strlcpy(Weapon_desc_lines[1], &(Weapon_desc_lines[0][currchar_src+1]), WEAPON_DESC_MAX_LENGTH); // copy remainder into line 1
2621 // entire title in line 0, thus line 1 is empty
2622 Weapon_desc_lines[1][0] = '\0';
2625 // break current description into lines (break at the /n's)
2627 while (Weapon_info[Selected_wl_class].desc[currchar_src] != '\0') {
2628 if (Weapon_info[Selected_wl_class].desc[currchar_src] == '\n') {
2630 if (currchar_src != 0) { // protect against leading /n's
2631 Weapon_desc_lines[currline_dest][currchar_dest] = '\0';
2637 Weapon_desc_lines[currline_dest][currchar_dest] = Weapon_info[Selected_wl_class].desc[currchar_src];
2643 SDL_assert(currline_dest < WEAPON_DESC_MAX_LINES);
2644 SDL_assert(currchar_dest < WEAPON_DESC_MAX_LENGTH);
2647 // wrap up the line processing
2648 Weapon_desc_lines[currline_dest][currchar_dest] = '\0';
2649 for (i=currline_dest+1; i<WEAPON_DESC_MAX_LINES; i++) {
2650 Weapon_desc_lines[i][0] = '\0';
2657 // ---------------------------------------------------------------------------------
2658 // weapon_select_do() is called once per frame while in the weapon loadout screen.
2660 // Calls to common_ functions are made for those functions which are common to the
2661 // ship select and briefing screens.
2663 void weapon_select_do(float frametime)
2665 int k, wl_choice, snazzy_action;
2668 if ( !Weapon_select_open )
2669 weapon_select_init();
2671 wl_choice = snazzy_menu_do(WeaponSelectMaskData, Weaponselect_mask_w, Weaponselect_mask_h, Num_weapon_select_regions, Weapon_select_region, &snazzy_action, 0);
2673 if ( wl_choice >= 0 ) {
2674 if ( snazzy_action == SNAZZY_CLICKED ) {
2675 nprintf(("Alan","got one\n"));
2680 Hot_weapon_icon = -1;
2681 Hot_weapon_bank = -1;
2682 Hot_weapon_bank_icon = -1;
2684 k = common_select_do(frametime);
2686 if ( help_overlay_active(WL_OVERLAY) ) {
2687 if ( Weapon_anim_class >= 0 && Wl_icons[Weapon_anim_class].anim_instance ) {
2688 anim_pause(Wl_icons[Weapon_anim_class].anim_instance);
2692 if ( Weapon_anim_class >= 0 && Wl_icons[Weapon_anim_class].anim_instance ) {
2693 anim_unpause(Wl_icons[Weapon_anim_class].anim_instance);
2697 // Check common keypresses
2698 common_check_keys(k);
2700 if ( Mouse_down_last_frame ) {
2701 Wl_mouse_down_on_region = wl_choice;
2704 if ( wl_choice > -1 ) {
2706 case ICON_PRIMARY_0:
2707 do_mouse_over_list_weapon(0);
2709 case ICON_PRIMARY_1:
2710 do_mouse_over_list_weapon(1);
2712 case ICON_PRIMARY_2:
2713 do_mouse_over_list_weapon(2);
2715 case ICON_PRIMARY_3:
2716 do_mouse_over_list_weapon(3);
2718 case ICON_SECONDARY_0:
2719 do_mouse_over_list_weapon(4);
2721 case ICON_SECONDARY_1:
2722 do_mouse_over_list_weapon(5);
2724 case ICON_SECONDARY_2:
2725 do_mouse_over_list_weapon(6);
2727 case ICON_SECONDARY_3:
2728 do_mouse_over_list_weapon(7);
2730 case ICON_SHIP_PRIMARY_0:
2731 if ( do_mouse_over_ship_weapon(0) )
2734 case ICON_SHIP_PRIMARY_1:
2735 if ( do_mouse_over_ship_weapon(1) )
2738 case ICON_SHIP_PRIMARY_2:
2739 if ( do_mouse_over_ship_weapon(2) )
2742 case ICON_SHIP_SECONDARY_0:
2743 if ( do_mouse_over_ship_weapon(3) )
2746 case ICON_SHIP_SECONDARY_1:
2747 if ( do_mouse_over_ship_weapon(4) )
2750 case ICON_SHIP_SECONDARY_2:
2751 if ( do_mouse_over_ship_weapon(5) )
2754 case ICON_SHIP_SECONDARY_3:
2755 if ( do_mouse_over_ship_weapon(6) )
2800 if ( !mouse_down(MOUSE_LEFT_BUTTON) ) {
2801 wl_dump_carried_icon();
2804 // Check for a mouse click on buttons
2805 common_check_buttons();
2806 weapon_check_buttons();
2808 // Check for the mouse clicks over a region
2809 if ( wl_choice > -1 && snazzy_action == SNAZZY_CLICKED ) {
2810 switch (wl_choice) {
2811 case ICON_PRIMARY_0:
2812 maybe_select_new_weapon(0);
2814 case ICON_PRIMARY_1:
2815 maybe_select_new_weapon(1);
2817 case ICON_PRIMARY_2:
2818 maybe_select_new_weapon(2);
2820 case ICON_PRIMARY_3:
2821 maybe_select_new_weapon(3);
2823 case ICON_SECONDARY_0:
2824 maybe_select_new_weapon(4);
2826 case ICON_SECONDARY_1:
2827 maybe_select_new_weapon(5);
2829 case ICON_SECONDARY_2:
2830 maybe_select_new_weapon(6);
2832 case ICON_SECONDARY_3:
2833 maybe_select_new_weapon(7);
2835 case ICON_SHIP_PRIMARY_0:
2836 maybe_select_new_ship_weapon(0);
2838 case ICON_SHIP_PRIMARY_1:
2839 maybe_select_new_ship_weapon(1);
2841 case ICON_SHIP_PRIMARY_2:
2842 maybe_select_new_ship_weapon(2);
2844 case ICON_SHIP_SECONDARY_0:
2845 maybe_select_new_ship_weapon(3);
2847 case ICON_SHIP_SECONDARY_1:
2848 maybe_select_new_ship_weapon(4);
2850 case ICON_SHIP_SECONDARY_2:
2851 maybe_select_new_ship_weapon(5);
2853 case ICON_SHIP_SECONDARY_3:
2854 maybe_select_new_ship_weapon(6);
2857 maybe_select_wl_slot(0,0);
2860 maybe_select_wl_slot(0,1);
2863 maybe_select_wl_slot(0,2);
2866 maybe_select_wl_slot(0,3);
2869 maybe_select_wl_slot(1,0);
2872 maybe_select_wl_slot(1,1);
2875 maybe_select_wl_slot(1,2);
2878 maybe_select_wl_slot(1,3);
2881 maybe_select_wl_slot(2,0);
2884 maybe_select_wl_slot(2,1);
2887 maybe_select_wl_slot(2,2);
2890 maybe_select_wl_slot(2,3);
2901 if ( Weapon_anim_class != -1 && ( Selected_wl_class == Weapon_anim_class ) ) {
2903 SDL_assert(Selected_wl_class >= 0 && Selected_wl_class < MAX_WEAPON_TYPES );
2904 if ( Weapon_anim_class != Selected_wl_class )
2905 start_weapon_animation(Selected_wl_class);
2907 SDL_assert(Weapon_anim_class == Selected_wl_class);
2908 icon = &Wl_icons[Selected_wl_class];
2909 if ( icon->anim_instance ) {
2910 if ( icon->anim_instance->frame_num == icon->anim_instance->stop_at ) {
2911 anim_play_struct aps;
2912 int *weapon_ani_coords;
2914 // get the correct weapon animations coords
2915 if (Game_mode & GM_MULTIPLAYER) {
2916 weapon_ani_coords = Wl_weapon_ani_coords_multi[gr_screen.res];
2918 weapon_ani_coords = Wl_weapon_ani_coords[gr_screen.res];
2921 anim_release_render_instance(icon->anim_instance);
2922 anim_play_init(&aps, icon->anim, weapon_ani_coords[0], weapon_ani_coords[1]);
2923 aps.start_at = WEAPON_ANIM_LOOP_FRAME-1;
2924 aps.screen_id = ON_WEAPON_SELECT;
2925 aps.framerate_independent = 1;
2926 aps.skip_frames = 0;
2927 icon->anim_instance = anim_play(&aps);
2932 weapon_select_render(frametime);
2933 if ( !Background_playing ) {
2934 Weapon_ui_window.draw();
2935 wl_redraw_pressed_buttons();
2937 anim_render_all(ON_WEAPON_SELECT, frametime);
2938 wl_check_for_stopped_ship_anims();
2939 wl_render_overhead_view(frametime);
2940 wl_draw_ship_weapons(Selected_wl_slot);
2941 for ( int i = 0; i < MAX_WING_BLOCKS; i++ ) {
2942 draw_wing_block(i, Hot_wl_slot, Selected_wl_slot, -1);
2944 common_render_selected_screen_button();
2947 // maybe blit the multiplayer "locked" button
2948 if((Game_mode & GM_MULTIPLAYER) && multi_ts_is_locked()){
2949 Buttons[gr_screen.res][WL_BUTTON_MULTI_LOCK].button.draw_forced(2);
2953 if ( wl_icon_being_carried() ) {
2955 SDL_assert(Carried_wl_icon.weapon_class < MAX_WEAPON_TYPES);
2956 mouse_get_pos( &mx, &my );
2957 sx = mx + Wl_delta_x;
2958 sy = my + Wl_delta_y;
2961 if ( Wl_icons[Carried_wl_icon.weapon_class].can_use > 0) {
2962 gr_set_color_fast(&Color_blue);
2963 gr_set_bitmap(Wl_icons[Carried_wl_icon.weapon_class].icon_bmaps[WEAPON_ICON_FRAME_SELECTED], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2967 // draw number to prevent it from disappearing on clicks
2968 if ( Carried_wl_icon.from_bank >= MAX_WL_PRIMARY ) {
2969 if ( mx == Carried_wl_icon.from_x && my == Carried_wl_icon.from_y ) {
2970 int num_missiles = Wss_slots[Carried_wl_icon.from_slot].wep_count[Carried_wl_icon.from_bank];
2971 //sprintf(buf, "%d", num_missiles);
2972 //gr_set_color_fast(&Color_white);
2974 //int x_offset = wl_fury_missile_offset_hack(Carried_wl_icon.weapon_class, num_missiles);
2975 //gr_string(sx-19-x_offset, sy+8, buf);
2978 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]);
2982 // check so see if this is really a legal weapon to carry away
2983 if ( !Wl_icons[Carried_wl_icon.weapon_class].can_use ) {
2985 diffx = abs(Carried_wl_icon.from_x-mx);
2986 diffy = abs(Carried_wl_icon.from_y-my);
2987 if ( (diffx > 2) || (diffy > 2) ) {
2988 int ship_class = Wss_slots[Selected_wl_slot].ship_class;
2991 // might have to get weapon name translation
2992 char display_name[128];
2993 SDL_strlcpy(display_name, Weapon_info[Carried_wl_icon.weapon_class].name, sizeof(display_name));
2994 lcl_translate_wep_name(display_name, sizeof(display_name));
2995 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);
2997 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);
3000 wl_dump_carried_icon();
3005 if ( Weapon_anim_class != Selected_wl_class ) {
3006 start_weapon_animation(Selected_wl_class);
3009 // render weapon description text
3010 wl_render_weapon_desc(frametime);
3012 wl_maybe_flash_button();
3014 // should render the chatbox as close to the end as possible so it overlaps all controls
3015 if(!Background_playing){
3017 // render some extra stuff in multiplayer
3018 if(Game_mode & GM_MULTIPLAYER){
3019 // render the chatbox
3023 Weapon_ui_window.draw_tooltip();
3025 // render the status indicator for the voice system
3026 multi_common_voice_display_status();
3028 // blit the "ships/players" locked button
3029 // multi_ts_blit_locked_button();
3033 // blit help overlay if active
3034 help_overlay_maybe_blit(WL_OVERLAY);
3037 // If the commit button was pressed, do the commit button actions. Done at the end of the
3038 // loop so there isn't a skip in the animation (since ship_create() can take a long time if
3039 // the ship model is not in memory
3040 if ( Commit_pressed ) {
3041 if(Game_mode & GM_MULTIPLAYER){
3042 multi_ts_commit_pressed();
3050 // -------------------------------------------------------------------------------
3051 // weapon_select_close() will free the bitmap slot and memory that was allocated
3052 // to store the mask bitmap.
3054 // Weapon_select_open is cleared when this function completes.
3056 void weapon_select_close()
3058 if ( !Weapon_select_open ) {
3059 nprintf(("Alan","weapon_select_close() returning without doing anything\n"));
3063 nprintf(("Alan", "Entering weapon_select_close()\n"));
3065 stop_weapon_animation();
3067 // done with the bitmaps, so unlock it
3068 bm_unlock(WeaponSelectMaskBitmap);
3070 Weapon_ui_window.destroy();
3073 common_free_interface_palette();
3077 help_overlay_unload(WL_OVERLAY);
3079 bm_unload(WeaponSelectMaskBitmap);
3082 wl_unload_all_anim_instances();
3083 wl_unload_all_anims();
3085 Selected_wl_class = -1;
3086 Weapon_select_open = 0;
3090 // ------------------------------------------------------------------------
3091 // wl_render_icon_count()
3092 // renders the number next to the weapon icon
3094 // input: x,y => x,y screen position OF THE ICON (NOT where u want the text,
3095 // this is calculated to prevent overlapping)
3096 // num => the actual count to be printed
3098 void wl_render_icon_count(int num, int x, int y)
3102 int number_to_draw = (num > 1000) ? 999 : num; // cap count @ 999
3103 SDL_assert(number_to_draw >= 0);
3105 SDL_snprintf(buf, sizeof(buf), "%d", number_to_draw);
3106 gr_get_string_size(&num_w, &num_h, buf, strlen(buf));
3109 gr_set_color_fast(&Color_white);
3111 // strict left align
3112 gr_string(x-21, y+8, buf);
3114 gr_string(x-num_w-4, y+8, buf);
3119 // ------------------------------------------------------------------------
3122 // input: index => index into Wl_icons[], identifying which weapon to draw
3123 // x,y => x,y screen position to draw icon at
3124 // num => count for weapon
3125 // draw_num_flag => 0 if not to draw count for weapon, nonzero otherwise
3126 // hot_mask => value that should match Hot_weapon_icon to show mouse is over
3127 // hot_bank_mask => value that should match Hot_weapon_bank_icon to show mouse is over
3128 // select_mask => value that should match Selected_wl_class to show icon is selected
3130 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)
3135 if ( Selected_wl_slot == -1 )
3138 icon = &Wl_icons[index];
3140 if ( icon->icon_bmaps[0] == -1 ) {
3141 wl_load_icons(index);
3144 // assume default bitmap is to be used
3145 bitmap_id = icon->icon_bmaps[WEAPON_ICON_FRAME_NORMAL]; // normal frame
3147 if ( bitmap_id < 0 ) {
3152 // next check if ship has mouse over it
3153 if ( !wl_icon_being_carried() ) {
3154 if ( Hot_weapon_icon > -1 && Hot_weapon_icon == hot_mask )
3155 bitmap_id = icon->icon_bmaps[WEAPON_ICON_FRAME_HOT];
3157 if ( Hot_weapon_bank_icon > -1 && Hot_weapon_bank_icon == hot_bank_mask )
3158 bitmap_id = icon->icon_bmaps[WEAPON_ICON_FRAME_HOT];
3161 // if icon is selected
3162 if ( Selected_wl_class > -1 ) {
3163 if ( Selected_wl_class == select_mask)
3164 bitmap_id = icon->icon_bmaps[WEAPON_ICON_FRAME_SELECTED]; // selected icon
3167 // if icon is disabled
3168 if ( !icon->can_use ) {
3169 bitmap_id = icon->icon_bmaps[WEAPON_ICON_FRAME_DISABLED]; // disabled icon
3172 gr_set_color_fast(&Color_blue);
3173 gr_set_bitmap(bitmap_id, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
3176 // draw the number of the item
3177 // now, right justified
3178 if ( draw_num_flag != 0 ) {
3180 // add a little extra text padding for secondary weapons
3181 if ( hot_mask > 3 ) {
3182 wl_render_icon_count(num, x-9, y);
3184 wl_render_icon_count(num, x, y);
3187 wl_render_icon_count(num, x, y);
3192 // ------------------------------------------------------------------------
3193 // wl_draw_ship_weapons()
3195 // Draw the icons for the weapons that are currently on the selected ship
3197 // input: slot_num => Slot to draw weapons for
3199 void wl_draw_ship_weapons(int index)
3202 int *wep, *wep_count;
3207 SDL_assert(index >= 0 && index < MAX_WSS_SLOTS);
3208 wep = Wss_slots[index].wep;
3209 wep_count = Wss_slots[index].wep_count;
3211 for ( i = 0; i < MAX_WL_WEAPONS; i++ ) {
3213 if ( Carried_wl_icon.from_bank == i && Carried_wl_icon.from_slot == index ) {
3217 if ( (wep[i] != -1) && (wep_count[i] > 0) ) {
3218 int x_offset = wl_fury_missile_offset_hack(wep[i], wep_count[i]);
3220 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]);
3225 // ------------------------------------------------------------------------
3226 // draw_wl_icon_with_number()
3228 // input: list_count => list position on screen (0-7)
3229 // weapon_class => class of weapon
3231 void draw_wl_icon_with_number(int list_count, int weapon_class)
3233 SDL_assert( list_count >= 0 && list_count < 8 );
3235 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],
3236 Wl_pool[weapon_class], 1, list_count, -1, weapon_class);
3239 // ------------------------------------------------------------------------
3242 // Draw the weapon icons that are available
3243 void draw_wl_icons()
3248 for ( i = Plist_start; i < Plist_size; i++ ) {
3249 draw_wl_icon_with_number(count, Plist[i]);
3255 for ( i = Slist_start; i < Slist_size; i++ ) {
3256 draw_wl_icon_with_number(count+4, Slist[i]);
3262 // ------------------------------------------------------------------------
3263 // wl_pick_icon_from_list()
3265 // determine if an icon from the scrollable weapon list can be picked up
3266 // (for drag and drop). It calculates the difference in x & y between the icon
3267 // and the mouse, so we can move the icon with the mouse in a realistic way
3268 // input: index (0..7)
3269 void wl_pick_icon_from_list(int index)
3271 int weapon_class, mx, my;
3273 // if this is a multiplayer game and the player is an observer, he can never pick any weapons up
3274 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
3278 // if a weapon is being carried, do nothing
3279 if ( wl_icon_being_carried() ) {
3284 weapon_class = Plist[Plist_start+index];
3286 weapon_class = Slist[Slist_start+index-4];
3289 // there isn't a weapon there at all!
3290 if ( weapon_class < 0 )
3293 // no weapons left of that class
3294 if ( Wl_pool[weapon_class] <= 0 ) {
3299 // some are available, but weapon cannot be used on current ship class
3300 if ( !Wl_icons[weapon_class].can_use ) {
3303 int ship_class = Wss_slots[Selected_wl_slot].ship_class;
3304 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);
3311 wl_set_carried_icon(-1, -1, weapon_class);
3312 common_flash_button_init();
3314 mouse_get_pos( &mx, &my );
3315 Wl_delta_x = Wl_weapon_icon_coords[gr_screen.res][index][0] - mx;
3316 Wl_delta_y = Wl_weapon_icon_coords[gr_screen.res][index][1] - my;
3319 // ------------------------------------------------------------------------
3320 // pick_from_ship_slot()
3322 // input: num -> index into shipb banks (0..2 primary, 3..6 secondary)
3323 void pick_from_ship_slot(int num)
3325 int mx, my, *wep, *wep_count;
3327 SDL_assert(num < 7);
3329 if ( Selected_wl_slot == -1 )
3332 if ( wl_icon_being_carried() )
3335 if ( ss_disabled_slot( Selected_wl_slot ) )
3338 wep = Wss_slots[Selected_wl_slot].wep;
3339 wep_count = Wss_slots[Selected_wl_slot].wep_count;
3341 // check if a weapon even exists in that slot
3342 if ( (wep[num] < 0) || (wep_count[num] <= 0) ) {
3346 SDL_assert(Wl_icons[wep[num]].can_use);
3348 wl_set_carried_icon(num, Selected_wl_slot, wep[num]);
3349 common_flash_button_init();
3351 mouse_get_pos( &mx, &my );
3353 int x_offset = wl_fury_missile_offset_hack(wep[num], wep_count[num]);
3354 Wl_delta_x = Wl_bank_coords[gr_screen.res][num][0] - mx + x_offset;
3355 Wl_delta_y = Wl_bank_coords[gr_screen.res][num][1] - my;
3357 Carried_wl_icon.from_x = mx;
3358 Carried_wl_icon.from_y = my;
3361 // determine if this slot has no weapons
3362 int wl_slots_all_empty(wss_unit *slot)
3366 for ( i = 0; i < MAX_WL_WEAPONS; i++ ) {
3367 if ( (slot->wep_count[i] > 0) && (slot->wep[i] >= 0) )
3374 // ------------------------------------------------------------------------
3375 // wl_update_ship_weapons()
3377 // Change a ship's weapons based on the information contained in the
3378 // Weapon_data[] structure that is filled in during weapon loadout
3380 // returns: -1 => if the playre ship has no weapons
3381 // 0 => function finished without errors
3382 int wl_update_ship_weapons(int objnum, wss_unit *slot )
3384 // AL 11-15-97: Ensure that the player ship hasn't removed all
3385 // weapons from their ship. This will cause a warning to appear.
3386 if ( objnum == OBJ_INDEX(Player_obj) && Weapon_select_open ) {
3387 if ( wl_slots_all_empty(slot) ) {
3392 wl_bash_ship_weapons(&Ships[Objects[objnum].instance].weapons, slot);
3397 // ------------------------------------------------------------------------
3398 // wl_update_parse_object_weapons()
3400 // Set the Pilot subsystem of a parse_object to the weapons that are setup
3401 // for the wing_block,wing_slot ship
3403 // input: pobjp => pointer to parse object that references Pilot subsystem
3405 void wl_update_parse_object_weapons(p_object *pobjp, wss_unit *slot)
3407 int i, j, sidx, pilot_index, max_count;
3410 SDL_assert(slot->ship_class >= 0);
3412 pilot_index = wl_get_pilot_subsys_index(pobjp);
3414 if ( pilot_index == -1 )
3417 ss = &Subsys_status[pilot_index];
3419 for ( i = 0; i < MAX_PRIMARY_BANKS; i++ ) {
3420 ss->primary_banks[i] = -1;
3423 for ( i = 0; i < MAX_SECONDARY_BANKS; i++ ) {
3424 ss->secondary_banks[i] = -1;
3428 for ( i = 0; i < MAX_WL_PRIMARY; i++ ) {
3429 if ( (slot->wep_count[i] > 0) && (slot->wep[i] >= 0) ) {
3430 ss->primary_banks[j] = slot->wep[i];
3436 for ( i = 0; i < MAX_WL_SECONDARY; i++ ) {
3437 sidx = i+MAX_WL_PRIMARY;
3438 if ( (slot->wep_count[sidx] > 0) && (slot->wep[sidx] >= 0) ) {
3439 ss->secondary_banks[j] = slot->wep[sidx];
3440 // Important: the secondary_ammo[] value is a percentage of max capacity!
3441 max_count = wl_calc_missile_fit(slot->wep[sidx], Ship_info[slot->ship_class].secondary_bank_ammo_capacity[j]);
3442 ss->secondary_ammo[j] = fl2i( i2fl(slot->wep_count[sidx]) / max_count * 100.0f + 0.5f);
3448 // ------------------------------------------------------------------------
3449 // stop_weapon_animation()
3451 // Stop the current weapon animation from playing.
3453 void stop_weapon_animation()
3455 if ( Weapon_anim_class < 0 )
3458 if ( anim_playing(Wl_icons[Weapon_anim_class].anim_instance) )
3459 anim_release_render_instance(Wl_icons[Weapon_anim_class].anim_instance);
3461 Wl_icons[Weapon_anim_class].anim_instance = NULL;
3462 Weapon_anim_class = -1;
3465 // ------------------------------------------------------------------------
3466 // start_weapon_animation()
3468 // Start the current weapon animation from playing.
3470 void start_weapon_animation(int weapon_class)
3473 int *weapon_ani_coords;
3475 if ( weapon_class < 0 )
3478 if ( weapon_class == Weapon_anim_class )
3481 // get the correct weapon animations coords
3482 if (Game_mode & GM_MULTIPLAYER) {
3483 weapon_ani_coords = Wl_weapon_ani_coords_multi[gr_screen.res];
3485 weapon_ani_coords = Wl_weapon_ani_coords[gr_screen.res];
3488 icon = &Wl_icons[weapon_class];
3490 // stop current animation playing
3491 stop_weapon_animation();
3493 // see if we need to load in the animation from disk
3494 if ( icon->anim == NULL ) {
3495 wl_load_anim(weapon_class);
3497 icon->anim = anim_load(Weapon_info[weapon_class].anim_filename, 1);
3498 if ( icon->anim == NULL ) {
3499 Int3(); // could not open the weapon animation
3505 // see if we need to get an instance
3506 if ( icon->anim_instance == NULL ) {
3507 anim_play_struct aps;
3509 anim_play_init(&aps, icon->anim, weapon_ani_coords[0], weapon_ani_coords[1]);
3510 aps.screen_id = ON_WEAPON_SELECT;
3511 aps.framerate_independent = 1;
3512 aps.skip_frames = 0;
3513 icon->anim_instance = anim_play(&aps);
3514 gamesnd_play_iface(SND_WEAPON_ANIM_START);
3517 Weapon_anim_class = weapon_class;
3519 // start the text wipe
3520 wl_weapon_desc_start_wipe();
3523 // reset the weapons loadout to the defaults in the mission
3524 void wl_reset_to_defaults()
3526 // don't reset of weapons pool in multiplayer
3527 if(Game_mode & GM_MULTIPLAYER){
3531 wl_init_pool(&Team_data[Common_team]);
3532 wl_init_icon_lists();
3534 wl_reset_selected_slot();
3535 wl_reset_carried_icon();
3536 wl_maybe_reset_selected_weapon_class();
3539 // Bash ship weapons, based on what is stored in the stored weapons loadout
3540 // NOTE: Wss_slots[] is assumed to be correctly set
3541 void wl_bash_ship_weapons(ship_weapon *swp, wss_unit *slot)
3545 for ( i = 0; i < MAX_PRIMARY_BANKS; i++ ) {
3546 swp->primary_bank_weapons[i] = -1;
3549 for ( i = 0; i < MAX_SECONDARY_BANKS; i++ ) {
3550 swp->secondary_bank_weapons[i] = -1;
3554 for ( i = 0; i < MAX_WL_PRIMARY; i++ ) {
3555 if ( (slot->wep_count[i] > 0) && (slot->wep[i] >= 0) ) {
3556 swp->primary_bank_weapons[j] = slot->wep[i];
3560 swp->num_primary_banks = j;
3563 for ( i = 0; i < MAX_WL_SECONDARY; i++ ) {
3564 sidx = i+MAX_WL_PRIMARY;
3565 if ( (slot->wep_count[sidx] > 0) && (slot->wep[sidx] >= 0) ) {
3566 swp->secondary_bank_weapons[j] = slot->wep[sidx];
3567 swp->secondary_bank_ammo[j] = slot->wep_count[sidx];
3571 swp->num_secondary_banks = j;
3574 // utility function for swapping two banks
3575 void wl_swap_weapons(int ship_slot, int from_bank, int to_bank)
3579 slot = &Wss_slots[ship_slot];
3581 if ( from_bank == to_bank ) {
3586 tmp = slot->wep[from_bank];
3587 slot->wep[from_bank] = slot->wep[to_bank];
3588 slot->wep[to_bank] = tmp;
3590 // swap weapon count
3591 tmp = slot->wep_count[from_bank];
3592 slot->wep_count[from_bank] = slot->wep_count[to_bank];
3593 slot->wep_count[to_bank] = tmp;
3596 // utility function used to put back overflow into the weapons pool
3597 void wl_saturate_bank(int ship_slot, int bank)
3600 int max_count, overflow;
3602 slot = &Wss_slots[ship_slot];
3604 if ( (slot->wep[bank] < 0) || (slot->wep_count <= 0) ) {
3608 max_count = wl_calc_missile_fit(slot->wep[bank], Ship_info[slot->ship_class].secondary_bank_ammo_capacity[bank-3]);
3609 overflow = slot->wep_count[bank] - max_count;
3610 if ( overflow > 0 ) {
3611 slot->wep_count[bank] -= overflow;
3612 // add overflow back to pool
3613 Wl_pool[slot->wep[bank]] += overflow;
3617 // exit: 0 -> no data changed
3618 // 1 -> data changed
3619 // sound => gets filled with sound id to play
3620 int wl_swap_slot_slot(int from_bank, int to_bank, int ship_slot, int *sound)
3623 slot = &Wss_slots[ship_slot];
3625 if ( slot->ship_class == -1 ) {
3626 Int3(); // should not be possible
3630 // do nothing if swapping with self
3631 if ( from_bank == to_bank ) {
3632 *sound=SND_ICON_DROP_ON_WING;
3633 return 0; // no update
3636 // ensure that source bank exists and has something to pick from
3637 if ( slot->wep[from_bank] == -1 || slot->wep_count[from_bank] <= 0 ) {
3641 // ensure that the dest bank exists
3642 if ( slot->wep_count[to_bank] < 0 ) {
3646 // ensure that the banks are both of the same class
3647 if ( (IS_BANK_PRIMARY(from_bank) && IS_BANK_SECONDARY(to_bank)) || (IS_BANK_SECONDARY(from_bank) && IS_BANK_PRIMARY(to_bank)) ) {
3648 // put from_bank back into list
3649 Wl_pool[slot->wep[from_bank]] += slot->wep_count[from_bank];; // return to list
3650 slot->wep[from_bank] = -1; // remove from slot
3651 slot->wep_count[from_bank] = 0;
3652 *sound=SND_ICON_DROP;
3656 // case 1: primaries (easy)
3657 if ( IS_BANK_PRIMARY(from_bank) && IS_BANK_PRIMARY(to_bank) ) {
3658 wl_swap_weapons(ship_slot, from_bank, to_bank);
3659 *sound=SND_ICON_DROP_ON_WING;
3663 // case 2: secondaries (harder)
3664 if ( IS_BANK_SECONDARY(from_bank) && IS_BANK_SECONDARY(to_bank) ) {
3666 // case 2a: secondaries are the same type
3667 if ( slot->wep[from_bank] == slot->wep[to_bank] ) {
3668 int dest_max, dest_can_fit, source_can_give;
3669 dest_max = wl_calc_missile_fit(slot->wep[to_bank], Ship_info[slot->ship_class].secondary_bank_ammo_capacity[to_bank-3]);
3671 dest_can_fit = dest_max - slot->wep_count[to_bank];
3673 if ( dest_can_fit <= 0 ) {
3674 // dest bank is already full.. nothing to do here
3678 // see how much source can give
3679 source_can_give = min(dest_can_fit, slot->wep_count[from_bank]);
3681 if ( source_can_give > 0 ) {
3682 slot->wep_count[to_bank] += source_can_give; // add to dest
3683 slot->wep_count[from_bank] -= source_can_give; // take from source
3684 *sound=SND_ICON_DROP_ON_WING;
3691 // case 2b: secondaries are different types
3692 if ( slot->wep[from_bank] != slot->wep[to_bank] ) {
3695 wl_swap_weapons(ship_slot, from_bank, to_bank);
3697 // put back some on list if required
3698 wl_saturate_bank(ship_slot, from_bank);
3699 wl_saturate_bank(ship_slot, to_bank);
3700 *sound=SND_ICON_DROP_ON_WING;
3705 Int3(); // should never get here
3709 // exit: 0 -> no data changed
3710 // 1 -> data changed
3711 // sound => gets filled with sound id to play
3712 int wl_dump_to_list(int from_bank, int to_list, int ship_slot, int *sound)
3715 slot = &Wss_slots[ship_slot];
3717 // ensure that source bank exists and has something to pick from
3718 if ( slot->wep[from_bank] == -1 || slot->wep_count[from_bank] <= 0 ) {
3722 // put weapon bank to the list
3723 Wl_pool[to_list] += slot->wep_count[from_bank]; // return to list
3724 slot->wep[from_bank] = -1; // remove from slot
3725 slot->wep_count[from_bank] = 0;
3726 *sound=SND_ICON_DROP;
3731 // exit: 0 -> no data changed
3732 // 1 -> data changed
3733 // sound => gets filled with sound id to play
3734 int wl_grab_from_list(int from_list, int to_bank, int ship_slot, int *sound)
3737 slot = &Wss_slots[ship_slot];
3740 // ensure that the banks are both of the same class
3741 if ( (IS_LIST_PRIMARY(from_list) && IS_BANK_SECONDARY(to_bank)) || (IS_LIST_SECONDARY(from_list) && IS_BANK_PRIMARY(to_bank)) ) {
3743 *sound=SND_ICON_DROP;
3747 // ensure that dest bank exists
3748 if ( slot->wep_count[to_bank] < 0 ) {
3749 *sound=SND_ICON_DROP;
3753 // bank should be empty:
3754 SDL_assert(slot->wep_count[to_bank] == 0);
3755 SDL_assert(slot->wep[to_bank] < 0);
3757 // ensure that pool has weapon
3758 if ( Wl_pool[from_list] <= 0 ) {
3762 // find how much dest bank can fit
3763 if ( to_bank < MAX_WL_PRIMARY ) {
3766 max_fit = wl_calc_missile_fit(from_list, Ship_info[slot->ship_class].secondary_bank_ammo_capacity[to_bank-MAX_WL_PRIMARY]);
3769 // take weapon from list
3770 if ( Wl_pool[from_list] < max_fit ) {
3771 max_fit = Wl_pool[from_list];
3773 Wl_pool[from_list] -= max_fit;
3776 slot->wep[to_bank] = from_list;
3777 slot->wep_count[to_bank] = max_fit;
3779 *sound=SND_ICON_DROP_ON_WING;
3783 // exit: 0 -> no data changed
3784 // 1 -> data changed
3785 // sound => gets filled with sound id to play
3786 int wl_swap_list_slot(int from_list, int to_bank, int ship_slot, int *sound)
3789 slot = &Wss_slots[ship_slot];
3792 // ensure that the banks are both of the same class
3793 if ( (IS_LIST_PRIMARY(from_list) && IS_BANK_SECONDARY(to_bank)) || (IS_LIST_SECONDARY(from_list) && IS_BANK_PRIMARY(to_bank)) ) {
3795 *sound=SND_ICON_DROP;
3799 // ensure that dest bank exists
3800 if ( slot->wep_count[to_bank] < 0 ) {
3804 // bank should have something in it
3805 SDL_assert(slot->wep_count[to_bank] > 0);
3806 SDL_assert(slot->wep[to_bank] >= 0);
3808 // ensure that pool has weapon
3809 if ( Wl_pool[from_list] <= 0 ) {
3813 // dump slot weapon back into list
3814 Wl_pool[slot->wep[to_bank]] += slot->wep_count[to_bank];
3815 slot->wep_count[to_bank] = 0;
3816 slot->wep[to_bank] = -1;
3818 // put weapon on ship from list
3820 // find how much dest bank can fit
3821 if ( to_bank < MAX_WL_PRIMARY ) {
3824 max_fit = wl_calc_missile_fit(from_list, Ship_info[slot->ship_class].secondary_bank_ammo_capacity[to_bank-MAX_WL_PRIMARY]);
3827 // take weapon from list
3828 if ( Wl_pool[from_list] < max_fit ) {
3829 max_fit = Wl_pool[from_list];
3831 Wl_pool[from_list] -= max_fit;
3834 slot->wep[to_bank] = from_list;
3835 slot->wep_count[to_bank] = max_fit;
3837 *sound=SND_ICON_DROP_ON_WING;
3841 // update any interface data that may be dependent on Wss_slots[]
3842 void wl_synch_interface()
3846 void wl_apply(int mode,int from_bank,int from_list,int to_bank,int to_list,int ship_slot,int player_index)
3852 // get the appropriate net player
3853 if(Game_mode & GM_MULTIPLAYER){
3854 if(player_index == -1){
3857 pl = &Net_players[player_index];
3864 case WSS_SWAP_SLOT_SLOT:
3865 update = wl_swap_slot_slot(from_bank, to_bank, ship_slot, &sound);
3867 case WSS_DUMP_TO_LIST:
3868 update = wl_dump_to_list(from_bank, to_list, ship_slot, &sound);
3870 case WSS_GRAB_FROM_LIST:
3871 update = wl_grab_from_list(from_list, to_bank, ship_slot, &sound);
3873 case WSS_SWAP_LIST_SLOT:
3874 update = wl_swap_list_slot(from_list, to_bank, ship_slot, &sound);
3878 // only play this sound if the move was done locally (by the host in other words)
3879 if ( (sound >= 0) && (player_index == -1) ) {
3880 gamesnd_play_iface(sound);
3884 if ( MULTIPLAYER_HOST ) {
3886 ubyte wss_data[MAX_PACKET_SIZE-20];
3888 size = store_wss_data(wss_data, MAX_PACKET_SIZE-20,sound,player_index);
3889 SDL_assert(pl != NULL);
3890 send_wss_update_packet(pl->p_info.team,wss_data, size);
3893 if(Game_mode & GM_MULTIPLAYER){
3894 SDL_assert(pl != NULL);
3896 // if the pool we're using has changed, synch stuff up
3897 if(pl->p_info.team == Net_player->p_info.team){
3898 wl_synch_interface();
3901 wl_synch_interface();
3906 void wl_drop(int from_bank,int from_list,int to_bank,int to_list, int ship_slot, int player_index)
3911 // get the appropriate net player
3912 if(Game_mode & GM_MULTIPLAYER){
3913 if(player_index == -1){
3916 pl = &Net_players[player_index];
3922 common_flash_button_init();
3923 if ( !(Game_mode & GM_MULTIPLAYER) || MULTIPLAYER_HOST ) {
3924 if ( (Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM) ) {
3925 SDL_assert(pl != NULL);
3926 // set the global pointers to the right pools
3927 ss_set_team_pointers(pl->p_info.team);
3931 mode = wss_get_mode(from_bank, from_list, to_bank, to_list, ship_slot);
3933 wl_apply(mode, from_bank, from_list, to_bank, to_list, ship_slot, player_index);
3936 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_TEAM)){
3937 // set the global pointers to the right pools
3938 ss_set_team_pointers(Net_player->p_info.team);
3941 send_wss_request_packet(Net_player->player_id, from_bank, from_list, to_bank, to_list, ship_slot, -1, WSS_WEAPON_SELECT);