1 /*
2 	weapons.c
3 
4 	Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 	and the "Aleph One" developers.
6 
7 	This program is free software; you can redistribute it and/or modify
8 	it under the terms of the GNU General Public License as published by
9 	the Free Software Foundation; either version 3 of the License, or
10 	(at your option) any later version.
11 
12 	This program is distributed in the hope that it will be useful,
13 	but WITHOUT ANY WARRANTY; without even the implied warranty of
14 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 	GNU General Public License for more details.
16 
17 	This license is contained in the file "COPYING",
18 	which is included with this source code; it is available online at
19 	http://www.gnu.org/licenses/gpl.html
20 
21 	Saturday, May 13, 1995 4:41:04 PM- rdm created.
22 		Recreating to fix all the annoying problems.
23 
24 Feb. 4, 2000 (Loren Petrich):
25 	Changed halt() to assert(false) for better debugging
26 
27 Feb 19, 2000 (Loren Petrich):
28 	Suppressed debug checking of which weapons and triggers
29 	in get_trigger_definition()
30 
31 March 2, 2000 (Loren Petrich):
32 	Suppressed player_weapon_has_ammo() assert in should_switch_to_weapon();
33 	causes problems in "Missed Island"'s first level.
34 
35 March 3, 2000 (Loren Petrich):
36 	Suppressed complicated assert in fire_weapon();
37 	 causes problems in the map "Dirt Devil", which turns the flamethrower into a jetpack.
38 
39 Apr 27, 2000 (Loren Petrich):
40 	Added Josh Elsasser's "don't switch weapons" patch
41 
42 May 23, 2000 (Loren Petrich):
43 	Correct behavior of weapon luminosity; it now adds to miner's light
44 	rather than substituting for it.
45 
46 May 26, 2000 (Loren Petrich):
47 	Added XML configuration of shell casings and weapon order.
48 	Attempted to add more graceful behavior for some weapons being NONE.
49 	In Muerte Machine, the weapons are disabled if the fists have weapon type NONE;
50 	implemented the use of this as a flag.
51 
52 	Added "CannotWieldWeapons()" test; it returns true if the fists have a weapon type of NONE
53 
54 Jun 14, 2000 (Loren Petrich):
55 	Suppressed assertion about multiple triggers that follows the Dirt-Devil one
56 
57 Jun 15, 2000 (Loren Petrich):
58 	Added support for Chris Pruett's Pfhortran
59 
60 Jul 1, 2000 (Loren Petrich):
61 	Made some accessors inline
62 
63 Jul 1, 2000 (Loren Petrich):
64 	Added Benad's changes
65 
66 Aug 31, 2000 (Loren Petrich):
67 	Added stuff for unpacking and packing
68 
69 Sep 3, 2000 (Loren Petrich):
70 	Suppressed "assert(weapon_type!=NUMBER_OF_WEAPONS);" in a search-for-which-weapon loop;
71 	some physics models get to this without causing other trouble
72 
73 Oct 19, 2000 (Loren Petrich):
74 	Weapon-sprite absence in get_weapon_display_information() handled by bugging out instead of
75 	a failed assertion; having a SMG will not crash if one's using a M2 shapes file.
76 	Also, added a bug-out in case of no view being found.
77 
78 Dec 24, 2000 (Loren Petrich):
79 	Added support for idle-weapon animations
80 
81 Dec 31, 2000 (Loren Petrich):
82 	Turned a remaining out-of-range assert into a no-render
83 
84 Jan 6, 2001 (Loren Petrich):
85 	Added modification of guided-projectile patch from AlexJLS@aol.com;
86 	one can now shoot guided missiles.
87 
88 Feb 1, 2001 (Loren Petrich):
89 	Added fix for firing-animation wraparound; prevent_wrap is true for those animations also.
90 
91 Apr 10, 2003 (Woody Zenfell):
92         Fixed bug where dropping the skull made two of them (had this really been in there for almost 3 years??)
93 */
94 
95 #include "cseries.h"
96 #include "map.h"
97 #include "projectiles.h"
98 #include "player.h"
99 #include "weapons.h"
100 #include "SoundManager.h"
101 #include "interface.h"
102 #include "items.h"
103 #include "monsters.h"
104 #include "game_window.h"
105 #include "preferences.h"
106 #include "InfoTree.h"
107 
108 #include "Packing.h"
109 #include "shell.h"
110 
111 #include <string.h>
112 #include <stdlib.h>
113 #include <limits.h>
114 
115 #include "weapon_definitions.h"
116 
117 // To Do:
118 // lowering second weapon on ammo empty flubs.
119 
120 /* ------------- enums */
121 enum /* weapon states */
122 {
123 	_weapon_idle, /* if weapon_delay is non-zero, the weapon cannot be fired again yet */
124 	_weapon_raising, /* weapon is rising to idle position */
125 	_weapon_lowering, /* weapon is lowering off the screen */
126 	_weapon_charging, /* Weapon is charging to fire.. */
127 	_weapon_charged, /* Ready to fire.. */
128 	_weapon_firing, /* in firing animation */
129 	_weapon_recovering, /* Weapon is recovering from firing. */
130 	_weapon_awaiting_reload, /* About to start reload sequence */
131 	_weapon_waiting_to_load, /* waiting to actually put bullets in */
132 	_weapon_finishing_reload, /* finishing the reload */
133 
134 	_weapon_lowering_for_twofisted_reload,	/* lowering so the other weapon can reload */
135 	_weapon_awaiting_twofisted_reload, /* waiting for other to lower.. */
136 	_weapon_waiting_for_twofist_to_reload, /* we are offscreen, waiting for the other to finish its load */
137 	_weapon_sliding_over_to_second_position, /* pistol is going across when the weapon is present */
138 	_weapon_sliding_over_from_second_position, /* Pistol returning to center of screen.. */
139 	_weapon_waiting_for_other_idle_to_reload, /* Pistol awaiting friend's idle.. */
140 	NUMBER_OF_WEAPON_STATES
141 };
142 
143 enum {
144 	_trigger_down= 0x0001,
145 	_primary_weapon_is_up= 0x0002,
146 	_secondary_weapon_is_up= 0x0004,
147 	_wants_twofist= 0x0008,
148 	_flip_state= 0x0010
149 };
150 
151 enum {
152 	_weapon_type= 0,
153 	_shell_casing_type,
154 	_weapon_ammo_type,
155 	NUMBER_OF_DATA_TYPES
156 };
157 
158 enum { /* For the flags */ /* [11.unused 1.horizontal 1.vertical 3.unused] */
159 	_flip_shape_horizontal= 0x08,
160 	_flip_shape_vertical= 0x10
161 };
162 
163 #define PRIMARY_WEAPON_IS_VALID(wd) ((wd)->flags & _primary_weapon_is_up)
164 #define SECONDARY_WEAPON_IS_VALID(wd) ((wd)->flags & _secondary_weapon_is_up)
165 #define SET_PRIMARY_WEAPON_IS_VALID(wd, v)  ((void)((v) ? ((wd)->flags |= _primary_weapon_is_up) : ((wd)->flags &= ~_primary_weapon_is_up)))
166 #define SET_SECONDARY_WEAPON_IS_VALID(wd, v)  ((void)((v) ? ((wd)->flags |= _secondary_weapon_is_up) : ((wd)->flags &= ~_secondary_weapon_is_up)))
167 
168 #define SET_WEAPON_WANTS_TWOFIST(wd, v)  ((void)((v) ? ((wd)->flags |= _wants_twofist) : ((wd)->flags &= ~_wants_twofist)))
169 #define WEAPON_WANTS_TWOFIST(wd) ((wd)->flags & _wants_twofist)
170 
171 #define TRIGGER_IS_DOWN(wd) ((wd)->flags & _trigger_down)
172 #define SET_TRIGGER_DOWN(wd, v)  ((void)((v) ? ((wd)->flags |= _trigger_down) : ((wd)->flags &= ~_trigger_down)))
173 
174 #define GET_WEAPON_VARIANCE_SIGN(wd) (((wd)->flags & _flip_state) ? (1) : (-1))
175 #define FLIP_WEAPON_VARIANCE_SIGN(wd) (((wd)->flags & _flip_state) ? ((wd)->flags &= ~_flip_state) : ((wd)->flags |= _flip_state))
176 
177 #define PISTOL_SEPARATION_WIDTH (FIXED_ONE/4)
178 #define AUTOMATIC_STILL_FIRING_DURATION (4)
179 #define FIRING_BEFORE_SHELL_CASING_SOUND_IS_PLAYED (TICKS_PER_SECOND/2)
180 #define COST_PER_CHARGED_WEAPON_SHOT 4
181 #define ANGULAR_VARIANCE (32)
182 
183 #define M1_MISSILE_AMMO_SEQUENCE 20
184 #define M1_MISSILE_AMMO_XOFFSET (FIXED_ONE/12)
185 #define M1_MISSILE_AMMO_YOFFSET (-FIXED_ONE/15)
186 
187 enum // shell casing flags
188 {
189 	_shell_casing_is_reversed= 0x0001
190 };
191 #define SHELL_CASING_IS_REVERSED(s) ((s)->flags&_shell_casing_is_reversed)
192 
193 /* ----------- structures */
194 /* ...were all moved to weapons.h */
195 
196 /* ------------- globals */
197 /* The array of player weapon states */
198 static struct player_weapon_data *player_weapons_array;
199 
200 /* ------------- macros */
201 #define get_maximum_number_of_players() (MAXIMUM_NUMBER_OF_PLAYERS)
202 #define BUILD_WEAPON_IDENTIFIER(weapon, trigger) (weapon<<1+trigger)
203 #define GET_WEAPON_FROM_IDENTIFIER(identifier) (identifier>>1)
204 #define GET_TRIGGER_FROM_IDENTIFIER(identifier) (identifier&1)
205 
206 /*static*/ player_weapon_data *get_player_weapon_data(
207 	const short player_index);
208 
209 static weapon_definition *get_weapon_definition(
210 	const short weapon_type);
211 
212 static shell_casing_definition *get_shell_casing_definition(
213 	const short type);
214 
215 /* -------------- accessors */
216 
get_player_weapon_data(const short player_index)217 player_weapon_data *get_player_weapon_data(
218 	const short player_index)
219 {
220 	player_weapon_data *data = GetMemberWithBounds(player_weapons_array,player_index,get_maximum_number_of_players());
221 	assert(data);
222 
223 	return data;
224 }
225 
get_weapon_definition(const short weapon_type)226 weapon_definition *get_weapon_definition(
227 	const short weapon_type)
228 {
229 	weapon_definition *definition = GetMemberWithBounds(weapon_definitions,weapon_type,NUMBER_OF_WEAPONS);
230 	assert(definition);
231 
232 	return definition;
233 }
234 
get_shell_casing_definition(const short type)235 shell_casing_definition *get_shell_casing_definition(
236 	const short type)
237 {
238 	shell_casing_definition *definition = GetMemberWithBounds(shell_casing_definitions,type,NUMBER_OF_SHELL_CASING_TYPES);
239 	assert(definition);
240 
241 	return definition;
242 }
243 
244 /* ------------- local prototypes */
245 static void reset_trigger_data(short player_index, short weapon_type, short which_trigger);
246 static bool weapon_works_in_current_environment(short weapon_index);
247 /*static*/ void select_next_best_weapon(short player_index);
248 static struct trigger_data *get_player_trigger_data(short player_index,
249 	short which_trigger);
250 struct trigger_data *get_trigger_data(short player_index, short weapon_index,
251 	short which_trigger);
252 static struct weapon_data *get_player_current_weapon(short player_index);
253 static void fire_weapon(short player_index, short which_trigger,
254 	_fixed charged_amount, bool flail_wildly);
255 static struct trigger_definition *get_trigger_definition(short player_index, short which_weapon,
256 	short which_trigger);
257 static bool should_switch_to_weapon(short player_index, short new_weapon);
258 /* CP Addition: 'static' removed from decleration of ready_weapon() */
259 /*static*/ bool ready_weapon(short player_index, short weapon_index);
260 struct weapon_definition *get_current_weapon_definition(short player_index);
261 static bool reload_weapon(short player_index, short which_trigger);
262 static struct trigger_definition *get_player_trigger_definition(short player_index,
263 	short which_trigger);
264 static bool handle_trigger_down(short player_index, short which_trigger);
265 static bool handle_trigger_up(short player_index, short which_trigger);
266 static void put_rounds_into_weapon(short player_index, short which_weapon, short which_trigger);
267 static void blow_up_player(short player_index);
268 static void select_next_weapon(short player_index, bool forward);
269 static void calculate_weapon_position_for_idle(short player_index, short count, short weapon_type,
270 					       _fixed *height, _fixed *width, bool use_elevation);
271 static void add_random_flutter(_fixed flutter_base, _fixed *height, _fixed *width);
272 static void calculate_weapon_origin_and_vector(short player_index, short which_trigger,
273 	world_point3d *origin, world_point3d *_vector, short *origin_polygon, angle delta_theta);
274 static void play_weapon_sound(short player_index, short sound, _fixed pitch);
275 static bool player_weapon_has_ammo(short player_index, short weapon_index);
276 static void lower_weapon(short player_index, short weapon_index);
277 static void raise_weapon(short player_index, short weapon_index);
278 static bool check_reload(short player_index, short which_trigger);
279 static short get_active_trigger_count_and_states(short player_index,
280 	short weapon_index, uint32 action_flags, short *first_trigger, bool *triggers_down);
281 static bool dual_function_secondary_has_control(short player_index);
282 static void calculate_ticks_from_shapes(void);
283 static void update_sequence(short player_index, short which_trigger);
284 static void update_automatic_sequence(short player_index, short which_trigger);
285 static bool get_weapon_data_type_for_count(short player_index, short count, short *type,
286 	short *index, short *flags);
287 static void update_player_ammo_count(short player_index);
288 /*static*/ bool player_has_valid_weapon(short player_index);
289 static void idle_weapon(short player_index);
290 static void test_raise_double_weapon(short player_index, uint32 *action_flags);
291 static void modify_position_for_two_weapons(short player_index, short count, _fixed *width, _fixed *height);
292 static void change_to_desired_weapon(short player_index);
293 static void destroy_current_weapon(short player_index);
294 static void initialize_shell_casings(short player_index);
295 static short new_shell_casing(short player_index, short type, uint16 flags);
296 static void update_shell_casings(short player_index);
297 static bool get_shell_casing_display_data(struct weapon_display_information *display, short index);
298 static bool automatic_still_firing(short player_index, short which_trigger);
299 static void	play_shell_casing_sound(short player_index, short sound_index);
300 static short find_weapon_power_index(short weapon_type);
301 
302 #ifdef DEBUG
303 	static void debug_weapon(short index);
304 	static void debug_trigger_data(short weapon_type, short which_trigger);
305 #endif
306 
307 
308 // LP addition: this function indicates whether weapons can be wielded
309 // Set to fists being NONE
CannotWieldWeapons()310 inline bool CannotWieldWeapons()
311 	{return get_weapon_definition(_weapon_fist)->weapon_class == NONE;}
312 
313 // For animating the idle weapons shape
314 static void UpdateIdleAnimation(short player_index, short which_trigger);
315 
316 
317 /* ------------ code starts */
initialize_weapon_manager(void)318 void initialize_weapon_manager(
319 	void)
320 {
321 	player_weapons_array= (struct player_weapon_data *) malloc(MAXIMUM_NUMBER_OF_PLAYERS*sizeof(struct player_weapon_data));
322 	assert(player_weapons_array);
323 
324 	objlist_clear(player_weapons_array, MAXIMUM_NUMBER_OF_PLAYERS);
325 }
326 
initialize_player_weapons_for_new_game(short player_index)327 void initialize_player_weapons_for_new_game(
328 	short player_index)
329 {
330 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
331 
332 	/* Clear the shots fired and all that jazz */
333 	obj_clear(*player_weapons);
334 
335 	/* initialize the weapons to known states. */
336 	initialize_player_weapons(player_index);
337 	initialize_shell_casings(player_index);
338 }
339 
340 /* initialize the given players weapons-> called after creating a player */
initialize_player_weapons(short player_index)341 void initialize_player_weapons(
342 	short player_index)
343 {
344 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
345 	struct player_data *player= get_player_data(player_index);
346 
347 	for(unsigned weapon_type= 0; weapon_type<NUMBER_OF_WEAPONS; ++weapon_type)
348 	{
349 		short which_trigger;
350 
351 		for(which_trigger= 0; which_trigger<NUMBER_OF_TRIGGERS; ++which_trigger)
352 		{
353 			reset_trigger_data(player_index, weapon_type, which_trigger);
354 		}
355 
356 		/* We _could_ figure this out, but this is easier.. */
357 		player_weapons->weapons[weapon_type].weapon_type= weapon_type;
358 		player_weapons->weapons[weapon_type].flags= 0;
359 		player_weapons->weapons[weapon_type].unused= 0;
360 	}
361 
362 	/* Reset the current and desired weapon.. */
363 	player_weapons->current_weapon= NONE;
364 	player_weapons->desired_weapon= NONE;
365 
366 	/* Reset the player crap.. */
367 	player->weapon_intensity= NATURAL_LIGHT_INTENSITY;
368 	player->weapon_intensity_decay= 0;
369 }
370 
371 /* Mark the weapon collections for loading or unloading.. */
mark_weapon_collections(bool loading)372 void mark_weapon_collections(
373 	bool loading)
374 {
375 	for(unsigned index= 0; index<NUMBER_OF_WEAPONS; ++index)
376 	{
377 		struct weapon_definition *definition= get_weapon_definition(index);
378 
379 		/* Mark the weapon�s collection */
380 		loading ? mark_collection_for_loading(definition->collection) :
381 			mark_collection_for_unloading(definition->collection);
382 
383 		/* Mark the projectile�s collection, NONE is handled correctly */
384 		if(index != _weapon_ball)
385 		{
386 			mark_projectile_collections(definition->weapons_by_trigger[_primary_weapon].projectile_type, loading);
387 			mark_projectile_collections(definition->weapons_by_trigger[_secondary_weapon].projectile_type, loading);
388 		}
389 	}
390 }
391 
player_hit_target(short player_index,short weapon_identifier)392 void player_hit_target(
393 	short player_index,
394 	short weapon_identifier)
395 {
396 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
397 	short weapon_id, trigger;
398 
399 	weapon_id= GET_WEAPON_FROM_IDENTIFIER(weapon_identifier);
400 	trigger= GET_TRIGGER_FROM_IDENTIFIER(weapon_identifier);
401 
402 	assert(weapon_id>=0 && weapon_id<short(NUMBER_OF_WEAPONS));
403 	player_weapons->weapons[weapon_id].triggers[trigger].shots_hit++;
404 }
405 
406 /* Called on entry to a level, and will change weapons if this one doesn't work */
407 /*  in the given environment. */
check_player_weapons_for_environment_change(void)408 void check_player_weapons_for_environment_change(
409 	void)
410 {
411 	short player_index;
412 
413 	for(player_index=0; player_index<dynamic_world->player_count; ++player_index)
414 	{
415 		if(player_has_valid_weapon(player_index))
416 		{
417 			struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
418 
419 			if(!weapon_works_in_current_environment(player_weapons->current_weapon))
420 			{
421 				/* Change out of the current weapon immediately.. */
422 				player_weapons->current_weapon= NONE;
423 
424 				/* Select the next best weapon for this person.. */
425 				select_next_best_weapon(player_index);
426 			}
427 		}
428 	}
429 
430 	/* while we are at it, setup the definitions for the weapons */
431 	calculate_ticks_from_shapes();
432 }
433 
434 /* Called when a player dies to discharge the weapons that they have charged up. */
discharge_charged_weapons(short player_index)435 void discharge_charged_weapons(
436 	short player_index)
437 {
438 	struct trigger_data *weapon;
439 	short which_trigger;
440 
441 	if(player_has_valid_weapon(player_index))
442 	{
443 		short first_trigger, trigger_count;
444 		struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
445 
446 		trigger_count= get_active_trigger_count_and_states(player_index, player_weapons->current_weapon,
447 			0l, &first_trigger, NULL);
448 		for(which_trigger= first_trigger; which_trigger<trigger_count; ++which_trigger)
449 		{
450 			weapon= get_player_trigger_data(player_index, which_trigger);
451 			if(weapon->state==_weapon_charged)
452 			{
453 				/* Fire the weapon! (give it to them fully charged..) */
454 				fire_weapon(player_index, which_trigger, FIXED_ONE, true);
455 			}
456 		}
457 	}
458 }
459 
460 /* When the player runs over an item, check for reloads, etc. */
process_new_item_for_reloading(short player_index,short item_type)461 void process_new_item_for_reloading(
462 	short player_index,
463 	short item_type)
464 {
465 	/* Is this a weapon? */
466 	switch(get_item_kind(item_type))
467 	{
468 		case _ball:
469 		case _weapon:
470 			for(unsigned weapon_type= 0; weapon_type<NUMBER_OF_WEAPONS; ++weapon_type)
471 			{
472 				struct weapon_definition *definition= get_weapon_definition(weapon_type);
473 
474 				/* If this is actually a weapon.. */
475 				if(definition->item_type==item_type)
476 				{
477 					short which_trigger, first_trigger, trigger_count;
478 					struct player_data *player= get_player_data(player_index);
479 
480 					/* Load the weapons */
481 					if(definition->weapon_class==_twofisted_pistol_class)
482 					{
483 						// Skip over unrecognized ones
484 						assert(definition->item_type>=0 && definition->item_type<NUMBER_OF_ITEMS);
485 						if(player->items[definition->item_type]>1)
486 						{
487 							/* Just load the secondary one.. */
488 							first_trigger= _secondary_weapon;
489 							trigger_count= 2;
490 
491 							/* Go ahead and mark the weapon display as dirty (because it will be) */
492 							update_player_ammo_count(player_index);
493 							if(player_index==current_player_index) mark_weapon_display_as_dirty();
494 						} else {
495 							first_trigger= _primary_weapon;
496 							trigger_count= 1;
497 						}
498 					} else {
499 						/* They aren't twofisted pistols */
500 						first_trigger= _primary_weapon;
501 						switch(definition->weapon_class)
502 						{
503 							case _normal_class:
504 								trigger_count= 1;
505 								break;
506 
507 							case _dual_function_class:
508 							case _melee_class:
509 							case _multipurpose_class:
510 								trigger_count= 2;
511 								break;
512 
513 							// LP change: no weapon
514 							case NONE:
515 							case _twofisted_pistol_class:
516 							default:
517 								trigger_count = 0;
518 								break;
519 						}
520 					}
521 
522 					/* Reset the trigger data.. */
523 					for(which_trigger= first_trigger; which_trigger<trigger_count; ++which_trigger)
524 					{
525 						struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
526 						struct trigger_definition *trigger_definition=
527 							get_trigger_definition(player_index, weapon_type, which_trigger);
528 
529 						/* Reset it. */
530 						reset_trigger_data(player_index, weapon_type, which_trigger);
531 
532 						if(definition->flags & _weapon_has_random_ammo_on_pickup)
533 						{
534 							short rounds_given;
535 
536 							rounds_given= trigger_definition->rounds_per_magazine/2 +
537 								(global_random()%(trigger_definition->rounds_per_magazine/2+1));
538 							player_weapons->weapons[weapon_type].triggers[which_trigger].rounds_loaded=
539 								rounds_given;
540 
541 							/* Sync the weapons ammo amounts.. */
542 							if(definition->flags & _weapon_triggers_share_ammo)
543 							{
544 								player_weapons->weapons[weapon_type].triggers[!which_trigger].rounds_loaded=
545 									rounds_given;
546 							}
547 						} else {
548 							player_weapons->weapons[weapon_type].triggers[which_trigger].rounds_loaded=
549 								trigger_definition->rounds_per_magazine;
550 						}
551 					}
552 
553 					if(should_switch_to_weapon(player_index, weapon_type))
554 					{
555 						if(!ready_weapon(player_index, weapon_type))
556 						{
557 							dprintf("Error! Unable to ready something I should: %d weapon: %d;g",
558 								player_index, weapon_type);
559 						}
560 					}
561 					break; /* Out of the for loop */
562 				}
563 			}
564 			// One comes here if a weapon had not been on one of the list
565 			// assert(weapon_type!=NUMBER_OF_WEAPONS);
566 			break;
567 
568 		case _ammunition:
569 			/* Don't try to reload if the player has an invalid weapon */
570 			if(player_has_valid_weapon(player_index))
571 			{
572 				for(unsigned weapon_type= 0; weapon_type<NUMBER_OF_WEAPONS; ++weapon_type)
573 				{
574 					short which_trigger, first_trigger, trigger_count;
575 
576 					trigger_count= get_active_trigger_count_and_states(player_index, weapon_type, 0l, &first_trigger, NULL);
577 					for(which_trigger= first_trigger; which_trigger<trigger_count; ++which_trigger)
578 					{
579 						struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
580 						struct trigger_definition *trigger_definition=
581 							get_trigger_definition(player_index, weapon_type, which_trigger);
582 
583 						if(trigger_definition->ammunition_type==item_type &&
584 							int(weapon_type)==player_weapons->current_weapon &&
585 							player_weapons->current_weapon==player_weapons->desired_weapon)
586 						{
587 							struct weapon_data *weapon= get_player_current_weapon(player_index);
588 
589 							/* reload it. */
590 							if(weapon->triggers[which_trigger].state==_weapon_idle &&
591 								weapon->triggers[which_trigger].rounds_loaded==0)
592 							{
593 								if(!reload_weapon(player_index, which_trigger))
594 								{
595 									dprintf("Error reloading!?");
596 								}
597 							}
598 						}
599 					}
600 				}
601 			}
602 			break;
603 
604 		default:
605 			break;
606 	}
607 }
608 
609 #define IDLE_PHASE_COUNT 1000 // doesn't matter
610 #define CHARGED_WEAPON_OVERLOAD (60*TICKS_PER_SECOND)
611 #define WEAPON_FORWARD_DISPLACEMENT (WORLD_ONE_FOURTH/2)
612 #define WEAPON_SHORTED_SOUND NONE
613 
614 /* Update the given player's weapons */
update_player_weapons(short player_index,uint32 action_flags)615 void update_player_weapons(
616 	short player_index,
617 	uint32 action_flags)
618 {
619 	update_shell_casings(player_index);
620 
621 	if(player_has_valid_weapon(player_index))
622 	{
623 		struct player_data *player= get_player_data(player_index);
624 		struct weapon_data *weapon= get_player_current_weapon(player_index);
625 		struct weapon_definition *definition= get_current_weapon_definition(player_index);
626 		short which_trigger, trigger_count, first_trigger;
627 		bool triggers_down[NUMBER_OF_TRIGGERS];
628 
629 		/* Did they want to raise a second weapon? */
630 		test_raise_double_weapon(player_index, &action_flags);
631 
632 		/* Calculate how many triggers we have to deal with.. */
633 		trigger_count= get_active_trigger_count_and_states(player_index, weapon->weapon_type,
634 			action_flags, &first_trigger, triggers_down);
635 
636 		/* twiddle with their weapon_intensity decay */
637 		if (player->weapon_intensity_decay>0)
638 		{
639 			if(definition->firing_intensity_decay_ticks)
640 			{
641 				player->weapon_intensity= NATURAL_LIGHT_INTENSITY +
642 					// LP change: now adds correctly, rather than replacing
643 					((definition->firing_light_intensity)*
644 					player->weapon_intensity_decay)/definition->firing_intensity_decay_ticks;
645 				player->weapon_intensity_decay--;
646 			} else {
647 				player->weapon_intensity_decay= 0;
648 			}
649 		} else
650 			player->weapon_intensity = NATURAL_LIGHT_INTENSITY;
651 
652 		// wheee!!!
653 		for(which_trigger= first_trigger; which_trigger<trigger_count; ++which_trigger)
654 		{
655 			struct trigger_data *trigger= get_player_trigger_data(player_index, which_trigger);
656 
657 			/* Twiddle the sequence (done after we change our states..) */
658 			/* This has to be in front of the trigger stuff, otherwise you won't see the first */
659 			/* tick of the firing animation frame.  But it also needs to be after the state change */
660 			/*  so that you don't wrap on the reloading sequence.  This is fixed by special casing */
661 			/*  the loading such that it doesn't update on the last tick. */
662 			update_sequence(player_index, which_trigger);
663 
664 			/* Check for trigger down states before entering the state machine. */
665 			if(triggers_down[which_trigger])
666 			{
667 				handle_trigger_down(player_index, which_trigger);
668 			} else {
669 				handle_trigger_up(player_index, which_trigger);
670 			}
671 
672 			/* Increment ticks since last shot, decrement the phase. */
673 			trigger->ticks_since_last_shot++;
674 			trigger->phase--;
675 
676 			/* Update the ticks firing */
677 			if(which_trigger==_primary_weapon &&
678 				(definition->flags & _weapon_is_automatic) &&
679 				(trigger->state==_weapon_firing || trigger->state==_weapon_recovering ||
680 				(trigger->state==_weapon_idle && automatic_still_firing(player_index, _primary_weapon))))
681 			{
682 				trigger->ticks_firing++;
683 			} else {
684 				trigger->ticks_firing= 0;
685 			}
686 
687 			/* If we had a state change.. */
688 			if(trigger->phase<=0)
689 			{
690 				switch(trigger->state)
691 				{
692 					case _weapon_waiting_to_load:
693 						/* This is th point that you actually load the wepaon */
694 						if(definition->finish_loading_ticks)
695 						{
696 							trigger->state= _weapon_finishing_reload;
697 							trigger->phase= definition->finish_loading_ticks;
698 						} else {
699 							/* Don't go to a state with a zero duration */
700 							trigger->state= _weapon_idle;
701 							trigger->sequence= 0;
702 							trigger->phase= IDLE_PHASE_COUNT;
703 						}
704 
705 						/* Bracketed for optimization (stupidity) gains. */
706 						{
707 							struct player_weapon_data *player_weapons=
708 								get_player_weapon_data(player_index);
709 
710 							 put_rounds_into_weapon(player_index, player_weapons->current_weapon,
711 								which_trigger);
712 						}
713 						break;
714 
715 					case _weapon_raising:
716 						trigger->phase= IDLE_PHASE_COUNT; // doesn't matter.
717 						trigger->state= _weapon_idle;
718 						trigger->sequence= 0;
719 						check_reload(player_index, which_trigger);
720 						break;
721 
722 					case _weapon_finishing_reload:
723 					case _weapon_sliding_over_to_second_position:
724 					case _weapon_sliding_over_from_second_position:
725 						trigger->phase= IDLE_PHASE_COUNT; // doesn't matter.
726 						trigger->state= _weapon_idle;
727 						trigger->sequence= 0;
728 						break;
729 
730 					// LP: separate case here, because it is now animated
731 					case _weapon_idle:
732 						trigger->phase= IDLE_PHASE_COUNT; // doesn't matter.
733 						trigger->state= _weapon_idle;
734 						break;
735 
736 					case _weapon_recovering:
737 						trigger->phase= IDLE_PHASE_COUNT; // doesn't matter.
738 						trigger->state= _weapon_idle;
739 						trigger->sequence= 0;
740 
741 						check_reload(player_index, which_trigger);
742 						break;
743 
744 					case _weapon_waiting_for_other_idle_to_reload:
745 						/* This is a twofisted weapon, waiting for its friend to be idle so it can */
746 						/*  load.. */
747 						{
748 							struct trigger_data *other_trigger= get_player_trigger_data(player_index, !which_trigger);
749 
750 							if(other_trigger->state==_weapon_idle)
751 							{
752 								trigger->state= _weapon_awaiting_twofisted_reload;
753 								trigger->phase= definition->ready_ticks;
754 								other_trigger->state= _weapon_lowering_for_twofisted_reload;
755 								other_trigger->phase= definition->ready_ticks;
756 							} else {
757 								/* Try again next time.. */
758 								trigger->phase= 0;
759 							}
760 						}
761 						break;
762 
763 					case _weapon_lowering:
764 						if(definition->item_type==_i_red_ball)
765 						{
766 							short ball_color= find_player_ball_color(player_index);
767 							world_point3d origin, _vector;
768 							short origin_polygon, item_type;
769 
770 							//START Benad
771 							if (ball_color != NONE)
772 							{
773 								item_type= ball_color+BALL_ITEM_BASE;
774 
775 								calculate_weapon_origin_and_vector(player_index, _primary_weapon,
776 									&origin, &_vector, &origin_polygon, 0);
777 
778 								drop_the_ball(&origin, origin_polygon, player->monster_index,
779 									_monster_marine, item_type);
780 								destroy_current_weapon(player_index);
781 							}
782 							// END Benad
783 						}
784 
785 						if(which_trigger==_primary_weapon)
786 						{
787 							struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
788 
789 							if(trigger_count==1 && player_weapons->current_weapon != player_weapons->desired_weapon)
790 							{
791 								change_to_desired_weapon(player_index);
792 							}
793 
794 							/* Reset for the next time.. */
795 							SET_PRIMARY_WEAPON_IS_VALID(weapon, false);
796 							// dprintf("prim down;g");
797 						} else {
798 							struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
799 
800 							if(player_weapons->current_weapon!=player_weapons->desired_weapon)
801 							{
802 								change_to_desired_weapon(player_index);
803 							}
804 
805 							/* Lowering the second weapon for a twofisted weapon */
806 							/* Reset for the next time.. */
807 							SET_SECONDARY_WEAPON_IS_VALID(weapon, false);
808 							// dprintf("second down;g");
809 						}
810 
811 						/* Reset to idle to be consistent */
812 						trigger->phase= IDLE_PHASE_COUNT;
813 						trigger->state= _weapon_idle;
814 						trigger->sequence= 0;
815 						break;
816 
817 					case _weapon_charging:
818 						trigger->phase= CHARGED_WEAPON_OVERLOAD;
819 						trigger->state= _weapon_charged;
820 						break;
821 
822 					case _weapon_charged:
823 						if(definition->flags & _weapon_overloads)
824 						{
825 							/* just in case we don't kill them.. */
826 							trigger->phase= IDLE_PHASE_COUNT; // doesn't matter.
827 							trigger->state= _weapon_idle;
828 							trigger->sequence= 0;
829 
830 							/* oops. */
831 							blow_up_player(player_index);
832 						} else {
833 							/* Reenter the _weapon_charged state. */
834 							trigger->phase= CHARGED_WEAPON_OVERLOAD;
835 							trigger->state= _weapon_charged;
836 						}
837 						break;
838 
839 					case _weapon_firing:
840 						{
841 							struct trigger_definition *trigger_definition=
842 								get_player_trigger_definition(player_index, which_trigger);
843 
844 							if(trigger_definition->recovery_ticks==0)
845 							{
846 								trigger->state= _weapon_idle;
847 								trigger->phase= 0;
848 
849 								if(which_trigger==_primary_weapon && TRIGGER_IS_DOWN(weapon) && (definition->flags & _weapon_is_automatic))
850 								{
851 									/* Don't reset the sequence for the amount of time we consider to be still firing... */
852 									trigger->phase= AUTOMATIC_STILL_FIRING_DURATION;
853 									// dprintf("Ticks firing: %d;g", trigger->ticks_firing);
854 								} else {
855 									trigger->sequence= 0;
856 								}
857 
858 								/* Check reload state & phase take precedence over the AUTOMATIC_STILL_FIRING stuff. */
859 								check_reload(player_index, which_trigger);
860 							} else {
861 								trigger->state= _weapon_recovering;
862 								trigger->phase= trigger_definition->recovery_ticks;
863 								if (definition->flags & _weapon_is_marathon_1)
864 								{
865 									trigger->sequence = 0;
866 								}
867 							}
868 						}
869 						break;
870 
871 					case _weapon_awaiting_reload:
872 						/* enter the state where we wait to actually put the bullets in */
873 						assert(definition->loading_ticks);
874 						trigger->state= _weapon_waiting_to_load;
875 						trigger->phase= definition->loading_ticks;
876 						break;
877 
878 					case _weapon_lowering_for_twofisted_reload:
879 						/* We are off the screen, and waiting for the other guy to finish loading */
880 						trigger->state= _weapon_waiting_for_twofist_to_reload;
881 						trigger->phase= definition->await_reload_ticks+definition->loading_ticks+
882 							definition->finish_loading_ticks;
883 						break;
884 
885 					case _weapon_awaiting_twofisted_reload:
886 						/* The other guy is off the screen, we can load now.. */
887 						if(definition->await_reload_ticks)
888 						{
889 							trigger->state= _weapon_awaiting_reload;
890 							trigger->phase= definition->await_reload_ticks; // should this be by trigger?
891 						} else {
892 							trigger->state= _weapon_waiting_to_load;
893 							trigger->phase= definition->loading_ticks; // should this be by trigger?
894 						}
895 						break;
896 
897 					case _weapon_waiting_for_twofist_to_reload:
898 						/* Raise back up.. */
899 						trigger->state= _weapon_raising;
900 						trigger->phase= definition->ready_ticks;
901 						break;
902 
903 					default:
904 						vhalt(csprintf(temporary, "What the hell is state: %d?", trigger->state));
905 						break;
906 				}
907 			}
908 		}
909 	}
910 
911 	/* If they didn't just finish switching weapons.. */
912 	if(action_flags & _cycle_weapons_forward)
913 	{
914 		select_next_weapon(player_index, true);
915 	}
916 
917 	/* Cycle the weapon backward */
918 	if(action_flags & _cycle_weapons_backward)
919 	{
920 		select_next_weapon(player_index, false);
921 	}
922 
923 	/* And switch the weapon.. */
924 	idle_weapon(player_index);
925 
926 	// dprintf("done;g");
927 }
928 
929 // START Benad
destroy_players_ball(short player_index)930 void destroy_players_ball(
931 	short player_index)
932 {
933 	if (film_profile.destroy_players_ball_fix && !player_has_valid_weapon(player_index))
934 		return;
935 
936 	struct player_data *player= get_player_data(player_index);
937 	short ball_color= find_player_ball_color(player_index);
938 	struct weapon_data *weapon= get_player_current_weapon(player_index);
939 	short item_type;
940 
941 	assert(ball_color!=NONE);
942 	item_type= ball_color+BALL_ITEM_BASE;
943 
944 	/*
945 	world_point3d origin, vector;
946 	short origin_polygon;
947 	calculate_weapon_origin_and_vector(player_index, _primary_weapon,
948 		&origin, &vector, &origin_polygon, 0);
949 
950 	drop_the_ball(&origin, origin_polygon, player->monster_index,
951 		_monster_marine, item_type);
952 	*/
953 
954 	weapon->triggers[0].rounds_loaded = 0;
955 	weapon->triggers[1].rounds_loaded = 0;
956 	weapon->weapon_type = _weapon_ball;
957 	player->items[item_type]= NONE;
958 	object_was_just_destroyed(_object_is_item, item_type);
959 
960 	//destroy_current_weapon(player_index);
961 
962 	mark_player_inventory_as_dirty(player_index, _i_knife);
963 	select_next_best_weapon(player_index);
964 
965 }
966 // END Benad
967 
get_player_desired_weapon(short player_index)968 short get_player_desired_weapon(
969 	short player_index)
970 {
971 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
972 
973 	return player_weapons->desired_weapon;
974 }
975 
get_player_weapon_ammo_count(short player_index,short which_weapon,short which_trigger)976 short get_player_weapon_ammo_count(
977 	short player_index,
978 	short which_weapon,
979 	short which_trigger)
980 {
981 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
982 	struct weapon_definition *definition= get_weapon_definition(which_weapon);
983 	short rounds_loaded;
984 	struct player_data *player= get_player_data(player_index);
985 
986 	assert(which_weapon>=0 && which_weapon<short(NUMBER_OF_WEAPONS));
987 	assert(which_trigger>=0 && which_trigger<NUMBER_OF_TRIGGERS);
988 
989 	switch(definition->weapon_class)
990 	{
991 		case _melee_class:
992 		case _normal_class:
993 		case _dual_function_class:
994 		case _multipurpose_class:
995 			rounds_loaded= player_weapons->weapons[which_weapon].triggers[which_trigger].rounds_loaded;
996 			break;
997 
998 		case _twofisted_pistol_class:
999 			if(player->items[definition->item_type]<=1 && which_trigger==_secondary_weapon)
1000 			{
1001 				rounds_loaded= NONE;
1002 			} else {
1003 				rounds_loaded= player_weapons->weapons[which_weapon].triggers[which_trigger].rounds_loaded;
1004 			}
1005 			break;
1006 
1007 		// LP change: no weapon
1008 		case NONE:
1009 		default:
1010 			rounds_loaded = NONE;
1011 			break;
1012 	}
1013 
1014 	return rounds_loaded;
1015 }
1016 
get_player_weapon_ammo_maximum(short player_index,short which_weapon,short which_trigger)1017 short get_player_weapon_ammo_maximum(
1018 																	 short player_index,
1019 																	 short which_weapon,
1020 																	 short which_trigger)
1021 {
1022 	struct trigger_definition *trigger_definition= get_trigger_definition(player_index,
1023 																						 which_weapon, which_trigger);
1024 
1025 	assert(which_weapon>=0 && which_weapon<short(NUMBER_OF_WEAPONS));
1026 	assert(which_trigger>=0 && which_trigger<NUMBER_OF_TRIGGERS);
1027 
1028 	return trigger_definition->rounds_per_magazine;
1029 }
1030 
get_player_weapon_ammo_type(short player_index,short which_weapon,short which_trigger)1031 int16 get_player_weapon_ammo_type(
1032 																		 short player_index,
1033 																		 short which_weapon,
1034 																		 short which_trigger)
1035 {
1036 	struct trigger_definition *trigger_definition= get_trigger_definition(player_index,
1037 																																				which_weapon, which_trigger);
1038 
1039 	assert(which_weapon>=0 && which_weapon<short(NUMBER_OF_WEAPONS));
1040 	assert(which_trigger>=0 && which_trigger<NUMBER_OF_TRIGGERS);
1041 
1042 	return trigger_definition->ammunition_type;
1043 }
1044 
get_player_weapon_drawn(short player_index,short which_weapon,short which_trigger)1045 bool get_player_weapon_drawn(
1046 							 short player_index,
1047 							 short which_weapon,
1048 							 short which_trigger)
1049 {
1050 	struct player_weapon_data *pd = get_player_weapon_data(player_index);
1051 	if (pd->current_weapon != which_weapon)
1052 		return false;
1053 
1054 	return which_trigger == 0 ? PRIMARY_WEAPON_IS_VALID(&pd->weapons[which_weapon])
1055 							  : SECONDARY_WEAPON_IS_VALID(&pd->weapons[which_weapon]);
1056 }
1057 
1058 #ifdef DEBUG
debug_print_weapon_status(void)1059 void debug_print_weapon_status(
1060 	void)
1061 {
1062 	struct player_weapon_data *player_weapons= get_player_weapon_data(current_player_index);
1063 
1064 	dprintf("Current: %d Desired: %d;g", player_weapons->current_weapon, player_weapons->desired_weapon);
1065 	for(unsigned index= 0; index<NUMBER_OF_WEAPONS; ++index)
1066 	{
1067 		debug_weapon(index);
1068 	}
1069 }
1070 
debug_weapon(short index)1071 static void debug_weapon(
1072 	short index)
1073 {
1074 	struct player_weapon_data *player_weapons= get_player_weapon_data(current_player_index);
1075 
1076 	dprintf("Weapon: %d;g", index);
1077 	dprintf("weapon_type: %d flags: %d unused: %d;g", player_weapons->weapons[index].weapon_type,
1078 		player_weapons->weapons[index].flags, player_weapons->weapons[index].unused);
1079 
1080 	debug_trigger_data(index, _primary_weapon);
1081 
1082 	switch(index)
1083 	{
1084 		case _weapon_missile_launcher:
1085 		case _weapon_flamethrower:
1086 		case _weapon_alien_shotgun:
1087 			break;
1088 
1089 		default:
1090 			debug_trigger_data(index, _secondary_weapon);
1091 			break;
1092 	}
1093 }
1094 
debug_trigger_data(short weapon_type,short which_trigger)1095 static void debug_trigger_data(
1096 	short weapon_type,
1097 	short which_trigger)
1098 {
1099 	struct player_weapon_data *player_weapons= get_player_weapon_data(current_player_index);
1100 	struct trigger_data *trigger;
1101 	struct trigger_definition *trigger_definition;
1102 	struct weapon_definition *weapon_definition= get_weapon_definition(weapon_type);
1103 
1104 	trigger= &player_weapons->weapons[weapon_type].triggers[which_trigger];
1105 
1106 	dprintf("%d) State: %d Phase: %d;g", which_trigger, trigger->state, trigger->phase);
1107 	dprintf("%d) Loaded: %d Shot: %d Hit: %d;g", which_trigger, trigger->rounds_loaded,
1108 		trigger->shots_fired, trigger->shots_hit);
1109 	dprintf("%d) Ticks Since Last: %d;g", which_trigger, trigger->ticks_since_last_shot);
1110 
1111 	trigger_definition= get_trigger_definition(current_player_index,
1112 		weapon_type, which_trigger);
1113 
1114 	if(weapon_definition->item_type != NONE)
1115 	{
1116 		dprintf("%d) Has %d items;g", which_trigger,
1117 			current_player->items[weapon_definition->item_type]);
1118 	} else {
1119 		dprintf("%d) Item type is NONE;g", which_trigger);
1120 	}
1121 
1122 	if(trigger_definition->ammunition_type != NONE)
1123 	{
1124 		dprintf("%d) Player has %d clips;g", which_trigger,
1125 			current_player->items[trigger_definition->ammunition_type]);
1126 	} else {
1127 		dprintf("%d) Ammunition type is NONE;g", which_trigger);
1128 	}
1129 }
1130 #endif
1131 
get_weapon_array(void)1132 void *get_weapon_array(
1133 	void)
1134 {
1135 	return player_weapons_array;
1136 }
1137 
calculate_weapon_array_length(void)1138 int32 calculate_weapon_array_length(
1139 	void)
1140 {
1141 	return dynamic_world->player_count*sizeof(struct player_weapon_data);
1142 }
1143 
1144 /* -------------------------- functions related to rendering */
1145 /* Functions related to rendering! */
1146 /* while this returns true, keep calling.. */
get_weapon_display_information(short * count,struct weapon_display_information * data)1147 bool get_weapon_display_information(
1148 	short *count,
1149 	struct weapon_display_information *data)
1150 {
1151 	bool valid= false;
1152 	short player_index= current_player_index;
1153 
1154 	/* If the player's current weapon is not NONE.. */
1155 	if(player_has_valid_weapon(player_index))
1156 	{
1157 		struct weapon_data *weapon= get_player_current_weapon(player_index);
1158 		struct weapon_definition *definition= get_weapon_definition(weapon->weapon_type);
1159 		_fixed width, height;
1160 		short frame, which_trigger, shape_index, type, flags;
1161 		struct shape_animation_data *high_level_data;
1162 
1163 		/* Get the default width and height */
1164 		width= definition->idle_width;
1165 		height= definition->idle_height;
1166 		modify_position_for_two_weapons(player_index, *count, &width, &height);
1167 
1168 		/* What type of item is this? */
1169 		if(get_weapon_data_type_for_count(player_index, *count, &type, &which_trigger, &flags))
1170 		{
1171 			struct shape_and_transfer_mode owner_transfer_data;
1172 
1173 			/* Assume the best.. */
1174 			valid= true;
1175 
1176 			if(type==_weapon_type || type==_weapon_ammo_type)
1177 			{
1178 				short phase;
1179 
1180 				/* Tell the weapon a frame passed, in case it cares. */
1181 				phase= weapon->triggers[which_trigger].phase;
1182 
1183 				/* Calculate the base location.. */
1184 				if (definition->flags & _weapon_is_marathon_1) {
1185 					// only add in bob height if we're firing
1186 					if (weapon->triggers[which_trigger].state == _weapon_idle && !automatic_still_firing(player_index, which_trigger)) {
1187 						calculate_weapon_position_for_idle(player_index, which_trigger, weapon->weapon_type, &height, &width, false);
1188 					}
1189 				}
1190 				else
1191 				{
1192 					calculate_weapon_position_for_idle(player_index, which_trigger, weapon->weapon_type, &height, &width, true);
1193 				}
1194 
1195 				/* Figure out where to draw it. */
1196 				switch(weapon->triggers[which_trigger].state)
1197 				{
1198 					case _weapon_lowering:
1199 						assert(definition->ready_ticks);
1200 						height = (3*FIXED_ONE/2)-(((3*FIXED_ONE/2)-definition->idle_height)*phase)/definition->ready_ticks;
1201 						shape_index= definition->idle_shape;
1202 						break;
1203 
1204 					case _weapon_raising:
1205 						assert(definition->ready_ticks);
1206 						height += (((3*FIXED_ONE/2)-definition->idle_height)*phase)/definition->ready_ticks;
1207 						shape_index= definition->idle_shape;
1208 						break;
1209 
1210 					case _weapon_charged:
1211 						if(definition->flags & _weapon_overloads)
1212 						{
1213 							_fixed flutter_base;
1214 
1215 							/* 0-> FIXED ONE as it gets closer to nova.. */
1216 							flutter_base= (FIXED_ONE*(CHARGED_WEAPON_OVERLOAD-phase))/CHARGED_WEAPON_OVERLOAD;
1217 							add_random_flutter(flutter_base, &height, &width);
1218 						} else {
1219 							/* Calculate for idle, and then make it bounce */
1220 							add_random_flutter(FIXED_ONE, &height, &width);
1221 						}
1222 
1223 						/* This is a fully charged weapon.. */
1224 						if(definition->charged_shape != NONE)
1225 						{
1226 							shape_index= definition->charged_shape;
1227 						} else {
1228 							shape_index= definition->idle_shape;
1229 						}
1230 						break;
1231 
1232 					case _weapon_charging:
1233 						/* This is a fully charged weapon.. */
1234 						if(definition->charging_shape != NONE)
1235 						{
1236 							shape_index= definition->charging_shape;
1237 						} else {
1238 							shape_index= definition->idle_shape;
1239 						}
1240 						break;
1241 
1242 					case _weapon_waiting_for_twofist_to_reload:
1243 						/* Get it off the screen.. */
1244 						height= 4*FIXED_ONE;
1245 						shape_index= definition->idle_shape;
1246 						break;
1247 
1248 					case _weapon_awaiting_twofisted_reload:
1249 					case _weapon_waiting_for_other_idle_to_reload:
1250 						shape_index= definition->idle_shape;
1251 						break;
1252 
1253 					case _weapon_idle:
1254 						if(definition->flags & _weapon_is_automatic)
1255 						{
1256 							if(which_trigger==_primary_weapon ||
1257 								(which_trigger==_secondary_weapon && (definition->flags & _weapon_secondary_has_angular_flipping)))
1258 							{
1259 								if(automatic_still_firing(current_player_index, which_trigger))
1260 								{
1261 									shape_index= definition->firing_shape;
1262 									if (definition->flags & _weapon_flutters_while_firing)
1263 									{
1264 										add_random_flutter(FIXED_ONE, &height, &width);
1265 									}
1266 								} else {
1267 									shape_index= definition->idle_shape;
1268 									// Now handled in UpdateIdleWeapons()
1269 									// weapon->triggers[which_trigger].sequence= 0;
1270 								}
1271 							} else {
1272 								shape_index= definition->idle_shape;
1273 							}
1274 						} else {
1275 							shape_index= definition->idle_shape;
1276 						}
1277 						break;
1278 
1279 					case _weapon_sliding_over_to_second_position:
1280 						if(definition->weapon_class==_twofisted_pistol_class)
1281 						{
1282 							if(which_trigger==_primary_weapon)
1283 							{
1284 								width-= ((weapon->triggers[which_trigger].phase)
1285 									*(PISTOL_SEPARATION_WIDTH/2))/definition->ready_ticks;
1286 							} else {
1287 								width+= ((weapon->triggers[which_trigger].phase)
1288 									*(PISTOL_SEPARATION_WIDTH/2))/definition->ready_ticks;
1289 							}
1290 						} else {
1291 							/* Melee weapons stay where they were. */
1292 						}
1293 						shape_index= definition->idle_shape;
1294 						break;
1295 
1296 					case _weapon_sliding_over_from_second_position:
1297 						if(definition->weapon_class==_twofisted_pistol_class)
1298 						{
1299 							short sign;
1300 
1301 							if(which_trigger==_primary_weapon)
1302 							{
1303 								sign= -1;
1304 							} else {
1305 								sign= 1;
1306 							}
1307 							width+= sign*((definition->ready_ticks-weapon->triggers[which_trigger].phase)*(PISTOL_SEPARATION_WIDTH/2))/
1308 								definition->ready_ticks;
1309 						} else {
1310 							/* Melee weapons stay where they were. */
1311 						}
1312 						shape_index= definition->idle_shape;
1313 						break;
1314 
1315 					case _weapon_firing:
1316 						/* We are going up.. */
1317 						{
1318 							struct trigger_definition *trigger_definition;
1319 
1320 							trigger_definition= get_player_trigger_definition(player_index, which_trigger);
1321 							height -= (definition->kick_height*(trigger_definition->ticks_per_round-phase))/trigger_definition->ticks_per_round;
1322 							shape_index= definition->firing_shape;
1323 							if (definition->flags & _weapon_flutters_while_firing)
1324 							{
1325 								add_random_flutter(FIXED_ONE, &height, &width);
1326 							}
1327 						}
1328 						break;
1329 
1330 					case _weapon_recovering:
1331 						/* Going back down.. */
1332 						{
1333 							struct trigger_definition *trigger_definition= get_player_trigger_definition(player_index, which_trigger);
1334 							assert(trigger_definition->recovery_ticks);
1335 							height-= (definition->kick_height*phase)/trigger_definition->recovery_ticks;
1336 							if (definition->flags & _weapon_is_marathon_1)
1337 							{
1338 								shape_index = definition->idle_shape;
1339 							}
1340 							else
1341 							{
1342 								shape_index= definition->firing_shape;
1343 							}
1344 						}
1345 						break;
1346 
1347 					case _weapon_awaiting_reload:
1348 						if(definition->reloading_shape==NONE)
1349 						{
1350 							assert(definition->await_reload_ticks);
1351 							height+= (((3*FIXED_ONE/2)-definition->idle_height)*(definition->await_reload_ticks-phase))/definition->await_reload_ticks;
1352 							shape_index= definition->idle_shape;
1353 						} else {
1354 							height= definition->reload_height;
1355 							shape_index= definition->reloading_shape;
1356 						}
1357 						break;
1358 
1359 					case _weapon_waiting_to_load:
1360 						if(definition->reloading_shape==NONE)
1361 						{
1362 							/* Consider it offscreen */
1363 							valid= false;
1364 							shape_index= definition->idle_shape;
1365 						} else {
1366 							height= definition->reload_height;
1367 							shape_index= definition->reloading_shape;
1368 						}
1369 						break;
1370 
1371 					case _weapon_finishing_reload:
1372 						if(definition->reloading_shape==NONE)
1373 						{
1374 							assert(definition->finish_loading_ticks);
1375 							height+= (((3*FIXED_ONE/2)-definition->idle_height)*phase)/definition->finish_loading_ticks;
1376 
1377 							shape_index= definition->idle_shape;
1378 						} else {
1379 							height= definition->reload_height;
1380 							shape_index= definition->reloading_shape;
1381 						}
1382 						break;
1383 
1384 					case _weapon_lowering_for_twofisted_reload:
1385 						assert(definition->ready_ticks);
1386 						height = (3*FIXED_ONE/2)-(((3*FIXED_ONE/2)-definition->idle_height)*phase)/definition->ready_ticks;
1387 						shape_index= definition->idle_shape;
1388 						break;
1389 
1390 					default:
1391 						assert(false);
1392 						break;
1393 				}
1394 
1395 				/* Determine our frame. */
1396 				if (type==_weapon_ammo_type)
1397 				{
1398 					// hardcoded for Marathon 1 rocket launcher
1399 					shape_index = M1_MISSILE_AMMO_SEQUENCE;
1400 					frame = weapon->triggers[which_trigger].rounds_loaded - 1;
1401 				}
1402 				else
1403 					frame= GET_SEQUENCE_FRAME(weapon->triggers[which_trigger].sequence);
1404 
1405 				if (type==_weapon_type)
1406 				{
1407 					/* Go to the next frame for automatics.. */
1408 					update_automatic_sequence(current_player_index, which_trigger);
1409 
1410 					// Also for idle weapons
1411 					UpdateIdleAnimation(current_player_index, which_trigger);
1412 				}
1413 
1414 				/* setup the positioning information */
1415 				high_level_data= get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection,
1416 					shape_index));
1417 
1418 				// LP: bug out if there is no weapon sequence to render
1419 				if (!high_level_data) return false;
1420 				if (!(frame>=0 && frame<high_level_data->frames_per_view))
1421 					return false;
1422 
1423 				data->collection= BUILD_COLLECTION(definition->collection, 0);
1424 				data->shape_index = shape_index;
1425 				data->low_level_shape_index= high_level_data->low_level_shape_indexes[frame];
1426 				data->vertical_positioning_mode= _position_center;
1427 				data->horizontal_positioning_mode= _position_center;
1428 				data->vertical_position= height;
1429 				data->horizontal_position= width;
1430 				if(flags & _flip_shape_vertical)
1431 				{
1432 					data->flip_vertical= true;
1433 				} else {
1434 					data->flip_vertical= false;
1435 				}
1436 
1437 				if(flags & _flip_shape_horizontal)
1438 				{
1439 					data->flip_horizontal= true;
1440 				} else {
1441 					data->flip_horizontal= false;
1442 				}
1443 
1444 				if (type==_weapon_ammo_type)
1445 				{
1446 					// hardcoded for Marathon 1 rocket launcher
1447 					data->vertical_position += M1_MISSILE_AMMO_YOFFSET;
1448 					data->horizontal_position += M1_MISSILE_AMMO_XOFFSET;
1449 				}
1450 
1451 				/* Fill in the transfer mode and phase */
1452 				/* Cached, so that we only do it the first time through.. */
1453 				if(!(*count))
1454 				{
1455 					struct player_data *player= get_player_data(player_index);
1456 
1457 					get_object_shape_and_transfer_mode(&player->camera_location, player->object_index,
1458 						&owner_transfer_data);
1459 					// Bug out in case of nonexistent shape
1460 					if (owner_transfer_data.collection_code == NONE) return false;
1461 
1462 					data->transfer_mode= owner_transfer_data.transfer_mode;
1463 					data->transfer_phase= owner_transfer_data.transfer_phase;
1464 
1465 					// LP: model animation data
1466 					data->Frame = owner_transfer_data.Frame;
1467 					data->NextFrame = owner_transfer_data.NextFrame;
1468 					data->Phase = owner_transfer_data.Phase;
1469 					data->Ticks = owner_transfer_data.Ticks;
1470 				}
1471 			}
1472 			else if(type==_shell_casing_type)
1473 			{
1474 				get_shell_casing_display_data(data, which_trigger);
1475 			} else {
1476 				assert(false);
1477 			}
1478 		}
1479 
1480 		(*count)++;
1481 	}
1482 
1483 	return valid;
1484 }
1485 
get_player_weapon_mode_and_type(short player_index,short * shape_weapon_type,short * shape_mode)1486 void get_player_weapon_mode_and_type(
1487 	short player_index,
1488 	short *shape_weapon_type,
1489 	short *shape_mode)
1490 {
1491 
1492 	if(player_has_valid_weapon(player_index))
1493 	{
1494 		struct weapon_definition *definition= get_current_weapon_definition(player_index);
1495 		struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
1496 		struct weapon_data *weapon_data= get_player_current_weapon(player_index);
1497 		short which_trigger, mode;
1498 		short first_trigger, trigger_count;
1499 
1500 		*shape_weapon_type= player_weapons->current_weapon;
1501 
1502 		/* If we are a twofisted pistol, and both are up */
1503 		if(definition->weapon_class==_twofisted_pistol_class && PRIMARY_WEAPON_IS_VALID(weapon_data) && SECONDARY_WEAPON_IS_VALID(weapon_data))
1504 		{
1505 			switch(player_weapons->current_weapon)
1506 			{
1507 				case _weapon_shotgun:
1508 					*shape_weapon_type= _weapon_doublefisted_shotguns;
1509 					break;
1510 
1511 				case _weapon_pistol:
1512 				default:
1513 					*shape_weapon_type= _weapon_doublefisted_pistols;
1514 					break;
1515 			}
1516 		}
1517 
1518 		mode= NONE;
1519 
1520 		trigger_count= get_active_trigger_count_and_states(player_index, player_weapons->current_weapon, 0l, &first_trigger, NULL);
1521 		for(which_trigger= first_trigger; which_trigger<trigger_count; ++which_trigger)
1522 		{
1523 			struct trigger_data *trigger= get_player_trigger_data(player_index, which_trigger);
1524 
1525 			switch (trigger->state)
1526 			{
1527 				case _weapon_idle:
1528 					if(automatic_still_firing(player_index, which_trigger))
1529 					{
1530 						mode= MAX(mode, _shape_weapon_firing);
1531 					} else {
1532 						mode= MAX(mode, _shape_weapon_idle);
1533 					}
1534 					break;
1535 
1536 				case _weapon_raising:
1537 				case _weapon_lowering:
1538 				case _weapon_awaiting_reload:
1539 				case _weapon_waiting_to_load:
1540 				case _weapon_finishing_reload:
1541 				case _weapon_sliding_over_to_second_position:
1542 				case _weapon_sliding_over_from_second_position:
1543 				case _weapon_lowering_for_twofisted_reload:
1544 				case _weapon_awaiting_twofisted_reload:
1545 				case _weapon_waiting_for_twofist_to_reload:
1546 				case _weapon_waiting_for_other_idle_to_reload:
1547 					mode= MAX(mode, _shape_weapon_idle);
1548 					break;
1549 
1550 				case _weapon_charging:
1551 				case _weapon_charged:
1552 					mode= MAX(_shape_weapon_charging, mode);
1553 					break;
1554 
1555 				case _weapon_firing:
1556 				case _weapon_recovering:
1557 					mode= MAX(_shape_weapon_firing, mode);
1558 					break;
1559 
1560 				default:
1561 					assert(false);
1562 					break;
1563 			}
1564 		}
1565 
1566 		// LP change: suppressed error checking
1567 		if (mode == NONE) mode = _shape_weapon_idle;
1568 		*shape_mode= mode;
1569 	} else {
1570 		/* No weapon.. */
1571 		*shape_mode= _shape_weapon_idle;
1572 		*shape_weapon_type= _weapon_fist;
1573 	}
1574 }
1575 
1576 /* -------- general static code */
reset_trigger_data(short player_index,short weapon_type,short which_trigger)1577 static void reset_trigger_data(
1578 	short player_index,
1579 	short weapon_type,
1580 	short which_trigger)
1581 {
1582 	struct trigger_data *trigger= get_trigger_data(player_index, weapon_type, which_trigger);
1583 
1584 	trigger->state= _weapon_idle;
1585 	trigger->phase= 0;
1586 	trigger->rounds_loaded= 0;
1587 /* Note that trigger->shots_fired, and trigger->shots_hit are not reset (for total carnage graphs) */
1588 	trigger->ticks_since_last_shot= 0;
1589 	trigger->ticks_firing= 0;
1590 	trigger->sequence= 0;
1591 }
1592 
weapon_works_in_current_environment(short weapon_index)1593 static bool weapon_works_in_current_environment(
1594 	short weapon_index)
1595 {
1596 	bool weapon_works= true;
1597 
1598 	if(weapon_index!=NONE)
1599 	{
1600 		struct weapon_definition *definition= get_weapon_definition(weapon_index);
1601 		weapon_works= item_valid_in_current_environment(definition->item_type);
1602 	}
1603 
1604 	return weapon_works;
1605 }
1606 
1607 /* This selects the next best weapon */
select_next_best_weapon(short player_index)1608 /*static*/ void select_next_best_weapon(
1609 	short player_index)
1610 {
1611 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
1612 	int index, current_weapon_index;
1613 
1614 	/* Find where we are in the array. */
1615 	current_weapon_index= find_weapon_power_index(player_weapons->current_weapon);
1616 
1617 	/* Find the next weapon that the player has. */
1618 	for(index=current_weapon_index+1; index<NUMBER_OF_WEAPONS; ++index)
1619 	{
1620 		if(ready_weapon(player_index, weapon_ordering_array[index])) break;
1621 	}
1622 
1623 	if(index==NUMBER_OF_WEAPONS)
1624 	{
1625 		/* Try going down.. */
1626 		for(index= current_weapon_index-1; index>=0; index--)
1627 		{
1628 			if(ready_weapon(player_index, weapon_ordering_array[index])) break;
1629 		}
1630 	}
1631 
1632 	/* if we didn't change, we punt */
1633 }
1634 
select_next_weapon(short player_index,bool forward)1635 static void select_next_weapon(
1636 	short player_index,
1637 	bool forward)
1638 {
1639 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
1640 
1641 	if(player_weapons->desired_weapon!=_weapon_ball && player_weapons->current_weapon!=_weapon_ball)
1642 	{
1643 		short desired_weapon_index;
1644 
1645 		desired_weapon_index= find_weapon_power_index(player_weapons->desired_weapon);
1646 
1647 		/* This starts at one because we are trying to go forward or backward.. */
1648 		for(unsigned index=1; index<NUMBER_OF_WEAPONS; ++index)
1649 		{
1650 			short test_weapon_index;
1651 
1652 			if(forward)
1653 			{
1654 				test_weapon_index= (index+desired_weapon_index)%NUMBER_OF_WEAPONS;
1655 			} else {
1656 				test_weapon_index= (desired_weapon_index-index+NUMBER_OF_WEAPONS)%NUMBER_OF_WEAPONS;
1657 			}
1658 
1659 			if(ready_weapon(player_index, weapon_ordering_array[test_weapon_index])) break;
1660 		}
1661 	}
1662 }
1663 
get_player_trigger_definition(short player_index,short which_trigger)1664 static struct trigger_definition *get_player_trigger_definition(
1665 	short player_index,
1666 	short which_trigger)
1667 {
1668 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
1669 	return get_trigger_definition(player_index, player_weapons->current_weapon, which_trigger);
1670 }
1671 
get_trigger_definition(short player_index,short which_weapon,short which_trigger)1672 static struct trigger_definition *get_trigger_definition(
1673 	short player_index,
1674 	short which_weapon,
1675 	short which_trigger)
1676 {
1677 	struct weapon_definition *definition= get_weapon_definition(which_weapon);
1678 	struct trigger_definition *trigger_definition;
1679 
1680 	assert(which_trigger>=0 && which_trigger<NUMBER_OF_TRIGGERS);
1681 	assert(which_weapon>=0 && which_weapon<short(NUMBER_OF_WEAPONS));
1682 
1683 	trigger_definition= &definition->weapons_by_trigger[which_trigger];
1684 
1685 	return trigger_definition;
1686 }
1687 
get_player_trigger_data(short player_index,short which_trigger)1688 static struct trigger_data *get_player_trigger_data(
1689 	short player_index,
1690 	short which_trigger)
1691 {
1692 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
1693 
1694 	assert(player_weapons->current_weapon>=0 && player_weapons->current_weapon<short(NUMBER_OF_WEAPONS));
1695 
1696 	return get_trigger_data(player_index, player_weapons->current_weapon, which_trigger);
1697 }
1698 
get_trigger_data(short player_index,short weapon_index,short which_trigger)1699 struct trigger_data *get_trigger_data(
1700 	short player_index,
1701 	short weapon_index,
1702 	short which_trigger)
1703 {
1704 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
1705 
1706 	assert(which_trigger>=0 && which_trigger<NUMBER_OF_TRIGGERS);
1707 	assert(weapon_index>=0 && weapon_index<short(NUMBER_OF_WEAPONS));
1708 
1709 	return &player_weapons->weapons[weapon_index].triggers[which_trigger];
1710 }
1711 
get_player_current_weapon(short player_index)1712 static struct weapon_data *get_player_current_weapon(
1713 	short player_index)
1714 {
1715 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
1716 
1717 	assert(player_weapons->current_weapon>=0 && player_weapons->current_weapon<short(NUMBER_OF_WEAPONS));
1718 
1719 	return &player_weapons->weapons[player_weapons->current_weapon];
1720 }
1721 
1722 /*
1723 	This function does the following:
1724 		1) Calculates how many shots to fire.
1725 		2) creates all of the projectiles,
1726 		3) handles recoil
1727 		4) plays sounds
1728 		5) updates shots fired/rounds loaded
1729 */
fire_weapon(short player_index,short which_trigger,_fixed charged_amount,bool flail_wildly)1730 static void fire_weapon(
1731 	short player_index,
1732 	short which_trigger,
1733 	_fixed charged_amount,
1734 	bool flail_wildly)
1735 {
1736 	struct player_data *player= get_player_data(player_index);
1737 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
1738 	struct weapon_definition *definition= get_weapon_definition(player_weapons->current_weapon);
1739 	struct trigger_definition *trigger_definition;
1740 	struct trigger_data	*trigger;
1741 	world_point3d origin, _vector;
1742 	short origin_polygon, flailing_bonus, rounds_to_fire;
1743 	_fixed damage_modifier;
1744 
1745 	/* if they are under water, and it isn't a melee weapon, they lose */
1746 	if ((player->variables.flags&_HEAD_BELOW_MEDIA_BIT) && !(definition->flags&_weapon_fires_under_media))
1747 	{
1748 		play_weapon_sound(player_index, WEAPON_SHORTED_SOUND, FIXED_ONE);
1749 		return;
1750 	}
1751 
1752 	/* Delta theta.. */
1753 	flailing_bonus= flail_wildly ? 30 : 0;
1754 
1755 	/* Get the weapon they are using... */
1756 	trigger_definition= get_player_trigger_definition(player_index, which_trigger);
1757 	trigger= get_player_trigger_data(player_index, which_trigger);
1758 
1759 	/* Calculate the number of rounds to fire.. */
1760 	if(trigger_definition->burst_count)
1761 	{
1762 		if(trigger_definition->charging_ticks)
1763 		{
1764 			rounds_to_fire= (short)((trigger_definition->burst_count*charged_amount)/FIXED_ONE);
1765 		} else {
1766 			/* Non charging weapon.. */
1767 			rounds_to_fire= trigger_definition->burst_count;
1768 		}
1769 	} else {
1770 		rounds_to_fire= 1;
1771 	}
1772 
1773 	/* I hear you.. */
1774 	if(definition->weapon_class != _melee_class)
1775 	{
1776 		int32 range = -1;
1777 		if (static_world->environment_flags & _environment_activation_ranges)
1778 			range = trigger_definition->sound_activation_range * WORLD_ONE;
1779 
1780 		if(which_trigger==_primary_weapon && (definition->flags & _weapon_is_automatic) && trigger->ticks_firing<2)
1781 		{
1782 			activate_nearby_monsters(player->monster_index, player->monster_index,
1783 				_pass_one_zone_border|_activate_invisible_monsters, range);
1784 		} else {
1785 			activate_nearby_monsters(player->monster_index, player->monster_index,
1786 				_pass_one_zone_border|_activate_invisible_monsters, range);
1787 		}
1788 	}
1789 
1790 	/* If we have any rounds of ammunition */
1791 	if(trigger->rounds_loaded>0)
1792 	{
1793 		angle delta_theta= 0;
1794 
1795 		/* Handle the second trigger of the alien weapon.. */
1796 		if(which_trigger==_secondary_weapon && (definition->flags & _weapon_secondary_has_angular_flipping))
1797 		{
1798 			struct weapon_data *weapon= get_player_current_weapon(player_index);
1799 
1800 			delta_theta= ANGULAR_VARIANCE*GET_WEAPON_VARIANCE_SIGN(weapon);
1801 			FLIP_WEAPON_VARIANCE_SIGN(weapon);
1802 		}
1803 
1804 		/* Note that we no longer pin the rounds to fire by the amount in the gun.. */
1805 		if(rounds_to_fire>trigger->rounds_loaded)
1806 		{
1807 			rounds_to_fire= trigger->rounds_loaded;
1808 		}
1809 
1810 		/* Spawn the projectile. I can't update the shots_hit until it actually hits the */
1811 		/* target, which comes in update */
1812 		calculate_weapon_origin_and_vector(player_index, which_trigger,
1813 			&origin, &_vector, &origin_polygon, delta_theta);
1814 
1815 		/* If it is a melee weapon, add in the damage based on their speed.. */
1816 		if(definition->weapon_class==_melee_class)
1817 		{
1818 			/* Damage is in range of [FIXED_ONE/8, FIXED_ONE] */
1819 			/* Therefore melee damage should be pretty high. */
1820 			damage_modifier= get_player_forward_velocity_scale(player_index);
1821 			damage_modifier= MAX(damage_modifier, FIXED_ONE/8);
1822 		} else {
1823 			damage_modifier= FIXED_ONE;
1824 		}
1825 
1826 		while(rounds_to_fire--)
1827 		{
1828 			/* Increment rounds fired count */
1829 			player_weapons->weapons[player_weapons->current_weapon].triggers[which_trigger].shots_fired++;
1830 			player_weapons->weapons[player_weapons->current_weapon].triggers[which_trigger].rounds_loaded--;
1831 
1832 			/* Update the player ammunition count */
1833 			update_player_ammo_count(player_index);
1834 
1835 			/* on certain weapons, keep the weapon ammo pools synced.... */
1836 			if(definition->flags & _weapon_triggers_share_ammo)
1837 			{
1838 				player_weapons->weapons[player_weapons->current_weapon].triggers[!which_trigger].rounds_loaded--;
1839 			}
1840 
1841 			/* on dual function classes, keep the two ammo pools synched.. */
1842 			if(definition->weapon_class==_dual_function_class)
1843 			{
1844 				/* Dual function class, charging weapons use 4x the ammo. */
1845 				if(which_trigger==_secondary_weapon && trigger_definition->charging_ticks)
1846 				{
1847 					short rounds_count;
1848 
1849 					rounds_count= MIN(COST_PER_CHARGED_WEAPON_SHOT-1, player_weapons->weapons[player_weapons->current_weapon].triggers[which_trigger].rounds_loaded);
1850 
1851 					/* Decrement the ammo.. */
1852 					player_weapons->weapons[player_weapons->current_weapon].triggers[which_trigger].rounds_loaded-= rounds_count;
1853 
1854 					/* Decrement the other ammo as well.. */
1855 					if(definition->flags & _weapon_triggers_share_ammo)
1856 					{
1857 						player_weapons->weapons[player_weapons->current_weapon].triggers[!which_trigger].rounds_loaded-= rounds_count;
1858 					}
1859 				}
1860 			}
1861 
1862 			/* Fire the projectile */
1863 			// Added modification of guided-projectile patch from AlexJLS@aol.com;
1864 			// avoid doing search for targets for an unguided projectile.
1865 			if(trigger_definition->projectile_type!=_projectile_ball_dropped)
1866 			{
1867 				short Target = player_settings.PlayerShotsGuided ?
1868 					(ProjectileIsGuided(trigger_definition->projectile_type) ?
1869 						find_closest_appropriate_target(player->monster_index,false) :
1870 						NONE) : NONE;
1871 				new_projectile(&origin, origin_polygon, &_vector,
1872 					trigger_definition->theta_error+flailing_bonus,
1873 					trigger_definition->projectile_type,
1874 					player->monster_index, _monster_marine, Target, damage_modifier);
1875 					// player->monster_index, _monster_marine, NONE, damage_modifier);
1876 			}
1877 		}
1878 
1879 		/* Spawn a shell casing.... */
1880 		if (trigger_definition->shell_casing_type!=NONE)
1881 		{
1882 			short type= trigger_definition->shell_casing_type;
1883 			uint16 flags= 0;
1884 
1885 			if (type==_shell_casing_pistol)
1886 			{
1887 				struct weapon_data *weapon= get_player_current_weapon(player_index);
1888 
1889 				if (SECONDARY_WEAPON_IS_VALID(weapon))
1890 				{
1891 					if (PRIMARY_WEAPON_IS_VALID(weapon))
1892 					{
1893 						type= which_trigger ? _shell_casing_pistol_left : _shell_casing_pistol_right;
1894 					}
1895 					else
1896 					{
1897 						flags|= _shell_casing_is_reversed;
1898 					}
1899 				}
1900 			}
1901 
1902 			new_shell_casing(player_index, type, flags);
1903 		}
1904 
1905 		/* setup the weapon phase.. */
1906 		trigger->state= _weapon_firing;
1907 		trigger->phase= trigger_definition->ticks_per_round;
1908 		trigger->ticks_since_last_shot= 0;
1909 
1910 		/* Setup the decay.. */
1911 		player->weapon_intensity_decay= definition->firing_intensity_decay_ticks;
1912 
1913 		/* Blam */
1914 		play_weapon_sound(player_index, trigger_definition->firing_sound, FIXED_ONE);
1915 
1916 		/* Push them back.. */
1917 		if(trigger_definition->recoil_magnitude)
1918 		{
1919 			accelerate_monster(player->monster_index,
1920 				-(trigger_definition->recoil_magnitude*sine_table[player->elevation])>>TRIG_SHIFT,
1921 				NORMALIZE_ANGLE(player->facing+HALF_CIRCLE),
1922 				(trigger_definition->recoil_magnitude*cosine_table[player->elevation])>>TRIG_SHIFT);
1923 		}
1924 	} else {
1925 		/* uh oh, no bullets. */
1926 		while(rounds_to_fire--)
1927 		{
1928 			play_weapon_sound(player_index, trigger_definition->click_sound, FIXED_ONE);
1929 		}
1930 	}
1931 }
1932 
get_current_weapon_definition(short player_index)1933 struct weapon_definition *get_current_weapon_definition(
1934 	short player_index)
1935 {
1936 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
1937 
1938 	assert(player_weapons->current_weapon>=0 && player_weapons->current_weapon<short(NUMBER_OF_WEAPONS));
1939 
1940 	return get_weapon_definition(player_weapons->current_weapon);
1941 }
1942 
calculate_weapon_origin_and_vector(short player_index,short which_trigger,world_point3d * origin,world_point3d * _vector,short * origin_polygon,angle delta_theta)1943 static void calculate_weapon_origin_and_vector(
1944 	short player_index,
1945 	short which_trigger,
1946 	world_point3d *origin,
1947 	world_point3d *_vector,
1948 	short *origin_polygon,
1949 	angle delta_theta)
1950 {
1951 	struct player_data *player= get_player_data(player_index);
1952 	struct object_data *object= get_object_data(player->object_index);
1953 	struct trigger_definition *trigger_definition;
1954 	struct weapon_definition *definition= get_current_weapon_definition(player_index);
1955 	struct weapon_data *weapon_data= get_player_current_weapon(player_index);
1956 	short dx_translation_amount;
1957 	world_point3d destination;
1958 	angle projectile_facing;
1959 
1960 	trigger_definition= get_player_trigger_definition(player_index, which_trigger);
1961 
1962 	*origin= player->camera_location;
1963 	origin->z += trigger_definition->dz;
1964 
1965 	/* Translate the projectile out to the end of the gun barrel.. */
1966 	translate_point3d(origin, WEAPON_FORWARD_DISPLACEMENT,
1967 		player->facing, player->elevation);
1968 
1969 	/* Do left/right translation */
1970 	/* if it is twofisted, and both weapons aren't up, don't translate.. */
1971 	/* JM: Bungie originally had precedence wrong, but it didn't matter in practice */
1972 	if(definition->weapon_class==_twofisted_pistol_class &&
1973 	   ((PRIMARY_WEAPON_IS_VALID(weapon_data) && !SECONDARY_WEAPON_IS_VALID(weapon_data)) ||
1974 	    (!PRIMARY_WEAPON_IS_VALID(weapon_data) && SECONDARY_WEAPON_IS_VALID(weapon_data))))
1975 	{
1976 		dx_translation_amount= 0;
1977 	} else {
1978 		dx_translation_amount= trigger_definition->dx;
1979 	}
1980 
1981 	/* Handle the left/right translation */
1982 	translate_point2d((world_point2d *) origin, dx_translation_amount,
1983 		NORMALIZE_ANGLE(player->facing+QUARTER_CIRCLE));
1984 
1985 	/* Get a second point to build up a vector.. */
1986 	destination= *origin;
1987 	projectile_facing= NORMALIZE_ANGLE(player->facing+delta_theta);
1988 	translate_point3d(&destination, WORLD_ONE_HALF,
1989 		projectile_facing, player->elevation);
1990 
1991 	/* And create the vector.. */
1992 	_vector->x= destination.x-origin->x;
1993 	_vector->y= destination.y-origin->y;
1994 	_vector->z= destination.z-origin->z;
1995 
1996 	/* Now calculate the origin polygon index */
1997 	*origin_polygon= find_new_object_polygon((world_point2d *) &player->location,
1998 		(world_point2d *)origin, object->polygon);
1999 
2000 	/* They blew the pooch- this is expensive, therefore let's hope it doesn't happen often */
2001 	if(*origin_polygon==NONE)
2002 	{
2003 		short source_polygon= object->polygon;
2004 		short line_crossed = NONE;
2005 		struct line_data *line;
2006 		world_distance distance;
2007 
2008 		while(source_polygon != NONE)
2009 		{
2010 			line_crossed= find_line_crossed_leaving_polygon(source_polygon, (world_point2d *)
2011 				&player->location, (world_point2d *) origin);
2012 			source_polygon= find_adjacent_polygon(source_polygon, line_crossed);
2013 		}
2014 
2015 		line= get_line_data(line_crossed);
2016 		find_line_intersection(&get_endpoint_data(line->endpoint_indexes[0])->vertex,
2017 			&get_endpoint_data(line->endpoint_indexes[1])->vertex,
2018 			&player->location, origin, origin);
2019 
2020 		/* Now guess the distance.. */
2021 		distance= distance2d((world_point2d *)&player->location, (world_point2d *) origin);
2022 		distance-= 50; /* Fudge factor */
2023 
2024 		*origin= player->location;
2025 		translate_point2d((world_point2d *) origin, distance,
2026 			NORMALIZE_ANGLE(player->facing+QUARTER_CIRCLE));
2027 
2028 		*origin_polygon= find_new_object_polygon((world_point2d *) &player->location,
2029 			(world_point2d *)origin, object->polygon);
2030 		assert(*origin_polygon != NONE);
2031 	}
2032 }
2033 
reload_weapon(short player_index,short which_trigger)2034 static bool reload_weapon(
2035 	short player_index,
2036 	short which_trigger)
2037 {
2038 	struct trigger_data *trigger= get_player_trigger_data(player_index, which_trigger);
2039 	struct trigger_definition *trigger_definition=
2040 		get_player_trigger_definition(player_index, which_trigger);
2041 	struct player_data *player= get_player_data(player_index);
2042 	struct weapon_definition *definition= get_current_weapon_definition(player_index);
2043 	bool can_reload;
2044 
2045 	// LP change: bugging out if these cannot be done
2046 	if (!(trigger->state==_weapon_idle && trigger->rounds_loaded==0)) return false;
2047 	if (!(trigger_definition->ammunition_type==NONE || (trigger_definition->ammunition_type>=0 && trigger_definition->ammunition_type<NUMBER_OF_ITEMS))) return false;
2048 
2049 	if(trigger_definition->ammunition_type != NONE && player->items[trigger_definition->ammunition_type]>0)
2050 	{
2051 		struct weapon_data *weapon= get_player_current_weapon(player_index);
2052 
2053 		/* If this is a twofisted weapon & it doesn't reload in one hand... */
2054 		/* If it is a twofisted weapon, doesn't reload in one hand, and both weapons are valid */
2055 		if(definition->weapon_class==_twofisted_pistol_class &&
2056 			!(definition->flags & _weapon_reloads_in_one_hand)
2057 			&& PRIMARY_WEAPON_IS_VALID(weapon) && SECONDARY_WEAPON_IS_VALID(weapon))
2058 		{
2059 			struct trigger_data *other_trigger= get_player_trigger_data(player_index, !which_trigger);
2060 
2061 			/* Note the presence of two weapons trying to reload simultaneously.. */
2062 			if(other_trigger->state==_weapon_waiting_for_other_idle_to_reload)
2063 			{
2064 				/* He already had priority. */
2065 				trigger->state= _weapon_lowering_for_twofisted_reload;
2066 				trigger->phase= definition->ready_ticks;
2067 				other_trigger->state= _weapon_awaiting_twofisted_reload;
2068 				other_trigger->phase= definition->ready_ticks;
2069 			} else {
2070 				/* Try as we go through the loop next time.. */
2071 				trigger->state= _weapon_waiting_for_other_idle_to_reload;
2072 				trigger->phase= 0;
2073 			}
2074 		} else {
2075 			/* Don't go to a state that has a zero duration.. */
2076 			if(definition->await_reload_ticks)
2077 			{
2078 				trigger->state= _weapon_awaiting_reload;
2079 				trigger->phase= definition->await_reload_ticks; // should this be by trigger?
2080 			} else {
2081 				trigger->state= _weapon_waiting_to_load;
2082 				trigger->phase= definition->loading_ticks; // should this be by trigger?
2083 			}
2084 		}
2085 		trigger->sequence= 0; // Reset this here, because it won't get reset otherwise.
2086 		can_reload= true;
2087 	} else {
2088 		/* If this weapon needs to dissappear */
2089 		if(definition->flags & _weapon_disappears_after_use)
2090 		{
2091 			destroy_current_weapon(player_index);
2092 		}
2093 		can_reload= false;
2094 	}
2095 
2096 	return can_reload;
2097 }
2098 
destroy_current_weapon(short player_index)2099 static void destroy_current_weapon(
2100 	short player_index)
2101 {
2102 	struct player_data *player= get_player_data(player_index);
2103 	struct weapon_definition *definition= get_current_weapon_definition(player_index);
2104 	short item_type;
2105 
2106 	assert(definition->item_type>=0 && definition->item_type<NUMBER_OF_ITEMS);
2107 	if(get_item_kind(definition->item_type)==_ball)
2108 	{
2109 		/* Drop the ball.. */
2110 		short ball_color= find_player_ball_color(player_index);
2111 		// START Benad
2112 		// assert(ball_color!=NONE);
2113 		if (ball_color != NONE)
2114 			item_type= find_player_ball_color(player_index)+BALL_ITEM_BASE;
2115 		else
2116 			return;
2117 		// END Benad
2118 	} else {
2119 		item_type= definition->item_type;
2120 	}
2121 
2122 	/* Decrement the item.. */
2123 	player->items[item_type]--;
2124 	if(player->items[item_type]<=0)	player->items[item_type]= NONE;
2125 
2126 	/* Second parameter: */
2127 	/* NONE- don't switch to ammo list */
2128 	/* _i_magnum_magazine- switch to ammo list */
2129 	mark_player_inventory_as_dirty(player_index, _i_magnum_magazine);
2130 }
2131 
check_reload(short player_index,short which_trigger)2132 static bool check_reload(
2133 	short player_index,
2134 	short which_trigger)
2135 {
2136 	struct trigger_data *trigger= get_player_trigger_data(player_index, which_trigger);
2137 	struct weapon_definition *definition=
2138 		get_current_weapon_definition(player_index);
2139 	bool reloaded_weapon= false;
2140 
2141 	/* Check to see if the weapon is empty.. */
2142 	if(!trigger->rounds_loaded)
2143 	{
2144 		switch(definition->weapon_class)
2145 		{
2146 			case _melee_class:
2147 				/* Always have a round loaded.. */
2148 				trigger->rounds_loaded= 1;
2149 				break;
2150 
2151 			case _dual_function_class:
2152 				if(definition->flags & _weapon_triggers_share_ammo)
2153 				{
2154 					which_trigger= _primary_weapon;
2155 				}
2156 				/* Fallthrough */
2157 			case _normal_class:
2158 				/* Hmmm.. we are out of ammunition */
2159 				if(!reload_weapon(player_index, which_trigger))
2160 				{
2161 					/* Switch to the next weapon.. */
2162 					select_next_best_weapon(player_index);
2163 				} else {
2164 					reloaded_weapon= true;
2165 				}
2166 				break;
2167 
2168 			case _twofisted_pistol_class:
2169 				{
2170 					struct weapon_data *weapon= get_player_current_weapon(player_index);
2171 
2172 					if(PRIMARY_WEAPON_IS_VALID(weapon) && SECONDARY_WEAPON_IS_VALID(weapon))
2173 					{
2174 						if(!reload_weapon(player_index, which_trigger))
2175 						{
2176 							/* Okay, we couldn't reload one of them.  */
2177 							/* Does the other one have ammo? */
2178 							struct trigger_data *other_trigger_data=
2179 								get_player_trigger_data(player_index, !which_trigger);
2180 
2181 							if(!other_trigger_data->rounds_loaded)
2182 							{
2183 								/* We have to change... */
2184 								select_next_best_weapon(player_index);
2185 							} else {
2186 								if(which_trigger==_primary_weapon)
2187 								{
2188 									/* ���Problems? */
2189 									struct trigger_data *other_trigger=
2190 										get_player_trigger_data(player_index, !which_trigger);
2191 
2192 									trigger->state= _weapon_lowering;
2193 									trigger->phase= definition->ready_ticks-1;
2194 									trigger->sequence= 0;
2195 
2196 									other_trigger->state= _weapon_sliding_over_from_second_position;
2197 									other_trigger->phase= definition->ready_ticks;
2198 									other_trigger->sequence= 0;
2199 								} else {
2200 									struct trigger_data *other_trigger=
2201 										get_player_trigger_data(player_index, !which_trigger);
2202 
2203 									assert(which_trigger==_secondary_weapon);
2204 									trigger->state= _weapon_lowering;
2205 									trigger->phase= definition->ready_ticks;
2206 									trigger->sequence= 0;
2207 
2208 									other_trigger->state= _weapon_sliding_over_from_second_position;
2209 									other_trigger->phase= definition->ready_ticks;
2210 									other_trigger->sequence= 0;
2211 								}
2212 							}
2213 						} else {
2214 							reloaded_weapon= true;
2215 						}
2216 					} else {
2217 						/* Hmmm.. we are out of ammunition */
2218 						if(!reload_weapon(player_index, which_trigger))
2219 						{
2220 							/* Switch to the next weapon.. */
2221 							select_next_best_weapon(player_index);
2222 						} else {
2223 							reloaded_weapon= true;
2224 						}
2225 					}
2226 				}
2227 				break;
2228 
2229 			case _multipurpose_class:
2230 				/* Only switch if both of them are out of ammo, and we can't reload the one we */
2231 				/*  just fired with. */
2232 				if(!reload_weapon(player_index, which_trigger))
2233 				{
2234 					short other_trigger= !which_trigger;
2235 					struct trigger_data *other_trigger_data;
2236 
2237 					/* check to see if the other one is empty. */
2238 					other_trigger_data= get_player_trigger_data(
2239 						player_index, other_trigger);
2240 
2241 					if(!other_trigger_data->rounds_loaded)
2242 					{
2243 						switch(other_trigger_data->state)
2244 						{
2245 							case _weapon_awaiting_reload:
2246 							case _weapon_waiting_to_load:
2247 							case _weapon_finishing_reload:
2248 								/* Don't switch, because the other is empty now, but not for long.. */
2249 								break;
2250 
2251 							default:
2252 				//dprintf("Unable to reload ar & other out of ammo (Which: %d)", which_trigger);
2253 								/* Switch to the next weapon.. */
2254 								select_next_best_weapon(player_index);
2255 								break;
2256 						}
2257 					}
2258 				} else {
2259 					reloaded_weapon= true;
2260 				}
2261 				break;
2262 
2263 			// LP change: no weapon
2264 			case NONE:
2265 			default:
2266 				break;
2267 		}
2268 	}
2269 
2270 	return reloaded_weapon;
2271 }
2272 
put_rounds_into_weapon(short player_index,short which_weapon,short which_trigger)2273 static void put_rounds_into_weapon(
2274 	short player_index,
2275 	short which_weapon,
2276 	short which_trigger)
2277 {
2278 	struct trigger_data *trigger= get_trigger_data(player_index, which_weapon, which_trigger);
2279 	struct trigger_definition *trigger_definition= get_trigger_definition(player_index, which_weapon, which_trigger);
2280 	struct weapon_definition *definition= get_weapon_definition(which_weapon);
2281 	struct player_data *player= get_player_data(player_index);
2282 
2283 	assert(trigger_definition->ammunition_type>=0 && trigger_definition->ammunition_type<NUMBER_OF_ITEMS);
2284 	if (player->items[trigger_definition->ammunition_type] == 0) {
2285 		trigger->state = _weapon_lowering;
2286 		return;
2287 	}
2288 
2289 	/* Load the gun */
2290 	trigger->rounds_loaded= trigger_definition->rounds_per_magazine;
2291 
2292 	/* Decrement the ammo magazine count. */
2293 	player->items[trigger_definition->ammunition_type]--;
2294 
2295 	/* Update the inventory display. Second parameter: NONE- don't switch to ammo list */
2296 	/* _i_magnum_magazine- switch to ammo list */
2297 	mark_player_inventory_as_dirty(player_index, _i_magnum_magazine);
2298 
2299 	/* Keep the ammo stores in sync for dual function class weapons */
2300 	if(definition->flags & _weapon_triggers_share_ammo)
2301 	{
2302 		trigger= get_player_trigger_data(player_index, !which_trigger);
2303 		trigger->rounds_loaded= trigger_definition->rounds_per_magazine;
2304 	}
2305 
2306 
2307 	/* Update the world ammunition count for the placement data */
2308 	object_was_just_destroyed(_object_is_item, trigger_definition->ammunition_type);
2309 
2310 	/* Update the player ammunition count */
2311 	update_player_ammo_count(player_index);
2312 
2313 	/* Play the sound. */
2314 	play_weapon_sound(player_index, trigger_definition->reloading_sound, FIXED_ONE);
2315 }
2316 
2317 /* This, my friend, is the trickiest of the functions */
handle_trigger_down(short player_index,short which_trigger)2318 static bool handle_trigger_down(
2319 	short player_index,
2320 	short which_trigger)
2321 {
2322 	struct weapon_data *weapon= get_player_current_weapon(player_index);
2323 	bool fired= false;
2324 
2325 	/* IF this weapon is idle.. */
2326 	if(weapon->triggers[which_trigger].state==_weapon_idle)
2327 	{
2328 		struct trigger_definition *trigger_definition= get_player_trigger_definition(
2329 			player_index, which_trigger);
2330 
2331 		/* If this weapon charges.. */
2332 		if(trigger_definition->charging_ticks)
2333 		{
2334 			struct weapon_definition *definition= get_weapon_definition(weapon->weapon_type);
2335 
2336 			/* Either the other weapon is idle and we are dual, or we aren't dual */
2337 			if(definition->weapon_class != _dual_function_class ||
2338 				(definition->weapon_class==_dual_function_class && weapon->triggers[!which_trigger].state==_weapon_idle))
2339 			{
2340 				/* start charging... */
2341 				weapon->triggers[which_trigger].state= _weapon_charging;
2342 				weapon->triggers[which_trigger].phase= trigger_definition->charging_ticks;
2343 				play_weapon_sound(player_index, trigger_definition->charging_sound, FIXED_ONE);
2344 			}
2345 		} else {
2346 			struct weapon_definition *definition= get_current_weapon_definition(player_index);
2347 
2348 			switch(definition->weapon_class)
2349 			{
2350 				case _melee_class:
2351 				case _twofisted_pistol_class:
2352 					/* Stagger the weapons firing. */
2353 					/* Rocky modification */
2354 					if(PRIMARY_WEAPON_IS_VALID(weapon) && SECONDARY_WEAPON_IS_VALID(weapon))
2355 					{
2356 						if(definition->flags & _weapon_fires_out_of_phase)
2357 						{
2358 							short total_delay, delay;
2359 							struct trigger_definition *other_trigger_definition= get_player_trigger_definition(
2360 								player_index, !which_trigger);
2361 
2362 							total_delay= other_trigger_definition->recovery_ticks+other_trigger_definition->ticks_per_round;
2363 							delay= total_delay-weapon->triggers[!which_trigger].phase;
2364 							switch(weapon->triggers[!which_trigger].state)
2365 							{
2366 								case _weapon_firing: delay-= trigger_definition->recovery_ticks;
2367 								case _weapon_recovering:
2368 									break;
2369 
2370 								default:
2371 									total_delay= delay= 1;
2372 									break;
2373 							}
2374 
2375 							/* Only able to fire exactly out of sync. */
2376 							if(delay>total_delay/2)
2377 							{
2378 								fired= true;
2379 							}
2380 						}
2381 						else
2382 						{
2383 							switch(weapon->triggers[!which_trigger].state)
2384 							{
2385 								case _weapon_firing:
2386 								case _weapon_recovering:
2387 									break;
2388 
2389 								default:
2390 									fired= true;
2391 									break;
2392 							}
2393 						}
2394 					}
2395 					else
2396 					{
2397 						/* Both aren't up.  They can fire.. */
2398 						fired= true;
2399 					}
2400 					break;
2401 
2402 				case _normal_class:
2403 					/* Always able to fire.. */
2404 					fired= true;
2405 					break;
2406 
2407 				case _multipurpose_class:
2408 					if(which_trigger==_secondary_weapon)
2409 					{
2410 						switch(weapon->triggers[_primary_weapon].state)
2411 						{
2412 							case _weapon_idle:
2413 							case _weapon_recovering:
2414 							case _weapon_firing:
2415 								fired= true;
2416 								break;
2417 
2418 							default:
2419 								/* Don't fire the other weapon when we are reloading, raising, lowering, etc. */
2420 								break;
2421 						}
2422 					} else {
2423 						/* Can always fire an idle multifunction class */
2424 						fired= true;
2425 					}
2426 					break;
2427 
2428 				case _dual_function_class:
2429 					fired= true;
2430 					break;
2431 
2432 				// LP change: no weapon -- do nothing
2433 				case NONE:
2434 				default:
2435 					break;
2436 			}
2437 
2438 			if(fired)
2439 			{
2440 				fire_weapon(player_index, which_trigger, FIXED_ONE, false);
2441 			}
2442 		}
2443 	}
2444 
2445 	/* Set the trigger down state */
2446 	if(which_trigger==_primary_weapon)
2447 		SET_TRIGGER_DOWN(weapon, true);
2448 
2449 	return fired;
2450 }
2451 
2452 /* we only care about the trigger going up on charged weapons.. */
handle_trigger_up(short player_index,short which_trigger)2453 static bool handle_trigger_up(
2454 	short player_index,
2455 	short which_trigger)
2456 {
2457 	struct weapon_data *weapon= get_player_current_weapon(player_index);
2458 	struct trigger_definition *trigger_definition=
2459 		get_player_trigger_definition(player_index, which_trigger);
2460 	bool discharge;
2461 	_fixed charged_amount = 0;
2462 
2463 	/* On charged weapons, when the trigger goes up, we discharge.. */
2464 	switch(weapon->triggers[which_trigger].state)
2465 	{
2466 		case _weapon_charging:
2467 			discharge= true;
2468 			charged_amount= ((trigger_definition->charging_ticks-weapon->triggers[which_trigger].phase)*FIXED_ONE)/FIXED_ONE;
2469 			break;
2470 
2471 		case _weapon_charged:
2472 			/* These are the only states that we really care about. */
2473 			discharge= true;
2474 			charged_amount= FIXED_ONE;
2475 			break;
2476 
2477 		default:
2478 			discharge= false;
2479 			break;
2480 	}
2481 
2482 	/* Fire the weapon (but only if it is at least 90% charged.) */
2483 	if(discharge)
2484 	{
2485 		struct player_data *player= get_player_data(player_index);
2486 
2487 		/* Don't discharge on teleporting. */
2488 		if(!PLAYER_IS_TELEPORTING(player) && !PLAYER_IS_INTERLEVEL_TELEPORTING(player))
2489 		{
2490 			if(charged_amount>(9*FIXED_ONE)/10)
2491 			{
2492 				fire_weapon(player_index, which_trigger, charged_amount, false);
2493 			} else {
2494 				struct player_data *player= get_player_data(player_index);
2495 
2496 				/* You lose. */
2497 				weapon->triggers[which_trigger].state= _weapon_idle;
2498 				weapon->triggers[which_trigger].phase= IDLE_PHASE_COUNT;
2499 				weapon->triggers[which_trigger].sequence= 0;
2500 				SoundManager::instance()->StopSound(player->object_index, trigger_definition->charging_sound);
2501 			}
2502 		}
2503 	}
2504 
2505 	/* Trigger down is only maintained to avoid switching a weapon */
2506 	if(which_trigger==_primary_weapon)
2507 	{
2508 		SET_TRIGGER_DOWN(weapon, false);
2509 
2510 		if(weapon->triggers[which_trigger].ticks_firing>FIRING_BEFORE_SHELL_CASING_SOUND_IS_PLAYED)
2511 		{
2512 			struct trigger_definition *trigger_definition= get_player_trigger_definition(player_index,
2513 				which_trigger);
2514 
2515 			weapon->triggers[which_trigger].ticks_firing= 0;
2516 			play_shell_casing_sound(player_index, trigger_definition->shell_casing_sound);
2517 		}
2518 	}
2519 
2520 	return discharge;
2521 }
2522 
2523 /* Need to put a reload weapon in here, if that is what we want to do.. */
2524 	/* Need to put a reload weapon in here, if that is what we want to do.. */
2525 	/* CP Addition: removed 'static' to provide extern access
2526 static bool ready_weapon(
2527 	short player_index,
2528 	short weapon_index)
2529 
2530 */
ready_weapon(short player_index,short weapon_index)2531 bool ready_weapon(
2532 	short player_index,
2533 	short weapon_index)
2534 {
2535 	bool able_to_ready= false;
2536 	struct weapon_definition *definition= get_weapon_definition(weapon_index);
2537 	struct player_data *player= get_player_data(player_index);
2538 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
2539 
2540 	if(weapon_works_in_current_environment(weapon_index))
2541 	{
2542 		if(player_weapons->desired_weapon != weapon_index)
2543 		{
2544 			if(player->items[definition->item_type] > 0 || weapon_index==_weapon_ball)
2545 			{
2546 				if(player_weapon_has_ammo(player_index, weapon_index))
2547 				{
2548 					player_weapons->desired_weapon= weapon_index;
2549 
2550 					/* update the weapon display */
2551 					if(player_index==current_player_index) mark_weapon_display_as_dirty();
2552 					able_to_ready= true;
2553 				}
2554 			}
2555 		}
2556 	}
2557 
2558 	return able_to_ready;
2559 }
2560 
player_weapon_has_ammo(short player_index,short weapon_index)2561 static bool player_weapon_has_ammo(
2562 	short player_index,
2563 	short weapon_index)
2564 {
2565 	struct player_data *player= get_player_data(player_index);
2566 	struct weapon_definition *definition= get_weapon_definition(weapon_index);
2567 	bool has_ammo= false;
2568 
2569 	if(definition->weapon_class==_melee_class)
2570 	{
2571 		has_ammo= true;
2572 	} else {
2573 		short which_trigger, max_triggers;
2574 
2575 		switch(definition->weapon_class)
2576 		{
2577 			case _melee_class:
2578 			case _dual_function_class:
2579 			case _twofisted_pistol_class:
2580 			case _multipurpose_class:
2581 				max_triggers= 2;
2582 				break;
2583 
2584 			case _normal_class:
2585 				max_triggers= 1;
2586 				break;
2587 
2588 			// LP change: no weapon -- do nothing
2589 			case NONE:
2590 			default:
2591 				max_triggers= 0;
2592 				break;
2593 		}
2594 
2595 		for(which_trigger= _primary_weapon; !has_ammo && which_trigger<max_triggers; ++which_trigger)
2596 		{
2597 			struct trigger_data *trigger= get_trigger_data(player_index, weapon_index,
2598 				which_trigger);
2599 
2600 			if(trigger->rounds_loaded>0)
2601 			{
2602 				has_ammo= true;
2603 			} else {
2604 				struct trigger_definition *trigger_definition=
2605 					get_trigger_definition(player_index, weapon_index, which_trigger);
2606 
2607 				/* Could we load this guy? */
2608 				if(	trigger_definition->ammunition_type != NONE &&
2609 					player->items[trigger_definition->ammunition_type] > 0)
2610 				{
2611 					has_ammo=  true;
2612 				}
2613 			}
2614 		}
2615 	}
2616 
2617 	return has_ammo;
2618 }
2619 
lower_weapon(short player_index,short weapon_index)2620 static void lower_weapon(
2621 	short player_index,
2622 	short weapon_index)
2623 {
2624 	struct weapon_definition *definition= get_weapon_definition(weapon_index);
2625 	short which_trigger, active_trigger_count, first_trigger;
2626 
2627 	active_trigger_count= get_active_trigger_count_and_states(player_index, weapon_index,
2628 		0l, &first_trigger, NULL);
2629 	for(which_trigger= first_trigger; which_trigger<active_trigger_count; ++which_trigger)
2630 	{
2631 		struct trigger_data *trigger= get_trigger_data(player_index, weapon_index,
2632 			which_trigger);
2633 
2634 		/* If this weapon isn't already lowering.. */
2635 		if(trigger->state != _weapon_lowering)
2636 		{
2637 			/* If we aren't raising, set the phase.  Otherwise use */
2638 			/*  the current phase to go back down.. */
2639 			if( trigger->state==_weapon_idle)
2640 			{
2641 				trigger->phase= definition->ready_ticks;
2642 			} else {
2643 				assert(trigger->state==_weapon_raising);
2644 				trigger->phase= definition->ready_ticks - trigger->phase;
2645 			}
2646 
2647 			trigger->state= _weapon_lowering;
2648 			trigger->sequence= 0;
2649 		}
2650 	}
2651 }
2652 
2653 /*
2654 	note that if we are raising a weapon, we want to fill it up with ammo first,
2655 	if we can (and should).  This means that if you switch weapons during a lengthy
2656 	reload, you can win.
2657 */
raise_weapon(short player_index,short weapon_index)2658 static void raise_weapon(
2659 	short player_index,
2660 	short weapon_index)
2661 {
2662 	struct weapon_definition *definition= get_weapon_definition(weapon_index);
2663 	short which_trigger, active_trigger_count, first_trigger;
2664 
2665 // dprintf("Raising: %d;g", weapon_index);
2666 	active_trigger_count= get_active_trigger_count_and_states(player_index, weapon_index, 0l,
2667 		&first_trigger, NULL);
2668 	for(which_trigger= first_trigger; which_trigger<active_trigger_count; ++which_trigger)
2669 	{
2670 		struct trigger_data *trigger= get_trigger_data(player_index, weapon_index,
2671 			which_trigger);
2672 
2673 		if(trigger->state!=_weapon_raising)
2674 		{
2675 			/* If we aren't raising, set the phase.  Otherwise use */
2676 			/*  the current phase to go back down.. */
2677 			if(trigger->state==_weapon_idle)
2678 			{
2679 				trigger->phase= definition->ready_ticks;
2680 			} else {
2681 				vassert(trigger->state==_weapon_lowering, csprintf(temporary, "State: %d phase: %d trigger: %d weapon: %d",
2682 					trigger->state, trigger->phase, which_trigger, weapon_index));
2683 				trigger->phase= definition->ready_ticks-trigger->phase;
2684 // dprintf("Lowering: Phase: %d;g", trigger->phase);
2685 			}
2686 			trigger->state= _weapon_raising;
2687 			trigger->sequence= 0;
2688 
2689 			if(which_trigger==_primary_weapon)
2690 			{
2691 				struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
2692 
2693 				SET_PRIMARY_WEAPON_IS_VALID(&player_weapons->weapons[weapon_index], true);
2694 			} else {
2695 				struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
2696 
2697 // dprintf("Second valid;g");
2698 				SET_SECONDARY_WEAPON_IS_VALID(&player_weapons->weapons[weapon_index], true);
2699 			}
2700 		}
2701 	}
2702 }
2703 
2704 /* Note that we are guaranteed that the current weapon has ammo.. */
should_switch_to_weapon(short player_index,short new_weapon)2705 static bool should_switch_to_weapon(
2706 	short player_index,
2707 	short new_weapon)
2708 {
2709 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
2710 	bool should_change= false;
2711 
2712 	/* Switch to it if we should.. */
2713 	/* Change if: */
2714 	/*		The current weapon is the desired weapon, the trigger is not down, AND either: */
2715 	/*		A) They don't have a weapon */
2716 	/*		B) The new weapon is better and the current weapon is not charging OR */
2717 	/*		C) The current weapon has no ammunition */
2718 	if(weapon_works_in_current_environment(new_weapon))
2719 	{
2720 		if(player_weapons->desired_weapon==player_weapons->current_weapon || new_weapon==_weapon_ball)
2721 		{
2722 			short new_weapon_index, current_weapon_index;
2723 
2724 			/* Find the relative powers of the weapons to determine which is greater */
2725 			new_weapon_index= find_weapon_power_index(new_weapon);
2726 			current_weapon_index= find_weapon_power_index(player_weapons->current_weapon);
2727 
2728 			/* If the new weapon is better.. */
2729 			if(new_weapon_index>current_weapon_index)
2730 			{
2731 				if(player_weapons->current_weapon==NONE)
2732 				{
2733 					/* Always change if they didn't have a weapon.. */
2734 					should_change= true;
2735 				} else {
2736 					struct weapon_data *weapon= get_player_current_weapon(player_index);
2737 
2738 					if(new_weapon==_weapon_ball)
2739 					{
2740 						should_change= true;
2741 					} else {
2742 						/* If this weapon is not charging or charged.. */
2743 						if(weapon->triggers[_primary_weapon].state!=_weapon_charging &&
2744 							weapon->triggers[_primary_weapon].state!=_weapon_charged &&
2745 							weapon->triggers[_secondary_weapon].state!=_weapon_charging &&
2746 							weapon->triggers[_secondary_weapon].state!=_weapon_charged)
2747 						{
2748 							/* If this weapon doesn't have the trigger down... */
2749 							// LP addition: Josh Elsasser's dont-switch-weapons patch
2750 							if(!TRIGGER_IS_DOWN(weapon))
2751 							{
2752 								if (!PLAYER_DOESNT_AUTO_SWITCH_WEAPONS(get_player_data(player_index)))
2753 									should_change= true;
2754 							}
2755 						}
2756 					}
2757 				}
2758 			}
2759 			/* or the current weapon doesn't have ammo */
2760 			else if(!player_weapon_has_ammo(player_index, player_weapons->current_weapon))
2761 			{
2762 				should_change= true;
2763 			}
2764 		}
2765 	}
2766 
2767 	return should_change;
2768 }
2769 
calculate_weapon_position_for_idle(short player_index,short count,short weapon_type,_fixed * height,_fixed * width,bool use_elevation)2770 static void calculate_weapon_position_for_idle(
2771 	short player_index,
2772 	short count,
2773 	short weapon_type,
2774 	_fixed *height,
2775 	_fixed *width,
2776 	bool use_elevation)
2777 {
2778 	struct weapon_definition *definition= get_weapon_definition(weapon_type);
2779 	struct player_data *player= get_player_data(player_index);
2780 	_fixed horizontal_phase, vertical_angle, bob_height, bob_width;
2781 	short *table;
2782 
2783 	if(count==0)
2784 	{
2785 		table= sine_table;
2786 		horizontal_phase= player->variables.step_phase;
2787 		vertical_angle= player->variables.step_phase>>(FIXED_FRACTIONAL_BITS-ANGULAR_BITS);
2788 	} else {
2789 		table= cosine_table;
2790 		vertical_angle= NORMALIZE_ANGLE((player->variables.step_phase>>(FIXED_FRACTIONAL_BITS-ANGULAR_BITS))+HALF_CIRCLE);
2791 		horizontal_phase= player->variables.step_phase;
2792 	}
2793 	/* Weapons are the first thing drawn */
2794 	bob_height= (player->variables.step_amplitude*definition->bob_amplitude)>>FIXED_FRACTIONAL_BITS;
2795 	bob_height= (bob_height*table[vertical_angle])>>TRIG_SHIFT;
2796 	if (!graphics_preferences->screen_mode.camera_bob) bob_height= 0;
2797 	if (use_elevation) bob_height+= sine_table[player->elevation]<<3;
2798 	*height+= bob_height;
2799 
2800 	bob_width= (player->variables.step_amplitude*definition->horizontal_amplitude)>>FIXED_FRACTIONAL_BITS;
2801 	bob_width= (bob_width*table[horizontal_phase>>(FIXED_FRACTIONAL_BITS-ANGULAR_BITS)])>>TRIG_SHIFT;
2802 	if (!graphics_preferences->screen_mode.camera_bob) bob_width= 0;
2803 	*width += bob_width;
2804 }
2805 
modify_position_for_two_weapons(short player_index,short count,_fixed * width,_fixed * height)2806 static void modify_position_for_two_weapons(
2807 	short player_index,
2808 	short count,
2809 	_fixed *width,
2810 	_fixed *height)
2811 {
2812 	struct weapon_definition *definition= get_current_weapon_definition(player_index);
2813 
2814 	/* Handle modifying the width for twofisted weapons.. */
2815 	switch(definition->weapon_class)
2816 	{
2817 		case _melee_class:
2818 			{
2819 				if (definition->flags & _weapon_is_marathon_1) {
2820 					break;
2821 				}
2822 
2823 				struct weapon_data *weapon= get_player_current_weapon(player_index);
2824 				struct trigger_definition *trigger_definition;
2825 				short total_delay, delay, breakpoint_delay, sign;
2826 
2827 				if(PRIMARY_WEAPON_IS_VALID(weapon) && SECONDARY_WEAPON_IS_VALID(weapon))
2828 				{
2829 					switch(count)
2830 					{
2831 						case 0:
2832 						case 1:
2833 							sign= (count) ? -1 : 1;
2834 							*width+= (PISTOL_SEPARATION_WIDTH*sign);
2835 							trigger_definition= get_player_trigger_definition(player_index, !count);
2836 							total_delay= trigger_definition->ticks_per_round+trigger_definition->recovery_ticks;
2837 							breakpoint_delay= (2*total_delay)/3;
2838 							delay= total_delay-weapon->triggers[!count].phase;
2839 							switch(weapon->triggers[!count].state)
2840 							{
2841 								case _weapon_firing: delay-= trigger_definition->recovery_ticks;
2842 								case _weapon_recovering:
2843 									if(delay>=breakpoint_delay)
2844 									{
2845 										/* Delay needs to go from breakpoint_delay to zero */
2846 										delay= total_delay - delay;
2847 										*width+= sign*((FIXED_ONE/8)*delay)/(total_delay-breakpoint_delay);
2848 										*height+= ((FIXED_ONE/16)*delay)/(total_delay-breakpoint_delay);
2849 									} else {
2850 										*width+= sign*((FIXED_ONE/8)*delay)/breakpoint_delay;
2851 										*height+= ((FIXED_ONE/16)*delay)/breakpoint_delay;
2852 									}
2853 									break;
2854 							}
2855 							break;
2856 
2857 						default:
2858 							break;
2859 					}
2860 				} else {
2861 					*width+= FIXED_ONE_HALF/2;
2862 				}
2863 			}
2864 			break;
2865 
2866 		case _twofisted_pistol_class:
2867 			{
2868 				struct weapon_data *weapon= get_player_current_weapon(player_index);
2869 
2870 				if(PRIMARY_WEAPON_IS_VALID(weapon) && SECONDARY_WEAPON_IS_VALID(weapon))
2871 				{
2872 					switch(count)
2873 					{
2874 						case 0: *width += PISTOL_SEPARATION_WIDTH/2; break;
2875 						case 1: *width -= PISTOL_SEPARATION_WIDTH/2; break;
2876 						default: break;
2877 					}
2878 				}
2879 			}
2880 			break;
2881 
2882 		default:
2883 			break;
2884 	}
2885 }
2886 
add_random_flutter(_fixed flutter_base,_fixed * height,_fixed * width)2887 static void add_random_flutter(
2888 	_fixed flutter_base,
2889 	_fixed *height,
2890 	_fixed *width)
2891 {
2892 	_fixed delta_height, delta_width;
2893 
2894 	delta_height= flutter_base>>4;
2895 	delta_width= flutter_base>>6;
2896 
2897 	/* Note that we MUST use rand() here, and not global_random() */
2898 	if(delta_height) *height += (rand()%delta_height)-(delta_height/2);
2899 	if(delta_width) *width += (rand()%delta_width)-(delta_width/2);
2900 }
2901 
play_weapon_sound(short player_index,short sound,_fixed pitch)2902 static void play_weapon_sound(
2903 	short player_index,
2904 	short sound,
2905 	_fixed pitch)
2906 {
2907 	struct player_data *player= get_player_data(player_index);
2908 	struct monster_data *monster= get_monster_data(player->monster_index);
2909 	struct object_data *object= get_object_data(monster->object_index);
2910 	_fixed old_pitch= object->sound_pitch;
2911 
2912 	object->sound_pitch= pitch;
2913 	play_object_sound(monster->object_index, sound);
2914 	object->sound_pitch= old_pitch;
2915 }
2916 
get_active_trigger_count_and_states(short player_index,short weapon_index,uint32 action_flags,short * first_trigger,bool * triggers_down)2917 static short get_active_trigger_count_and_states(
2918 	short player_index,
2919 	short weapon_index,
2920 	uint32 action_flags,
2921 	short *first_trigger,
2922 	bool *triggers_down)
2923 {
2924 	struct weapon_definition *definition= get_weapon_definition(weapon_index);
2925 	short active_count = 0;
2926 
2927 	assert(first_trigger);
2928 
2929 	if(triggers_down)
2930 	{
2931 		triggers_down[0]= triggers_down[1]= false;
2932 	}
2933 
2934 	(*first_trigger)= _primary_weapon;
2935 
2936 	int16 weapon_class = definition->weapon_class;
2937 	if (weapon_class == _melee_class && (definition->flags & _weapon_is_marathon_1)) {
2938 		weapon_class = _normal_class;
2939 	}
2940 
2941 	switch(weapon_class)
2942 	{
2943 		case _normal_class:
2944 			active_count= 1;
2945 			if(triggers_down)
2946 			{
2947 				if(action_flags & _left_trigger_state || action_flags & _right_trigger_state) triggers_down[0]= true;
2948 			}
2949 			break;
2950 
2951 		case _melee_class:
2952 		case _twofisted_pistol_class:
2953 			{
2954 				struct player_data *player= get_player_data(player_index);
2955 				struct weapon_data *weapon= get_player_current_weapon(player_index);
2956 
2957 				if(player->items[definition->item_type]>1 &&
2958 					PRIMARY_WEAPON_IS_VALID(weapon) && SECONDARY_WEAPON_IS_VALID(weapon))
2959 				{
2960 					if(triggers_down)
2961 					{
2962 						if(action_flags & _left_trigger_state) triggers_down[0]= true;
2963 						if(action_flags & _right_trigger_state) triggers_down[1]= true;
2964 					}
2965 					active_count= 2;
2966 				} else {
2967 					if(SECONDARY_WEAPON_IS_VALID(weapon))
2968 					{
2969 						if(triggers_down)
2970 						{
2971 							if(action_flags & _left_trigger_state) triggers_down[1]= true;
2972 							if(action_flags & _right_trigger_state) triggers_down[1]= true;
2973 						}
2974 
2975 						(*first_trigger)= _secondary_weapon;
2976 						active_count= 2;
2977 					} else {
2978 						if(triggers_down)
2979 						{
2980 							if(action_flags & _left_trigger_state) triggers_down[0]= true;
2981 							if(action_flags & _right_trigger_state) triggers_down[0]= true;
2982 						}
2983 						active_count= 1;
2984 					}
2985 				}
2986 			}
2987 			break;
2988 
2989 		case _dual_function_class:
2990 			if(triggers_down)
2991 			{
2992 				if(dual_function_secondary_has_control(player_index))
2993 				{
2994 					triggers_down[_primary_weapon]= false;
2995 				} else {
2996 					if(action_flags & _left_trigger_state) triggers_down[0]= true;
2997 				}
2998 
2999 				/* check the right trigger */
3000 				if(action_flags & _right_trigger_state) triggers_down[1]= true;
3001 			}
3002 			active_count= 2;
3003 			break;
3004 
3005 		case _multipurpose_class:
3006 			if(triggers_down)
3007 			{
3008 				if(action_flags & _left_trigger_state) triggers_down[0]= true;
3009 				if(action_flags & _right_trigger_state) triggers_down[1]= true;
3010 			}
3011 			active_count= 2;
3012 			break;
3013 
3014 		// LP change: no weapon
3015 		case NONE:
3016 		default:
3017 			break;
3018 	}
3019 
3020 	return active_count;
3021 }
3022 
dual_function_secondary_has_control(short player_index)3023 static bool dual_function_secondary_has_control(
3024 	short player_index)
3025 {
3026 	struct trigger_data *trigger= get_player_trigger_data(player_index, _secondary_weapon);
3027 	bool secondary_has_control;
3028 
3029 	switch(trigger->state)
3030 	{
3031 		case _weapon_recovering:
3032 		case _weapon_firing:
3033 		case _weapon_charging:
3034 		case _weapon_charged:
3035 			/* You can't fire your primary until secondary is idle */
3036 			secondary_has_control= true;
3037 			break;
3038 
3039 		default:
3040 			secondary_has_control= false;
3041 			break;
3042 	}
3043 
3044 	return secondary_has_control;
3045 }
3046 
3047 /* Called once the shapes are loaded */
calculate_ticks_from_shapes(void)3048 static void calculate_ticks_from_shapes(
3049 	void)
3050 {
3051 	for(unsigned weapon_type= 0; weapon_type<NUMBER_OF_WEAPONS; ++weapon_type)
3052 	{
3053 		struct weapon_definition *definition= get_weapon_definition(weapon_type);
3054 
3055 		/* Handle the firing ticks */
3056 		if(definition->weapons_by_trigger[_primary_weapon].ticks_per_round==NONE)
3057 		{
3058 			struct shape_animation_data *high_level_data;
3059 			short total_ticks;
3060 
3061 			trigger_definition& primary = definition->weapons_by_trigger[_primary_weapon];
3062 			trigger_definition& secondary = definition->weapons_by_trigger[_secondary_weapon];
3063 
3064 			high_level_data= get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection,
3065 				definition->firing_shape));
3066 			// Skip over if the sequence is nonexistent
3067 			if(!high_level_data) continue;
3068 
3069 			total_ticks= high_level_data->ticks_per_frame*high_level_data->frames_per_view;
3070 
3071 			if (definition->flags & _weapon_is_marathon_1)
3072 			{
3073 				if (definition->flags & _weapon_is_automatic)
3074 				{
3075 					primary.ticks_per_round = total_ticks - 1;
3076 					primary.recovery_ticks = 0;
3077 				}
3078 				else
3079 				{
3080 					primary.ticks_per_round = total_ticks - 1;
3081 				}
3082 			}
3083 			else if(definition->flags & _weapon_is_automatic)
3084 			{
3085 				/* All automatic weapons have no recovery time.. */
3086 				primary.ticks_per_round= total_ticks;
3087 				primary.recovery_ticks= 0;
3088 			} else {
3089 				primary.ticks_per_round=
3090 					(high_level_data->key_frame+1)*high_level_data->ticks_per_frame;
3091 				primary.recovery_ticks= total_ticks-
3092 					definition->weapons_by_trigger[_primary_weapon].ticks_per_round;
3093 			}
3094 
3095 			/* Fixup the secondary trigger.. */
3096 			if(secondary.ticks_per_round== NONE && (definition->flags & _weapon_triggers_share_ammo))
3097 			{
3098 				secondary.ticks_per_round= primary.ticks_per_round;
3099 				secondary.recovery_ticks= primary.recovery_ticks;
3100 			}
3101 
3102 			/* Rocky modification */
3103 			if(definition->weapon_class==_melee_class || definition->weapon_class==_twofisted_pistol_class)
3104 			{
3105 				if (definition->flags & _weapon_is_marathon_1)
3106 				{
3107 					secondary.ticks_per_round = total_ticks - 1;
3108 				} else {
3109 					secondary.ticks_per_round=
3110 						(high_level_data->key_frame+1)*high_level_data->ticks_per_frame;
3111 					secondary.recovery_ticks= total_ticks-
3112 						definition->weapons_by_trigger[_secondary_weapon].ticks_per_round;
3113 				}
3114 			}
3115 		}
3116 
3117 		/* Handle the reloading ticks */
3118 		if(definition->reloading_shape != NONE)
3119 		{
3120 			struct shape_animation_data *high_level_data;
3121 			short total_ticks;
3122 
3123 			high_level_data= get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection,
3124 				definition->reloading_shape));
3125 			// Skip over if the sequence is nonexistent
3126 			if(!high_level_data) continue;
3127 
3128 			total_ticks= high_level_data->ticks_per_frame*high_level_data->frames_per_view;
3129 			definition->await_reload_ticks= 0;
3130 			definition->loading_ticks= high_level_data->ticks_per_frame*(high_level_data->key_frame+1)
3131 				- definition->await_reload_ticks;
3132 			definition->finish_loading_ticks= total_ticks - definition->loading_ticks
3133 				- definition->await_reload_ticks;
3134 		} else {
3135 			/* This shape doesn't have a reloading shape, therefore the reload */
3136 			/*  time is calculated here. */
3137 			short total_ticks= definition->await_reload_ticks +
3138 								definition->loading_ticks +
3139 								definition->finish_loading_ticks;
3140 
3141 			/* Each are set to the same value.. */
3142 			definition->await_reload_ticks= total_ticks/3;
3143 			definition->loading_ticks= total_ticks/3;
3144 			definition->finish_loading_ticks= total_ticks/3;
3145 		}
3146 	}
3147 }
3148 
update_automatic_sequence(short player_index,short which_trigger)3149 static void update_automatic_sequence(
3150 	short player_index,
3151 	short which_trigger)
3152 {
3153 	struct weapon_definition *definition= get_current_weapon_definition(player_index);
3154 
3155 	if(definition->flags & _weapon_is_automatic)
3156 	{
3157 		if(which_trigger==_primary_weapon ||
3158 			(which_trigger==_secondary_weapon && (definition->flags & _weapon_secondary_has_angular_flipping)))
3159 		{
3160 			struct trigger_data *trigger= get_player_trigger_data(player_index, which_trigger);
3161 			struct shape_animation_data *high_level_data= NULL;
3162 
3163 			switch(trigger->state)
3164 			{
3165 				case _weapon_firing:
3166 				case _weapon_recovering:
3167 					high_level_data= get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection,
3168 						definition->firing_shape));
3169 					break;
3170 
3171 				case _weapon_idle:
3172 					if(automatic_still_firing(player_index, which_trigger))
3173 					{
3174 						high_level_data= get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection,
3175 							definition->firing_shape));
3176 					} else {
3177 						// Now handled in UpdateIdleWeapon()
3178 						// trigger->sequence= BUILD_SEQUENCE(0, 0);
3179 					}
3180 					break;
3181 
3182 				default:
3183 					break;
3184 			}
3185 
3186 			if(high_level_data)
3187 			{
3188 				short frame;
3189 
3190 				frame= GET_SEQUENCE_FRAME(trigger->sequence);
3191 
3192 				// does Marathon 1 have a bug or something?
3193 				if (definition->flags & _weapon_is_marathon_1 && high_level_data->frames_per_view == 2)
3194 				{
3195 					if (++frame >= 1) {
3196 						frame = 0;
3197 					}
3198 				}
3199 				else if(++frame>=high_level_data->frames_per_view)
3200 				{
3201 					frame= 0;
3202 				}
3203 				trigger->sequence= BUILD_SEQUENCE(frame, 0);
3204 			}
3205 		}
3206 	}
3207 }
3208 
3209 // LP addition: update the idle-weapon animation:
UpdateIdleAnimation(short player_index,short which_trigger)3210 static void UpdateIdleAnimation(
3211 	short player_index,
3212 	short which_trigger)
3213 {
3214 	struct trigger_data *trigger= get_player_trigger_data(player_index, which_trigger);
3215 	if (trigger->state != _weapon_idle) return;
3216 	if (automatic_still_firing(player_index, which_trigger)) return;
3217 
3218 	struct weapon_definition *definition= get_current_weapon_definition(player_index);
3219 	struct shape_animation_data *animation =
3220 		get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection, definition->idle_shape));
3221 	if (!animation) return;
3222 
3223 	// Code cribbed from animate_object() in map.cpp
3224 
3225 	/* if this animation has frames, animate it */
3226 	if (animation->frames_per_view>=1 && animation->number_of_views!=_unanimated && !(definition->flags & _weapon_is_marathon_1))
3227 	{
3228 		short frame, phase;
3229 
3230 		// LP change: added some idiot-proofing to the ticks-per-frame value
3231 		if (animation->ticks_per_frame <= 0)
3232 			animation->ticks_per_frame = 1;
3233 
3234 		frame= GET_SEQUENCE_FRAME(trigger->sequence);
3235 		phase= GET_SEQUENCE_PHASE(trigger->sequence);
3236 		if (!frame && (!phase || phase>=animation->ticks_per_frame)) play_weapon_sound(player_index, animation->first_frame_sound, FIXED_ONE);
3237 
3238 		/* phase is left unadjusted if it goes over ticks_per_frame until the next call */
3239 		if (phase>=animation->ticks_per_frame) phase-= animation->ticks_per_frame;
3240 		if ((phase+= 1)>=animation->ticks_per_frame)
3241 		{
3242 			frame+= 1;
3243 			// LP change: interchanged these two so that
3244 			// 1: keyframe 0 would get recognized
3245 			// 2: to keep the timing correct in the nonzero case
3246 			// LP change: inverted the order yet again to get more like Moo,
3247 			// but this time, added detection of cases
3248 			// keyframe = 0 and keyframe = [frames per view]
3249 			// Inverted the order yet again (!) to supporess Hunter death bug
3250 			if (frame>=animation->frames_per_view)
3251 			{
3252 				frame= animation->loop_frame;
3253 				if (animation->last_frame_sound!=NONE) play_weapon_sound(player_index, animation->last_frame_sound, FIXED_ONE);
3254 			}
3255 			short offset_frame = frame + animation->frames_per_view; // LP addition
3256 			if (frame==animation->key_frame || offset_frame==animation->key_frame)
3257 			{
3258 				if (animation->key_frame_sound!=NONE) play_weapon_sound(player_index, animation->first_frame_sound, FIXED_ONE);
3259 			}
3260 		}
3261 
3262 		trigger->sequence= BUILD_SEQUENCE(frame, phase);
3263 	} else {
3264 		trigger->sequence = BUILD_SEQUENCE(0, 0);
3265 	}
3266 }
3267 
3268 
3269 /* Automatic weapons should always show every frame of their firing animation */
3270 /* If it is automatic: do nothing for idle/firing/recovery.  frame time: increment frame */
update_sequence(short player_index,short which_trigger)3271 static void update_sequence(
3272 	short player_index,
3273 	short which_trigger)
3274 {
3275 	struct weapon_definition *definition= get_current_weapon_definition(player_index);
3276 	struct trigger_data *trigger= get_player_trigger_data(player_index, which_trigger);
3277 	struct shape_animation_data *high_level_data= NULL;
3278 	bool prevent_wrap= false; /* GROSS! */
3279 	_fixed pitch= FIXED_ONE;
3280 	short sound_id= NONE;
3281 
3282 	switch(trigger->state)
3283 	{
3284 		case _weapon_firing:
3285 		case _weapon_recovering:
3286 			prevent_wrap = true;	// These animations should not repeat
3287 			if((which_trigger==_primary_weapon && (definition->flags & _weapon_is_automatic))
3288 				|| (which_trigger==_secondary_weapon && (definition->flags & _weapon_is_automatic) && (definition->flags & _weapon_secondary_has_angular_flipping)))
3289 			{
3290 			} else if (trigger->state == _weapon_recovering && (definition->flags & _weapon_is_marathon_1)) {
3291 				high_level_data = get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection, definition->idle_shape));
3292 			} else {
3293 				high_level_data= get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection,
3294 					definition->firing_shape));
3295 			}
3296 			break;
3297 
3298 		case _weapon_idle:
3299 			if((which_trigger==_primary_weapon && (definition->flags & _weapon_is_automatic))
3300 			|| (which_trigger==_secondary_weapon && (definition->flags & _weapon_is_automatic) && (definition->flags & _weapon_secondary_has_angular_flipping)))
3301 			{
3302 			} else {
3303 				// Now handled in UpdateIdleAnimation
3304 				// trigger->sequence= 0;
3305 			}
3306 			break;
3307 
3308 		case _weapon_charged:
3309 			{
3310 				struct trigger_definition *trigger_definition= get_player_trigger_definition(player_index, which_trigger);
3311 
3312 				high_level_data= get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection,
3313 					definition->charged_shape));
3314 
3315 				/* Get the charged sound */
3316 				sound_id= trigger_definition->charged_sound;
3317 
3318 				/* If this weapon overloads, play with the pitch */
3319 				if(definition->flags & _weapon_overloads)
3320 				{
3321 					pitch= FIXED_ONE+(FIXED_ONE*(CHARGED_WEAPON_OVERLOAD-trigger->phase))/CHARGED_WEAPON_OVERLOAD;
3322 				}
3323 			}
3324 			break;
3325 
3326 		case _weapon_awaiting_reload:
3327 		case _weapon_waiting_to_load:
3328 		case _weapon_finishing_reload:
3329 			if(definition->reloading_shape!=NONE)
3330 			{
3331 				high_level_data= get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection,
3332 					definition->reloading_shape));
3333 				prevent_wrap= true;
3334 			} else {
3335 				trigger->sequence= 0;
3336 			}
3337 			break;
3338 
3339 		default:
3340 			trigger->sequence= 0;
3341 			break;
3342 	}
3343 
3344 	if(high_level_data)
3345 	{
3346 		short frame, phase;
3347 
3348 		frame= GET_SEQUENCE_FRAME(trigger->sequence);
3349 		phase= GET_SEQUENCE_PHASE(trigger->sequence);
3350 
3351 		if(++phase>=high_level_data->ticks_per_frame)
3352 		{
3353 			if(++frame>=high_level_data->frames_per_view)
3354 			{
3355 				/* Gross hack, but necessary due to weapons synchronicity problems. */
3356 				if(prevent_wrap)
3357 				{
3358 					frame--;
3359 					frame = MAX(frame,0);
3360 					/*
3361 					frame--;
3362 					assert(trigger->phase==1);
3363 					assert(frame>=0);
3364 					*/
3365 				} else {
3366 					frame= 0;
3367 				}
3368 			}
3369 
3370 			/* Play the keyframe sound. */
3371 			if(frame==high_level_data->key_frame)
3372 			{
3373 				play_weapon_sound(player_index, sound_id, pitch);
3374 			}
3375 
3376 			phase= 0;
3377 		}
3378 		trigger->sequence= BUILD_SEQUENCE(frame, phase);
3379 	}
3380 }
3381 
blow_up_player(short player_index)3382 static void blow_up_player(
3383 	short player_index)
3384 {
3385 	struct player_data *player= get_player_data(player_index);
3386 	struct object_data *object= get_object_data(player->object_index);
3387 
3388 	detonate_projectile(&object->location, object->polygon, _projectile_overloaded_fusion_dispersal,
3389 		player->monster_index, _monster_marine, FIXED_ONE);
3390 }
3391 
get_weapon_data_type_for_count(short player_index,short count,short * type,short * index,short * flags)3392 static bool get_weapon_data_type_for_count(
3393 	short player_index,
3394 	short count,
3395 	short *type,
3396 	short *index,
3397 	short *flags)
3398 {
3399 	struct weapon_definition *definition= get_current_weapon_definition(player_index);
3400 	struct weapon_data *weapon= get_player_current_weapon(player_index);
3401 	bool valid= true;
3402 
3403 	*flags= 0;
3404 	*type= NONE;
3405 	*index= NONE;
3406 
3407 	if ((definition->flags & _weapon_is_marathon_1) &&
3408 		(definition == get_weapon_definition(_weapon_missile_launcher)) &&
3409 		weapon->triggers[_primary_weapon].rounds_loaded)
3410 	{
3411 		if (count == 0)
3412 		{
3413 			*type= _weapon_ammo_type;
3414 			*index= _primary_weapon;
3415 			return true;
3416 		}
3417 		count -= 1;
3418 	}
3419 
3420 	switch(definition->weapon_class)
3421 	{
3422 		case _normal_class:
3423 			switch(count)
3424 			{
3425 				case 0:
3426 					*type= _weapon_type;
3427 					*index= _primary_weapon;
3428 					break;
3429 				default:
3430 					*type= _shell_casing_type;
3431 					*index= count-1;
3432 					valid= get_shell_casing_display_data((struct weapon_display_information *) NULL, *index);
3433 					break;
3434 			}
3435 			break;
3436 
3437 		case _multipurpose_class:
3438 			switch(count)
3439 			{
3440 				case 0:
3441 					*type= _weapon_type;
3442 					if(definition->flags & _weapon_secondary_has_angular_flipping)
3443 					{
3444 						switch(weapon->triggers[_secondary_weapon].state)
3445 						{
3446 							case _weapon_idle:
3447 								if(automatic_still_firing(player_index, _secondary_weapon))
3448 								{
3449 									*index= _secondary_weapon;
3450 								} else {
3451 									*index= _primary_weapon;
3452 								}
3453 								break;
3454 
3455 							case _weapon_firing:
3456 							case _weapon_recovering:
3457 								*index= _secondary_weapon;
3458 								break;
3459 
3460 							default:
3461 								*index= _primary_weapon;
3462 								break;
3463 						}
3464 					} else {
3465 						*index= _primary_weapon;
3466 					}
3467 					break;
3468 
3469 				default:
3470 					*type= _shell_casing_type;
3471 					*index= count-1;
3472 					valid= get_shell_casing_display_data((struct weapon_display_information *) NULL, *index);
3473 					break;
3474 			}
3475 			break;
3476 
3477 		case _dual_function_class:
3478 			switch(count)
3479 			{
3480 				case 0:
3481 					*type= _weapon_type;
3482 					if(dual_function_secondary_has_control(player_index))
3483 					{
3484 						*index= _secondary_weapon;
3485 					} else {
3486 						*index= _primary_weapon;
3487 					}
3488 					break;
3489 
3490 				default:
3491 					*type= _shell_casing_type;
3492 					*index= count-1;
3493 					valid= get_shell_casing_display_data((struct weapon_display_information *) NULL, *index);
3494 					break;
3495 			}
3496 			break;
3497 
3498 		case _melee_class:
3499 		case _twofisted_pistol_class:
3500 			{
3501 				struct player_data *player= get_player_data(player_index);
3502 
3503 				if(player->items[definition->item_type]>1 &&
3504 					PRIMARY_WEAPON_IS_VALID(weapon) && SECONDARY_WEAPON_IS_VALID(weapon))
3505 				{
3506 					switch(count)
3507 					{
3508 						case 0: *type= _weapon_type; *index= _primary_weapon; break;
3509 						case 1: *type= _weapon_type; *index= _secondary_weapon; *flags |= _flip_shape_horizontal; break;
3510 						default:
3511 							*type= _shell_casing_type;
3512 							*index= count-2;
3513 							valid= get_shell_casing_display_data((struct weapon_display_information *) NULL, *index);
3514 							break;
3515 					}
3516 				} else {
3517 					/* Only have one up */
3518 					switch(count)
3519 					{
3520 						case 0:
3521 							*type= _weapon_type;
3522 							if(SECONDARY_WEAPON_IS_VALID(weapon))
3523 							{
3524 								*index= _secondary_weapon;
3525 								*flags |= _flip_shape_horizontal;
3526 							} else {
3527 								*index= _primary_weapon;
3528 							}
3529 							break;
3530 
3531 						default:
3532 							*type= _shell_casing_type;
3533 							*index= count-1;
3534 							valid= get_shell_casing_display_data((struct weapon_display_information *) NULL, *index);
3535 							break;
3536 					}
3537 				}
3538 			}
3539 			break;
3540 
3541 		// LP change: no weapon
3542 		case NONE:
3543 		default:
3544 			break;
3545 	}
3546 
3547 	return valid;
3548 }
3549 
update_player_ammo_count(short player_index)3550 static void update_player_ammo_count(
3551 	short player_index)
3552 {
3553 	if(player_index==current_player_index)
3554 	{
3555 		mark_ammo_display_as_dirty();
3556 	}
3557 }
3558 
3559 extern bool LuaPlayerCanWieldWeapons(short);
3560 
player_has_valid_weapon(short player_index)3561 /*static*/ bool player_has_valid_weapon(
3562 	short player_index)
3563 {
3564 	// LP change:
3565 	if (CannotWieldWeapons() || !LuaPlayerCanWieldWeapons(player_index)) return false;
3566 
3567 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
3568 
3569 	return (player_weapons->current_weapon!=NONE);
3570 }
3571 
idle_weapon(short player_index)3572 static void idle_weapon(
3573 	short player_index)
3574 {
3575 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
3576 
3577 	if(player_weapons->desired_weapon != player_weapons->current_weapon)
3578 	{
3579 		if(player_weapons->current_weapon==NONE)
3580 		{
3581 			change_to_desired_weapon(player_index);
3582 		} else {
3583 			struct weapon_data *weapon= get_player_current_weapon(player_index);
3584 			short active_triggers, which_trigger, first_trigger;
3585 			bool should_change= true;
3586 
3587 			active_triggers= get_active_trigger_count_and_states(player_index,
3588 				player_weapons->current_weapon, 0l, &first_trigger, NULL);
3589 
3590 			for(which_trigger= first_trigger; which_trigger<active_triggers; ++which_trigger)
3591 			{
3592 				switch(weapon->triggers[which_trigger].state)
3593 				{
3594 					case _weapon_idle:
3595 					case _weapon_raising:
3596 						break;
3597 
3598 					case _weapon_waiting_to_load:
3599 						{
3600 							struct weapon_definition *definition= get_weapon_definition(player_weapons->current_weapon);
3601 
3602 							if(definition->reloading_shape==NONE)
3603 							{
3604 								/* Allow them to change if it is completely offscreen */
3605 								weapon->triggers[_primary_weapon].state= _weapon_lowering;
3606 								weapon->triggers[_primary_weapon].phase= 1;
3607 								weapon->triggers[_primary_weapon].sequence= 0;
3608 
3609 								weapon->triggers[_secondary_weapon].state= _weapon_lowering;
3610 								weapon->triggers[_secondary_weapon].phase= 1;
3611 								weapon->triggers[_secondary_weapon].sequence= 0;
3612 							} else {
3613 								should_change= false;
3614 							}
3615 						}
3616 						break;
3617 
3618 					default:
3619 						should_change= false;
3620 						break;
3621 				}
3622 			}
3623 
3624 			if(should_change)
3625 			{
3626 				lower_weapon(player_index, player_weapons->current_weapon);
3627 			}
3628 		}
3629 	}
3630 	else /* desired==current */
3631 	{
3632 		if(player_weapons->current_weapon!=NONE)
3633 		{
3634 			struct weapon_data *weapon= get_player_current_weapon(player_index);
3635 			short active_triggers, which_trigger, first_trigger;
3636 			bool should_change= true;
3637 
3638 			active_triggers= get_active_trigger_count_and_states(player_index,
3639 				player_weapons->current_weapon, 0l, &first_trigger, NULL);
3640 
3641 			for(which_trigger= first_trigger; which_trigger<active_triggers; ++which_trigger)
3642 			{
3643 				switch(weapon->triggers[which_trigger].state)
3644 				{
3645 					case _weapon_lowering:
3646 						break;
3647 
3648 					default:
3649 						should_change= false;
3650 						break;
3651 				}
3652 			}
3653 
3654 			/* They switched back to this weapon... */
3655 			if(should_change)
3656 			{
3657 				raise_weapon(player_index, player_weapons->current_weapon);
3658 			} else {
3659 				struct weapon_definition *definition= get_current_weapon_definition(player_index);
3660 
3661 				/* Check for double weapon activation... */
3662 				if(definition->weapon_class==_twofisted_pistol_class ||
3663 					definition->weapon_class==_melee_class)
3664 				{
3665 					if(WEAPON_WANTS_TWOFIST(weapon))
3666 					{
3667 						should_change= true;
3668 
3669 						/* Start raising the other one.. */
3670 						for(which_trigger= first_trigger; which_trigger<active_triggers; ++which_trigger)
3671 						{
3672 							switch(weapon->triggers[which_trigger].state)
3673 							{
3674 								case _weapon_idle:
3675 									break;
3676 
3677 								default:
3678 									should_change= false;
3679 									break;
3680 							}
3681 						}
3682 
3683 						if(should_change)
3684 						{
3685 							short moving_weapon, raising_weapon;
3686 
3687 							if(!PRIMARY_WEAPON_IS_VALID(weapon))
3688 							{
3689 								/* Raise the primary.. */
3690 								moving_weapon= _secondary_weapon;
3691 								raising_weapon= _primary_weapon;
3692 								SET_PRIMARY_WEAPON_IS_VALID(weapon, true);
3693 								// dprintf("Prim up TF;g");
3694 							} else {
3695 								assert(!SECONDARY_WEAPON_IS_VALID(weapon));
3696 								moving_weapon= _primary_weapon;
3697 								raising_weapon= _secondary_weapon;
3698 								SET_SECONDARY_WEAPON_IS_VALID(weapon, true);
3699 								// dprintf("Second up TF;g");
3700 							}
3701 
3702 							/* Raise the secondary.. */
3703 							weapon->triggers[moving_weapon].state= _weapon_sliding_over_to_second_position;
3704 							weapon->triggers[raising_weapon].state= _weapon_raising;
3705 							weapon->triggers[moving_weapon].phase= definition->ready_ticks;
3706 							weapon->triggers[raising_weapon].phase= definition->ready_ticks;
3707 							SET_WEAPON_WANTS_TWOFIST(weapon, false);
3708 						}
3709 					}
3710 				}
3711 			}
3712 		}
3713 	}
3714 }
3715 
3716 /* We are requesting to raise the second pistol for a twofisted class... */
test_raise_double_weapon(short player_index,uint32 * action_flags)3717 static void test_raise_double_weapon(
3718 	short player_index,
3719 	uint32 *action_flags)
3720 {
3721 	struct weapon_definition *definition= get_current_weapon_definition(player_index);
3722 	struct player_data *player= get_player_data(player_index);
3723 
3724 	if(definition->weapon_class==_twofisted_pistol_class || (definition->weapon_class==_melee_class && !(definition->flags & _weapon_is_marathon_1)))
3725 	{
3726 		struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
3727 
3728 		/* Don't switch if it isn't hte current & the desired weapon.. */
3729 		if(player_weapons->desired_weapon==player_weapons->current_weapon)
3730 		{
3731 			struct weapon_data *weapon= get_player_current_weapon(player_index);
3732 
3733 			/* Only raise if they have more than one, and both aren't up.. */
3734 			if(player->items[definition->item_type]>1)
3735 			{
3736 				if (((*action_flags) & _left_trigger_state) && !PRIMARY_WEAPON_IS_VALID(weapon))
3737 				{
3738 					struct player_data *player= get_player_data(player_index);
3739 					struct trigger_definition *trigger_definition=
3740 						get_player_trigger_definition(player_index, _primary_weapon);
3741 
3742 					assert(SECONDARY_WEAPON_IS_VALID(weapon));
3743 
3744 					/* Try to raise the secondary weapon.. */
3745 					if(weapon->triggers[_primary_weapon].rounds_loaded ||
3746 						trigger_definition->ammunition_type==NONE ||
3747 						player->items[trigger_definition->ammunition_type]>0)
3748 					{
3749 						//dprintf("1 twofist;g");
3750 						SET_WEAPON_WANTS_TWOFIST(weapon, true);
3751 						(*action_flags) &= ~_left_trigger_state;
3752 					}
3753 				}
3754 				else if (((*action_flags) & _right_trigger_state) && !SECONDARY_WEAPON_IS_VALID(weapon))
3755 				{
3756 					struct player_data *player= get_player_data(player_index);
3757 					struct trigger_definition *trigger_definition=
3758 						get_player_trigger_definition(player_index, _secondary_weapon);
3759 
3760 					assert(PRIMARY_WEAPON_IS_VALID(weapon));
3761 
3762 					/* Try to raise the primary weapon.. */
3763 					if(weapon->triggers[_secondary_weapon].rounds_loaded ||
3764 						trigger_definition->ammunition_type==NONE ||
3765 						player->items[trigger_definition->ammunition_type]>0)
3766 					{
3767 						//dprintf("2 twofist;g");
3768 						SET_WEAPON_WANTS_TWOFIST(weapon, true);
3769 						(*action_flags) &= ~_right_trigger_state;
3770 					}
3771 				}
3772 			}
3773 		}
3774 	}
3775 }
3776 
change_to_desired_weapon(short player_index)3777 static void change_to_desired_weapon(
3778 	short player_index)
3779 {
3780 	struct player_weapon_data *player_weapons= get_player_weapon_data(player_index);
3781 	struct weapon_definition *definition= get_weapon_definition(player_weapons->desired_weapon);
3782 	short first_trigger = _primary_weapon, which_trigger, trigger_count = 1;
3783 
3784 	// dprintf("Changing!");
3785 	assert(player_weapons->desired_weapon != player_weapons->current_weapon);
3786 
3787 	/* Reset this weapons flags */
3788 	if(player_weapons->current_weapon!=NONE)
3789 	{
3790 		player_weapons->weapons[player_weapons->current_weapon].flags= 0;
3791 	}
3792 
3793 	/* Reset the desired weapon flags. */
3794 	player_weapons->weapons[player_weapons->desired_weapon].flags= 0;
3795 
3796 	/* Set the desired weapon. */
3797 	player_weapons->current_weapon= player_weapons->desired_weapon;
3798 
3799 	/* How many triggers do I need to update? */
3800 	switch(definition->weapon_class)
3801 	{
3802 		case _normal_class:
3803 			first_trigger= _primary_weapon;
3804 			trigger_count= 1;
3805 			break;
3806 
3807 		case _multipurpose_class:
3808 		case _dual_function_class:
3809 			first_trigger= _primary_weapon;
3810 			trigger_count= 2;
3811 			break;
3812 
3813 		case _melee_class:
3814 		case _twofisted_pistol_class:
3815 			/* We only ever raise one of them. */
3816 			/* If the first one has ammunition, we raise it.  If they have */
3817 			/* two of them, and the first one doesn't have ammunition, then */
3818 			/* we raise the second one. */
3819 			{
3820 				struct player_data *player= get_player_data(player_index);
3821 				if(player->items[definition->item_type]==1)
3822 				{
3823 					/* Only can raise the first one. */
3824 					first_trigger= _primary_weapon;
3825 					trigger_count= 1;
3826 				} else {
3827 					struct trigger_data *trigger= get_trigger_data(player_index,
3828 						player_weapons->desired_weapon, _primary_weapon);
3829 					struct trigger_definition *trigger_definition= get_trigger_definition(player_index,
3830 						player_weapons->desired_weapon, _primary_weapon);
3831 
3832 					/* If it is loaded or we can load it... */
3833 					if(trigger->rounds_loaded || trigger_definition->ammunition_type==NONE ||
3834 						player->items[trigger_definition->ammunition_type]>0)
3835 					{
3836 						first_trigger= _primary_weapon;
3837 						trigger_count= 1;
3838 					// LP change: adding fallback in case this does not succeed
3839 					} else if (get_trigger_data(player_index, player_weapons->desired_weapon, _secondary_weapon)->rounds_loaded) {
3840 						// assert(get_trigger_data(player_index, player_weapons->desired_weapon, _secondary_weapon)->rounds_loaded);
3841 						first_trigger= _secondary_weapon;
3842 						trigger_count= 2;
3843 					} else
3844 					{
3845 						first_trigger = _primary_weapon;
3846 						trigger_count = 2;
3847 					}
3848 				}
3849 			}
3850 			break;
3851 
3852 		// LP change: no weapon
3853 		case NONE:
3854 		default:
3855 			break;
3856 	}
3857 
3858 	/* Essentially the same as raise weapon, but it is always a full sequence */
3859 	for(which_trigger= first_trigger; which_trigger<trigger_count; ++which_trigger)
3860 	{
3861 		struct trigger_data *trigger= get_trigger_data(player_index, player_weapons->desired_weapon, which_trigger);
3862 
3863 		trigger->phase= definition->ready_ticks;
3864 		trigger->state= _weapon_raising;
3865 
3866 		if(which_trigger==_primary_weapon)
3867 		{
3868 			SET_PRIMARY_WEAPON_IS_VALID(&player_weapons->weapons[player_weapons->desired_weapon], true);
3869 		} else {
3870 			SET_SECONDARY_WEAPON_IS_VALID(&player_weapons->weapons[player_weapons->desired_weapon], true);
3871 		}
3872 
3873 		/* if it has no ammunition, load it- only if it has an offscreen reload. */
3874 		if(!trigger->rounds_loaded && definition->reloading_shape==NONE)
3875 		{
3876 			struct trigger_definition *trigger_definition=
3877 				get_trigger_definition(player_index, player_weapons->current_weapon, which_trigger);
3878 			struct player_data *player= get_player_data(player_index);
3879 
3880 			if(player->items[trigger_definition->ammunition_type] > 0)
3881 			{
3882 				put_rounds_into_weapon(player_index, player_weapons->current_weapon, which_trigger);
3883 			}
3884 		}
3885 	}
3886 }
3887 
automatic_still_firing(short player_index,short which_trigger)3888 static bool automatic_still_firing(
3889 	short player_index,
3890 	short which_trigger)
3891 {
3892 	bool still_firing= false;
3893 	struct weapon_data *weapon= get_player_current_weapon(player_index);
3894 	struct weapon_definition *definition= get_weapon_definition(weapon->weapon_type);
3895 
3896 	if(which_trigger==_primary_weapon ||
3897 		(which_trigger==_secondary_weapon && (definition->flags & _weapon_secondary_has_angular_flipping)))
3898 	{
3899 		assert(weapon->triggers[which_trigger].state==_weapon_idle);
3900 		if(definition->flags & _weapon_is_automatic)
3901 		{
3902 			if(TRIGGER_IS_DOWN(weapon) && weapon->triggers[which_trigger].ticks_since_last_shot<AUTOMATIC_STILL_FIRING_DURATION)
3903 			{
3904 				still_firing= true;
3905 			}
3906 		}
3907 	}
3908 
3909 	return still_firing;
3910 }
3911 
play_shell_casing_sound(short player_index,short sound_index)3912 static void	play_shell_casing_sound(
3913 	short player_index,
3914 	short sound_index)
3915 {
3916 	struct player_data *player= get_player_data(player_index);
3917 
3918 	if (!(player->variables.flags&_FEET_BELOW_MEDIA_BIT))
3919 	{
3920 		struct world_location3d location;
3921 
3922 		location.point= player->camera_location;
3923 		location.polygon_index= player->camera_polygon_index;
3924 		location.yaw= location.pitch= 0;
3925 		location.velocity.i= location.velocity.j= location.velocity.k= 0;
3926 
3927 		SoundManager::instance()->PlaySound(sound_index, &location, NONE);
3928 	}
3929 }
3930 
find_weapon_power_index(short weapon_type)3931 static short find_weapon_power_index(
3932 	short weapon_type)
3933 {
3934 	if(weapon_type==NONE)
3935 		return NONE;
3936 	else {
3937 		unsigned index;
3938 		for (index=0; index<NUMBER_OF_WEAPONS; ++index) {
3939 			if (weapon_type == weapon_ordering_array[index])
3940 				break;
3941 		}
3942 		assert(index != NUMBER_OF_WEAPONS);
3943 		return index;
3944 	}
3945 }
3946 
3947 /* ---------- shell casing stuff */
3948 
initialize_shell_casings(short player_index)3949 static void initialize_shell_casings(
3950 	short player_index)
3951 {
3952 	short shell_casing_index;
3953 	struct shell_casing_data *shell_casing;
3954 
3955 	for (shell_casing_index= 0, shell_casing= get_player_weapon_data(player_index)->shell_casings; shell_casing_index<MAXIMUM_SHELL_CASINGS; ++shell_casing_index, ++shell_casing)
3956 	{
3957 		MARK_SLOT_AS_FREE(shell_casing);
3958 	}
3959 }
3960 
new_shell_casing(short player_index,short type,uint16 flags)3961 static short new_shell_casing(
3962 	short player_index,
3963 	short type,
3964 	uint16 flags)
3965 {
3966 	short shell_casing_index;
3967 	struct shell_casing_data *shell_casing;
3968 
3969 	for (shell_casing_index= 0, shell_casing= get_player_weapon_data(player_index)->shell_casings; shell_casing_index<MAXIMUM_SHELL_CASINGS; ++shell_casing_index, ++shell_casing)
3970 	{
3971 		if (SLOT_IS_FREE(shell_casing)) break;
3972 	}
3973 
3974 	if (shell_casing_index==MAXIMUM_SHELL_CASINGS)
3975 	{
3976 		shell_casing_index= NONE;
3977 	}
3978 	else
3979 	{
3980 		struct shell_casing_definition *definition= get_shell_casing_definition(type);
3981 
3982 		shell_casing->type= type;
3983 		shell_casing->flags= flags;
3984 		shell_casing->x= definition->x0, shell_casing->y= definition->y0;
3985 		shell_casing->vx= SHELL_CASING_IS_REVERSED(shell_casing) ? -definition->vx0 : definition->vx0, shell_casing->vy= definition->vy0;
3986 
3987 		shell_casing->frame= local_random()&7;
3988 		shell_casing->x+= ((local_random()&0xff)*shell_casing->vx)>>9;
3989 		shell_casing->y+= ((local_random()&0xff)*shell_casing->vy)>>9;
3990 
3991 		MARK_SLOT_AS_USED(shell_casing);
3992 	}
3993 
3994 	return shell_casing_index;
3995 }
3996 
update_shell_casings(short player_index)3997 static void update_shell_casings(
3998 	short player_index)
3999 {
4000 	short shell_casing_index;
4001 	struct shell_casing_data *shell_casing;
4002 
4003 	for (shell_casing_index= 0, shell_casing= get_player_weapon_data(player_index)->shell_casings; shell_casing_index<MAXIMUM_SHELL_CASINGS; ++shell_casing_index, ++shell_casing)
4004 	{
4005 		if (SLOT_IS_USED(shell_casing))
4006 		{
4007 			struct shell_casing_definition *definition= get_shell_casing_definition(shell_casing->type);
4008 
4009 			shell_casing->x+= shell_casing->vx;
4010 			shell_casing->y+= shell_casing->vy;
4011 			shell_casing->vx+= SHELL_CASING_IS_REVERSED(shell_casing) ? -definition->dvx : definition->dvx;
4012 			shell_casing->vy+= definition->dvy;
4013 
4014 			if (shell_casing->x>=FIXED_ONE || shell_casing->x<0)
4015 			{
4016 				MARK_SLOT_AS_FREE(shell_casing);
4017 			}
4018 		}
4019 	}
4020 }
4021 
get_shell_casing_display_data(struct weapon_display_information * display,short index)4022 static bool get_shell_casing_display_data(
4023 	struct weapon_display_information *display,
4024 	short index)
4025 {
4026 	bool valid= false;
4027 	short shell_casing_index;
4028 	struct shell_casing_data *shell_casing;
4029 
4030 	for (shell_casing_index= 0, shell_casing= get_player_weapon_data(current_player_index)->shell_casings; shell_casing_index<MAXIMUM_SHELL_CASINGS; ++shell_casing_index, ++shell_casing)
4031 	{
4032 		if (SLOT_IS_USED(shell_casing))
4033 		{
4034 			if ((index-= 1)<0)
4035 			{
4036 				if (display)
4037 				{
4038 					struct shell_casing_definition *definition= get_shell_casing_definition(shell_casing->type);
4039 					struct shape_animation_data *high_level_data=
4040 						get_shape_animation_data(BUILD_DESCRIPTOR(definition->collection, definition->shape));
4041 					// Skip over if the sequence is nonexistent
4042 					if(!high_level_data) continue;
4043 
4044 					// animate it
4045 					if ((shell_casing->frame+= 1)>=high_level_data->frames_per_view) shell_casing->frame= 0;
4046 
4047 					display->collection= definition->collection;
4048 					display->shape_index = definition->shape;
4049 					display->low_level_shape_index= high_level_data->low_level_shape_indexes[shell_casing->frame];
4050 					display->flip_horizontal= display->flip_vertical= false;
4051 					display->vertical_positioning_mode= display->horizontal_positioning_mode= _position_center;
4052 					display->vertical_position= FIXED_ONE-shell_casing->y, display->horizontal_position= shell_casing->x;
4053 					display->transfer_mode= _xfer_normal, display->transfer_phase= 0;
4054 
4055 
4056 					// LP: model animation data
4057 					display->Frame = shell_casing->frame;
4058 					display->NextFrame = display->Frame + 1;
4059 					if (display->NextFrame >= high_level_data->frames_per_view)
4060 						display->NextFrame = 0;
4061 					// Apparently one frame per engine tick
4062 					display->Phase = 0;
4063 					display->Ticks = 1;
4064 
4065 				}
4066 
4067 				valid= true;
4068 				break;
4069 			}
4070 		}
4071 	}
4072 
4073 	return valid;
4074 }
4075 
4076 
StreamToTrigData(uint8 * & S,trigger_data & Object)4077 inline void StreamToTrigData(uint8* &S, trigger_data& Object)
4078 {
4079 	StreamToValue(S,Object.state);
4080 	StreamToValue(S,Object.phase);
4081 	StreamToValue(S,Object.rounds_loaded);
4082 	StreamToValue(S,Object.shots_fired);
4083 	StreamToValue(S,Object.shots_hit);
4084 	StreamToValue(S,Object.ticks_since_last_shot);
4085 	StreamToValue(S,Object.ticks_firing);
4086 	StreamToValue(S,Object.sequence);
4087 }
4088 
TrigDataToStream(uint8 * & S,trigger_data & Object)4089 inline void TrigDataToStream(uint8* &S, trigger_data& Object)
4090 {
4091 	ValueToStream(S,Object.state);
4092 	ValueToStream(S,Object.phase);
4093 	ValueToStream(S,Object.rounds_loaded);
4094 	ValueToStream(S,Object.shots_fired);
4095 	ValueToStream(S,Object.shots_hit);
4096 	ValueToStream(S,Object.ticks_since_last_shot);
4097 	ValueToStream(S,Object.ticks_firing);
4098 	ValueToStream(S,Object.sequence);
4099 }
4100 
4101 
StreamToWeapData(uint8 * & S,weapon_data & Object)4102 inline void StreamToWeapData(uint8* &S, weapon_data& Object)
4103 {
4104 	StreamToValue(S,Object.weapon_type);
4105 	StreamToValue(S,Object.flags);
4106 	StreamToValue(S,Object.unused);
4107 	for (int k=0; k<NUMBER_OF_TRIGGERS; k++)
4108 		StreamToTrigData(S,Object.triggers[k]);
4109 }
4110 
WeapDataToStream(uint8 * & S,weapon_data & Object)4111 inline void WeapDataToStream(uint8* &S, weapon_data& Object)
4112 {
4113 	ValueToStream(S,Object.weapon_type);
4114 	ValueToStream(S,Object.flags);
4115 	ValueToStream(S,Object.unused);
4116 	for (int k=0; k<NUMBER_OF_TRIGGERS; k++)
4117 		TrigDataToStream(S,Object.triggers[k]);
4118 }
4119 
4120 
StreamToShellData(uint8 * & S,shell_casing_data & Object)4121 inline void StreamToShellData(uint8* &S, shell_casing_data& Object)
4122 {
4123 	StreamToValue(S,Object.type);
4124 	StreamToValue(S,Object.frame);
4125 
4126 	StreamToValue(S,Object.flags);
4127 
4128 	StreamToValue(S,Object.x);
4129 	StreamToValue(S,Object.y);
4130 	StreamToValue(S,Object.vx);
4131 	StreamToValue(S,Object.vy);
4132 }
4133 
ShellDataToStream(uint8 * & S,shell_casing_data & Object)4134 inline void ShellDataToStream(uint8* &S, shell_casing_data& Object)
4135 {
4136 	ValueToStream(S,Object.type);
4137 	ValueToStream(S,Object.frame);
4138 
4139 	ValueToStream(S,Object.flags);
4140 
4141 	ValueToStream(S,Object.x);
4142 	ValueToStream(S,Object.y);
4143 	ValueToStream(S,Object.vx);
4144 	ValueToStream(S,Object.vy);
4145 }
4146 
4147 
unpack_player_weapon_data(uint8 * Stream,size_t Count)4148 uint8 *unpack_player_weapon_data(uint8 *Stream, size_t Count)
4149 {
4150 	uint8* S = Stream;
4151 	player_weapon_data* ObjPtr = player_weapons_array;
4152 
4153 	for (size_t k = 0; k < Count; k++, ObjPtr++)
4154 	{
4155 		StreamToValue(S,ObjPtr->current_weapon);
4156 		StreamToValue(S,ObjPtr->desired_weapon);
4157 		for (unsigned m=0; m<NUMBER_OF_WEAPONS; m++)
4158 			StreamToWeapData(S,ObjPtr->weapons[m]);
4159 		for (unsigned m=0; m<MAXIMUM_SHELL_CASINGS; m++)
4160 			StreamToShellData(S,ObjPtr->shell_casings[m]);
4161 	}
4162 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_player_weapon_data));
4163 	return S;
4164 }
4165 
pack_player_weapon_data(uint8 * Stream,size_t Count)4166 uint8 *pack_player_weapon_data(uint8 *Stream, size_t Count)
4167 {
4168 	uint8* S = Stream;
4169 	player_weapon_data* ObjPtr = player_weapons_array;
4170 
4171 	for (size_t k = 0; k < Count; k++, ObjPtr++)
4172 	{
4173 		ValueToStream(S,ObjPtr->current_weapon);
4174 		ValueToStream(S,ObjPtr->desired_weapon);
4175 		for (size_t m=0; m<NUMBER_OF_WEAPONS; m++)
4176 			WeapDataToStream(S,ObjPtr->weapons[m]);
4177 		for (size_t m=0; m<MAXIMUM_SHELL_CASINGS; m++)
4178 			ShellDataToStream(S,ObjPtr->shell_casings[m]);
4179 	}
4180 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_player_weapon_data));
4181 	return S;
4182 }
4183 
StreamToTrigDefData(uint8 * & S,trigger_definition & Object)4184 inline void StreamToTrigDefData(uint8* &S, trigger_definition& Object)
4185 {
4186 	StreamToValue(S,Object.rounds_per_magazine);
4187 	StreamToValue(S,Object.ammunition_type);
4188 	StreamToValue(S,Object.ticks_per_round);
4189 	StreamToValue(S,Object.recovery_ticks);
4190 	StreamToValue(S,Object.charging_ticks);
4191 	StreamToValue(S,Object.recoil_magnitude);
4192 	StreamToValue(S,Object.firing_sound);
4193 	StreamToValue(S,Object.click_sound);
4194 	StreamToValue(S,Object.charging_sound);
4195 	StreamToValue(S,Object.shell_casing_sound);
4196 	StreamToValue(S,Object.reloading_sound);
4197 	StreamToValue(S,Object.charged_sound);
4198 	StreamToValue(S,Object.projectile_type);
4199 	StreamToValue(S,Object.theta_error);
4200 	StreamToValue(S,Object.dx);
4201 	StreamToValue(S,Object.dz);
4202 	StreamToValue(S,Object.shell_casing_type);
4203 	StreamToValue(S,Object.burst_count);
4204 	Object.sound_activation_range = 0;
4205 }
4206 
TrigDefDataToStream(uint8 * & S,trigger_definition & Object)4207 inline void TrigDefDataToStream(uint8* &S, trigger_definition& Object)
4208 {
4209 	ValueToStream(S,Object.rounds_per_magazine);
4210 	ValueToStream(S,Object.ammunition_type);
4211 	ValueToStream(S,Object.ticks_per_round);
4212 	ValueToStream(S,Object.recovery_ticks);
4213 	ValueToStream(S,Object.charging_ticks);
4214 	ValueToStream(S,Object.recoil_magnitude);
4215 	ValueToStream(S,Object.firing_sound);
4216 	ValueToStream(S,Object.click_sound);
4217 	ValueToStream(S,Object.charging_sound);
4218 	ValueToStream(S,Object.shell_casing_sound);
4219 	ValueToStream(S,Object.reloading_sound);
4220 	ValueToStream(S,Object.charged_sound);
4221 	ValueToStream(S,Object.projectile_type);
4222 	ValueToStream(S,Object.theta_error);
4223 	ValueToStream(S,Object.dx);
4224 	ValueToStream(S,Object.dz);
4225 	ValueToStream(S,Object.shell_casing_type);
4226 	ValueToStream(S,Object.burst_count);
4227 }
4228 
4229 
unpack_weapon_definition(uint8 * Stream,size_t Count)4230 uint8 *unpack_weapon_definition(uint8 *Stream, size_t Count)
4231 {
4232 	return unpack_weapon_definition(Stream,weapon_definitions,Count);
4233 }
4234 
unpack_weapon_definition(uint8 * Stream,weapon_definition * Objects,size_t Count)4235 uint8 *unpack_weapon_definition(uint8 *Stream, weapon_definition *Objects, size_t Count)
4236 {
4237 	uint8* S = Stream;
4238 	weapon_definition* ObjPtr = Objects;
4239 
4240 	for (size_t k = 0; k < Count; k++, ObjPtr++)
4241 	{
4242 		StreamToValue(S,ObjPtr->item_type);
4243 		StreamToValue(S,ObjPtr->powerup_type);
4244 		StreamToValue(S,ObjPtr->weapon_class);
4245 		StreamToValue(S,ObjPtr->flags);
4246 
4247 		StreamToValue(S,ObjPtr->firing_light_intensity);
4248 		StreamToValue(S,ObjPtr->firing_intensity_decay_ticks);
4249 
4250 		StreamToValue(S,ObjPtr->idle_height);
4251 		StreamToValue(S,ObjPtr->bob_amplitude);
4252 		StreamToValue(S,ObjPtr->kick_height);
4253 		StreamToValue(S,ObjPtr->reload_height);
4254 		StreamToValue(S,ObjPtr->idle_width);
4255 		StreamToValue(S,ObjPtr->horizontal_amplitude);
4256 
4257 		StreamToValue(S,ObjPtr->collection);
4258 		StreamToValue(S,ObjPtr->idle_shape);
4259 		StreamToValue(S,ObjPtr->firing_shape);
4260 		StreamToValue(S,ObjPtr->reloading_shape);
4261 		StreamToValue(S,ObjPtr->unused);
4262 		StreamToValue(S,ObjPtr->charging_shape);
4263 		StreamToValue(S,ObjPtr->charged_shape);
4264 
4265 		StreamToValue(S,ObjPtr->ready_ticks);
4266 		StreamToValue(S,ObjPtr->await_reload_ticks);
4267 		StreamToValue(S,ObjPtr->loading_ticks);
4268 		StreamToValue(S,ObjPtr->finish_loading_ticks);
4269 		StreamToValue(S,ObjPtr->powerup_ticks);
4270 
4271 		for (int m=0; m<NUMBER_OF_TRIGGERS; m++)
4272 			StreamToTrigDefData(S,ObjPtr->weapons_by_trigger[m]);
4273 	}
4274 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_weapon_definition));
4275 	return S;
4276 }
4277 
unpack_m1_weapon_definition(uint8 * Stream,size_t Count)4278 uint8* unpack_m1_weapon_definition(uint8* Stream, size_t Count)
4279 {
4280 	uint8* S = Stream;
4281 	weapon_definition* ObjPtr = weapon_definitions;
4282 
4283 	for (size_t k = 0; k < Count; k++, ObjPtr++)
4284 	{
4285 		StreamToValue(S,ObjPtr->item_type);
4286 		ObjPtr->powerup_type = NONE;
4287 		StreamToValue(S,ObjPtr->weapon_class);
4288 		StreamToValue(S,ObjPtr->flags);
4289 
4290 		trigger_definition& Trigger0 = ObjPtr->weapons_by_trigger[0];
4291 		trigger_definition& Trigger1 = ObjPtr->weapons_by_trigger[1];
4292 
4293 		StreamToValue(S, Trigger0.ammunition_type);
4294 		StreamToValue(S, Trigger0.rounds_per_magazine);
4295 		StreamToValue(S, Trigger1.ammunition_type);
4296 		StreamToValue(S, Trigger1.rounds_per_magazine);
4297 
4298 		StreamToValue(S,ObjPtr->firing_light_intensity);
4299 		StreamToValue(S,ObjPtr->firing_intensity_decay_ticks);
4300 
4301 		StreamToValue(S,ObjPtr->idle_height);
4302 		StreamToValue(S,ObjPtr->bob_amplitude);
4303 		StreamToValue(S,ObjPtr->kick_height);
4304 		StreamToValue(S,ObjPtr->reload_height);
4305 		StreamToValue(S,ObjPtr->idle_width);
4306 		StreamToValue(S,ObjPtr->horizontal_amplitude);
4307 
4308 		StreamToValue(S,ObjPtr->collection);
4309 		StreamToValue(S,ObjPtr->idle_shape);
4310 		StreamToValue(S,ObjPtr->firing_shape);
4311 		StreamToValue(S,ObjPtr->reloading_shape);
4312 		StreamToValue(S, ObjPtr->unused);
4313 		StreamToValue(S,ObjPtr->charging_shape);
4314 		StreamToValue(S,ObjPtr->charged_shape);
4315 
4316 		StreamToValue(S, Trigger0.ticks_per_round);
4317 		StreamToValue(S, Trigger1.ticks_per_round);
4318 
4319 		StreamToValue(S,ObjPtr->await_reload_ticks);
4320 		StreamToValue(S,ObjPtr->ready_ticks);
4321 		ObjPtr->loading_ticks = 0;
4322 		ObjPtr->finish_loading_ticks = 0;
4323 
4324 		StreamToValue(S, Trigger0.recovery_ticks);
4325 		StreamToValue(S, Trigger1.recovery_ticks);
4326 		StreamToValue(S, Trigger0.charging_ticks);
4327 		StreamToValue(S, Trigger1.charging_ticks);
4328 
4329 		StreamToValue(S, Trigger0.recoil_magnitude);
4330 		StreamToValue(S, Trigger1.recoil_magnitude);
4331 
4332 		StreamToValue(S, Trigger0.firing_sound);
4333 		StreamToValue(S, Trigger1.firing_sound);
4334 		StreamToValue(S, Trigger0.click_sound);
4335 		StreamToValue(S, Trigger1.click_sound);
4336 
4337 		StreamToValue(S, Trigger0.reloading_sound);
4338 		Trigger1.reloading_sound = NONE;
4339 
4340 		StreamToValue(S, Trigger0.charging_sound);
4341 		Trigger1.charging_sound = Trigger0.charging_sound;
4342 
4343 		StreamToValue(S, Trigger0.shell_casing_sound);
4344 		StreamToValue(S, Trigger1.shell_casing_sound);
4345 
4346 		StreamToValue(S, Trigger0.sound_activation_range);
4347 		StreamToValue(S, Trigger1.sound_activation_range);
4348 
4349 		StreamToValue(S, Trigger0.projectile_type);
4350 		StreamToValue(S, Trigger1.projectile_type);
4351 
4352 		StreamToValue(S, Trigger0.theta_error);
4353 		StreamToValue(S, Trigger1.theta_error);
4354 
4355 		StreamToValue(S, Trigger0.dx);
4356 		StreamToValue(S, Trigger0.dz);
4357 		StreamToValue(S, Trigger1.dx);
4358 		StreamToValue(S, Trigger1.dz);
4359 
4360 		StreamToValue(S, Trigger0.burst_count);
4361 		StreamToValue(S, Trigger1.burst_count);
4362 
4363 		S += 2; // instant reload tick
4364 
4365 		Trigger0.charged_sound = NONE;
4366 		Trigger1.charged_sound = NONE;
4367 		Trigger0.shell_casing_type = NONE;
4368 		Trigger1.shell_casing_type = NONE;
4369 
4370 		if (ObjPtr->flags & _weapon_disappears_after_use_m1) {
4371 			ObjPtr->flags |= _weapon_disappears_after_use;
4372 			ObjPtr->flags &= ~_weapon_disappears_after_use_m1;
4373 		}
4374 
4375 		if (ObjPtr->weapon_class == _twofisted_pistol_class)
4376 		{
4377 			// Marathon's settings for trigger 1 are mostly empty
4378 			ObjPtr->flags |= _weapon_fires_out_of_phase;
4379 			int16 dx = Trigger1.dx;
4380 			int16 dz = Trigger1.dz;
4381 			Trigger1 = Trigger0;
4382 			Trigger1.dx = dx;
4383 			Trigger1.dz = dz;
4384 		}
4385 		else if (ObjPtr->weapon_class == _dual_function_class)
4386 		{
4387 			// triggers share ammo must have been
4388 			// hard-coded for dual function weapons in
4389 			// Marathon; also, Marathon 2 expects rounds
4390 			// per magazine and ammunition type to match
4391 			ObjPtr->flags |= _weapon_triggers_share_ammo;
4392 			Trigger1.rounds_per_magazine = Trigger0.rounds_per_magazine;
4393 			Trigger1.ammunition_type = Trigger0.ammunition_type;
4394 
4395 		}
4396 
4397 		// automatic weapons in Marathon flutter while firing
4398 		if (ObjPtr->flags & _weapon_is_automatic)
4399 		{
4400 			ObjPtr->flags |= _weapon_flutters_while_firing;
4401 		}
4402 
4403 		// this makes the TOZT render correctly, but we don't
4404 		// want it to flutter so apply after the above statement
4405 		if (Trigger0.recovery_ticks == 0)
4406 		{
4407 			ObjPtr->flags |= _weapon_is_automatic;
4408 		}
4409 
4410 		// SPNKR doesn't have a firing shape, just use idle
4411 		if (ObjPtr->firing_shape == NONE)
4412 		{
4413 			ObjPtr->firing_shape = ObjPtr->idle_shape;
4414 		}
4415 
4416 		if (k == _weapon_alien_shotgun) {
4417 			// is there a better way?
4418 			ObjPtr->flags |= _weapon_has_random_ammo_on_pickup;
4419 		}
4420 
4421 		ObjPtr->flags |= _weapon_is_marathon_1;
4422 	}
4423 	return S;
4424 }
4425 
4426 
pack_weapon_definition(uint8 * Stream,size_t Count)4427 uint8 *pack_weapon_definition(uint8 *Stream, size_t Count)
4428 {
4429 	return pack_weapon_definition(Stream,weapon_definitions,Count);
4430 }
4431 
pack_weapon_definition(uint8 * Stream,weapon_definition * Objects,size_t Count)4432 uint8 *pack_weapon_definition(uint8 *Stream, weapon_definition *Objects, size_t Count)
4433 {
4434 	uint8* S = Stream;
4435 	weapon_definition* ObjPtr = Objects;
4436 
4437 	for (size_t k = 0; k < Count; k++, ObjPtr++)
4438 	{
4439 		ValueToStream(S,ObjPtr->item_type);
4440 		ValueToStream(S,ObjPtr->powerup_type);
4441 		ValueToStream(S,ObjPtr->weapon_class);
4442 		ValueToStream(S,ObjPtr->flags);
4443 
4444 		ValueToStream(S,ObjPtr->firing_light_intensity);
4445 		ValueToStream(S,ObjPtr->firing_intensity_decay_ticks);
4446 
4447 		ValueToStream(S,ObjPtr->idle_height);
4448 		ValueToStream(S,ObjPtr->bob_amplitude);
4449 		ValueToStream(S,ObjPtr->kick_height);
4450 		ValueToStream(S,ObjPtr->reload_height);
4451 		ValueToStream(S,ObjPtr->idle_width);
4452 		ValueToStream(S,ObjPtr->horizontal_amplitude);
4453 
4454 		ValueToStream(S,ObjPtr->collection);
4455 		ValueToStream(S,ObjPtr->idle_shape);
4456 		ValueToStream(S,ObjPtr->firing_shape);
4457 		ValueToStream(S,ObjPtr->reloading_shape);
4458 		ValueToStream(S,ObjPtr->unused);
4459 		ValueToStream(S,ObjPtr->charging_shape);
4460 		ValueToStream(S,ObjPtr->charged_shape);
4461 
4462 		ValueToStream(S,ObjPtr->ready_ticks);
4463 		ValueToStream(S,ObjPtr->await_reload_ticks);
4464 		ValueToStream(S,ObjPtr->loading_ticks);
4465 		ValueToStream(S,ObjPtr->finish_loading_ticks);
4466 		ValueToStream(S,ObjPtr->powerup_ticks);
4467 
4468 		for (int m=0; m<NUMBER_OF_TRIGGERS; m++)
4469 			TrigDefDataToStream(S,ObjPtr->weapons_by_trigger[m]);
4470 	}
4471 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_weapon_definition));
4472 	return S;
4473 }
4474 
init_weapon_definitions()4475 void init_weapon_definitions()
4476 {
4477 	memcpy(weapon_definitions, original_weapon_definitions, sizeof(weapon_definitions));
4478 }
4479 
4480 // LP additions: get weapon-definition size and number of weapon types
get_number_of_weapon_types()4481 size_t get_number_of_weapon_types() {return NUMBER_OF_WEAPONS;}
4482 
4483 
4484 struct shell_casing_definition *original_shell_casing_definitions = NULL;
4485 int16 *original_weapon_ordering_array = NULL;
4486 
reset_mml_weapons()4487 void reset_mml_weapons()
4488 {
4489 	if (original_shell_casing_definitions) {
4490 		for (unsigned i = 0; i < NUMBER_OF_SHELL_CASING_TYPES; i++)
4491 			shell_casing_definitions[i] = original_shell_casing_definitions[i];
4492 		free(original_shell_casing_definitions);
4493 		original_shell_casing_definitions = NULL;
4494 	}
4495 
4496 	if (original_weapon_ordering_array) {
4497 		for (unsigned i = 0; i < NUMBER_OF_WEAPONS; i++)
4498 			weapon_ordering_array[i] = original_weapon_ordering_array[i];
4499 		free(original_weapon_ordering_array);
4500 		original_weapon_ordering_array = NULL;
4501 	}
4502 }
4503 
parse_mml_weapons(const InfoTree & root)4504 void parse_mml_weapons(const InfoTree& root)
4505 {
4506 	// back up old values first
4507 	if (!original_shell_casing_definitions) {
4508 		original_shell_casing_definitions = (struct shell_casing_definition *) malloc(sizeof(struct shell_casing_definition) * NUMBER_OF_SHELL_CASING_TYPES);
4509 		assert(original_shell_casing_definitions);
4510 		for (unsigned i = 0; i < NUMBER_OF_SHELL_CASING_TYPES; i++)
4511 			original_shell_casing_definitions[i] = shell_casing_definitions[i];
4512 	}
4513 
4514 	if (!original_weapon_ordering_array) {
4515 		original_weapon_ordering_array = (int16 *) malloc(sizeof(int16) * NUMBER_OF_WEAPONS);
4516 		assert(original_weapon_ordering_array);
4517 		for (unsigned i = 0; i < NUMBER_OF_WEAPONS; i++)
4518 			original_weapon_ordering_array[i] = weapon_ordering_array[i];
4519 	}
4520 
4521 	BOOST_FOREACH(InfoTree casing, root.children_named("shell_casings"))
4522 	{
4523 		int16 index;
4524 		if (!casing.read_indexed("index", index, NUMBER_OF_SHELL_CASING_TYPES))
4525 			continue;
4526 		shell_casing_definition& def = shell_casing_definitions[index];
4527 
4528 		casing.read_indexed("coll", def.collection, MAXIMUM_COLLECTIONS);
4529 		casing.read_indexed("seq", def.shape, MAXIMUM_SHAPES_PER_COLLECTION);
4530 		casing.read_fixed("x0", def.x0);
4531 		casing.read_fixed("y0", def.y0);
4532 		casing.read_fixed("vx0", def.vx0);
4533 		casing.read_fixed("vy0", def.vy0);
4534 		casing.read_fixed("dvx", def.dvx);
4535 		casing.read_fixed("dvy", def.dvy);
4536 	}
4537 
4538 	BOOST_FOREACH(InfoTree order, root.children_named("order"))
4539 	{
4540 		int16 index;
4541 		if (!order.read_indexed("index", index, NUMBER_OF_WEAPONS))
4542 			continue;
4543 		order.read_indexed("weapon", weapon_ordering_array[index], NUMBER_OF_WEAPONS);
4544 	}
4545 }
4546