1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #ifndef __FS2_BEAM_WEAPON_HEADER_FILE
13 #define __FS2_BEAM_WEAPON_HEADER_FILE
14 
15 // ------------------------------------------------------------------------------------------------
16 // BEAM WEAPON DEFINES/VARS
17 //
18 #include "globalincs/globals.h"
19 #include "model/model.h"
20 
21 // prototypes
22 class object;
23 class ship_subsys;
24 struct obj_pair;
25 struct beam_weapon_info;
26 struct vec3d;
27 
28 // beam types
29 #define BEAM_TYPE_A					0				// unidirectional beam
30 #define BEAM_TYPE_B					1				// "slash" in one direction
31 #define BEAM_TYPE_C					2				// targeting lasers (only lasts one frame)
32 #define BEAM_TYPE_D					3				// similar to the type A beams, but takes multiple shots and "chases" fighters around
33 #define BEAM_TYPE_E					4				// stupid beam. like type A, only it doesn't aim. it just shoots directly out of the turret
34 #define BEAM_TYPE_F					5				// SCP type, highly flexible and configurable
35 
36 // max # of "shots" an individual beam will take
37 #define MAX_BEAM_SHOTS				5
38 #define MAX_BEAMS					500
39 
40 // apply damage
41 #define BEAM_DAMAGE_TIME			170
42 
43 // uses to define beam behavior ahead of time - needed for multiplayer
44 typedef struct beam_info {
45 	vec3d			dir_a, dir_b;						// direction vectors for beams
46 	vec3d			rot_axis;
47 	ubyte				shot_count;							// # of shots
48 	float				shot_aim[MAX_BEAM_SHOTS];		// accuracy. this is a constant multiple of radius. anything < 1.0 will guarantee a hit
49 } beam_info;
50 
51 #define BFIF_IS_FIGHTER_BEAM	(1<<0)
52 #define BFIF_FORCE_FIRING		(1<<1)
53 #define BFIF_TARGETING_COORDS	(1<<2)
54 #define BFIF_FLOATING_BEAM		(1<<3)
55 
56 // to ensure validity of fire_info, the related fields MUST be provided
57 #define BFM_TURRET_FIRED         0   // objp, subsys, target
58 #define BFM_TURRET_FORCE_FIRED   1   // objp, subsys, target OR target_pos
59 #define BFM_FIGHTER_FIRED        2   // objp, subsys
60 #define BFM_SPAWNED              3   // starting pos, target OR target_pos
61 #define BFM_SEXP_FLOATING_FIRED  4   // starting pos, target OR target_pos
62 #define BFM_SUBSPACE_STRIKE      5   // starting pos, target
63 
64 // pass to beam fire
65 typedef struct beam_fire_info {
66 	int				beam_info_index;				// weapon info index
67 	object			*shooter;						// whos shooting
68 	vec3d			local_fire_postion;		// offset from the center of the object (for fighter beams only)
69 	ship_subsys		*turret;						// where he's shooting from
70 	float			accuracy;						// 0.0 to 1.0 (only really effects targeting on small ships)
71 	object			*target;							// who's getting shot
72 	ship_subsys		*target_subsys;						// (optional), specific subsystem to be targeted on the target
73 	vec3d			target_pos1;							// if we're shooting off into space
74 	vec3d			target_pos2;							// if we're shooting off into space (optional second point)
75 	vec3d			starting_pos;							// starting positiong for floating beams -MageKing17
76 	beam_info		*beam_info_override;			// (optional), pass this in to override all beam movement info (for multiplayer)
77 	int				num_shots;						// (optional), only used for type D weapons
78 	int bank;									// for fighters, which bank of the primary weapons are they in
79 	int point;									// for fighters, which point on the bank it is from
80 	int bfi_flags;
81 	char team;									// for floating beams, determines which team the beam is on
82 	int burst_seed;								// used for sharing random targets if part of the same burst
83 	int  fire_method;
84 	float per_burst_rotation;                         // for type 5 beams
85 	int burst_index;
86 } beam_fire_info;
87 
88 typedef struct fighter_beam_fire_info {
89 	int				beam_info_index;				// weapon info index
90 	object			*shooter;						// whos shooting
91 	vec3d			local_fire_postion;		// offset from the center of the object (for fighter beams only)
92 	ship_subsys		*turret;							// where he's shooting from
93 	float				accuracy;						// 0.0 to 1.0 (only really effects targeting on small ships)
94 	object			*target;							// whos getting shot
95 	ship_subsys		*target_subsys;				// (optional), specific subsystem to be targeted on the target
96 	beam_info		*beam_info_override;			// (optional), pass this in to override all beam movement info (for multiplayer)
97 	int				num_shots;						// (optional), only used for type D weapons
98 	int fighter_beam_loop_sound;			//loop sound used by fighter beams -Bobboau
99 	int warmup_stamp;
100 	int warmdown_stamp;
101 	float life_left;
102 	float life_total;
103 } fighter_beam_fire_info;
104 
105 // max # of collisions we'll allow per frame
106 #define MAX_FRAME_COLLISIONS		10
107 
108 // collision info
109 typedef struct beam_collision {
110 	mc_info			cinfo;							// collision info
111 	int				c_objnum;						// objnum of the guy we recently collided with
112 	int				c_sig;							// object sig
113 	int				c_stamp;							// when we should next apply damage
114 	int				quadrant;						// shield quadrant this beam hits if any -Bobboau
115 	bool			is_exit_collision;					//does this occur when the beam is exiting the ship
116 } beam_collision;
117 
118 // beam flag defines
119 #define BF_SAFETY						(1<<0)		// if this is set, don't collide or render for this frame. lifetime still increases though
120 #define BF_SHRINK						(1<<1)		// if this is set, the beam is shrinking in width and approaching the warmdown phase
121 #define BF_FORCE_FIRING					(1<<2)
122 #define BF_IS_FIGHTER_BEAM				(1<<3)
123 #define BF_TARGETING_COORDS				(1<<4)
124 #define BF_FLOATING_BEAM				(1<<5)
125 #define BF_GROW				            (1<<6)     // if this is set, the beam is growing in width
126 #define BF_FINISHED_GROWING				(1<<7)     // to stop grow from re-triggering
127 
128 // beam struct (the actual weapon/object)
129 typedef struct beam {
130 	// low-level data
131 	int		objnum;					// our own objnum
132 	int		weapon_info_index;
133 	int		sig;						// signature for the shooting object
134 	object	*objp;					// the shooting object (who owns the turret that I am being fired from)
135 	object	*target;					// target object
136 	ship_subsys *target_subsys;	// targeted subsys
137 	vec3d	target_pos1;				// if we're targeting a location in space
138 	vec3d	target_pos2;				// if we're targeting a location in space (optional second point)
139 	int		target_sig;				// target sig
140 	ship_subsys *subsys;				// subsys its being fired from
141 	beam		*next, *prev;			// link list stuff
142 	vec3d	local_fire_postion;		// offset from the center of the object (for fighter beams only)
143 	int		framecount;				// how many frames the beam has been active
144 	int		flags;					// see BF_* defines
145 	float		current_width_factor;		// applied to width due to shrink or grow
146 
147 	// beam info
148 	int		warmup_stamp;			// timestamp for "warming up"
149 	int		warmdown_stamp;		// timestamp for "warming down"
150 	int		type;						// see BEAM_TYPE_* defines in beam.h
151 	float		life_left;				// in seconds
152 	float		life_total;				// total life
153 	// this vector has very special meaning. BEFORE performing collision checks, it basically implies a "direction". meaning
154 	// the vector between it and last_start is where the beam will be aiming. AFTER performing collision checks, it is the
155 	// literal world collision point on the object (or meaningless, if we hit nothing). The function beam_move_all_pre() is
156 	// responsible for then setting it up pre-collision time
157 	vec3d	last_shot;
158 	vec3d	last_start;
159 	int		shot_index;				// for type D beam weapons
160 	float	beam_glow_frame;		// what frame a beam glow animation is on
161 	float	beam_section_frame[MAX_BEAM_SECTIONS];	// what frame a beam section animation is on
162 
163 	// recent collisions
164 	beam_collision r_collisions[MAX_FRAME_COLLISIONS];					// recent collisions
165 	int r_collision_count;														// # of recent collisions
166 
167 	// collision info for this frame
168 	beam_collision f_collisions[MAX_FRAME_COLLISIONS];					// collisions for the current frame
169 	int f_collision_count;														// # of collisions we recorded this frame
170 
171 	// looping sound info, HANDLE
172 	sound_handle beam_sound_loop; // invalid if none
173 
174 	// team
175 	char		team;
176 
177 	float range;
178 	float damage_threshold;
179 
180 	// exactly how the beam will behave. by passing this is multiplayer from server to client, we can ensure that
181 	// everything looks the same
182 	beam_info binfo;
183 	int bank;
184 
185 	int Beam_muzzle_stamp;
186 	int firingpoint;
187 	float		beam_collide_width;
188 	float		beam_light_width;
189 
190 	float u_offset_local;
191 
192 	bool rotates;					// type 5s only, determines whether it rotates
193 	float type5_rot_speed;          // how fast it rotates if it does
194 } beam;
195 
196 extern std::array<beam, MAX_BEAMS> Beams;				// all beams
197 extern int Beam_count;
198 
199 #define BEAM_INDEX(beam)			(int)((beam) - Beams.data())
200 
201 // ------------------------------------------------------------------------------------------------
202 // BEAM WEAPON FUNCTIONS
203 //
204 
205 // ---------------
206 // the next functions are probably the only ones anyone should care about calling. the rest require somewhat detailed knowledge of beam weapons
207 
208 // fire a beam, returns objnum on success. the innards of the code handle all the rest, foo
209 int beam_fire(beam_fire_info *fire_info);
210 
211 // fire a targeting beam, returns objnum on success. a much much simplified version of a beam weapon
212 // targeting lasers last _one_ frame. For a continuous stream - they must be created every frame.
213 // this allows it to work smoothly in multiplayer (detect "trigger down". every frame just create a targeting laser firing straight out of the
214 // object. this way you get all the advantages of nice rendering and collisions).
215 // NOTE : only references beam_info_index and shooter
216 int beam_fire_targeting(fighter_beam_fire_info *fire_info);
217 
218 // return an object index of the guy who's firing this beam
219 int beam_get_parent(object *bm);
220 
221 // return weapon_info_index of beam
222 int beam_get_weapon_info_index(object *bm);
223 
224 // given a beam object, get the # of collisions which happened during the last collision check (typically, last frame)
225 int beam_get_num_collisions(int objnum);
226 
227 // stuff collision info, returns 1 on success
228 int beam_get_collision(int objnum, int num, int *collision_objnum, mc_info **cinfo);
229 // ---------------
230 
231 // init at game startup
232 void beam_init();
233 
234 // initialize beam weapons for this level
235 void beam_level_init();
236 
237 // shutdown beam weapons for this level
238 void beam_level_close();
239 
240 // collide a beam with a ship, returns 1 if we can ignore all future collisions between the 2 objects
241 int beam_collide_ship(obj_pair *pair);
242 
243 // collide a beam with an asteroid, returns 1 if we can ignore all future collisions between the 2 objects
244 int beam_collide_asteroid(obj_pair *pair);
245 
246 // collide a beam with a missile, returns 1 if we can ignore all future collisions between the 2 objects
247 int beam_collide_missile(obj_pair *pair);
248 
249 // collide a beam with debris, returns 1 if we can ignore all future collisions between the 2 objects
250 int beam_collide_debris(obj_pair *pair);
251 
252 // pre-move (before collision checking - but AFTER ALL OTHER OBJECTS HAVE BEEN MOVED)
253 void beam_move_all_pre();
254 
255 // post-collision time processing for beams
256 void beam_move_all_post();
257 
258 // render all beam weapons
259 void beam_render_all();
260 
261 // early-out function for when adding object collision pairs, return 1 if the pair should be ignored
262 int beam_collide_early_out(object *a, object *b);
263 
264 // pause all looping beam sounds
265 void beam_pause_sounds();
266 
267 // unpause looping beam sounds
268 void beam_unpause_sounds();
269 
270 void beam_calc_facing_pts(vec3d *top, vec3d *bot, vec3d *fvec, vec3d *pos, float w, float z_add);
271 
272 // return the amount of damage which should be applied to a ship. basically, filters friendly fire damage
273 float beam_get_ship_damage(beam *b, object *objp, vec3d* hitpos = nullptr);
274 
275 
276 
277 #endif
278