2 * $Logfile: /Freespace2/code/CMeasure/CMeasure.cpp $
7 * Counter measures. Created by Mike Kulas, May 12, 1997.
10 * Revision 1.1 2002/05/03 03:28:08 root
14 * 5 9/05/99 11:25p Mikek
15 * Debug code (only on NDEBUG). Don't drop countermeasures if
16 * Ai_firing_enabled not set.
18 * 4 11/05/98 5:55p Dave
19 * Big pass at reducing #includes
21 * 3 10/13/98 9:28a Dave
22 * Started neatening up freespace.h. Many variables renamed and
23 * reorganized. Added AlphaColors.[h,cpp]
25 * 2 10/07/98 10:52a Dave
28 * 1 10/07/98 10:48a Dave
30 * 44 4/29/98 9:36p Allender
31 * ingame join tweaks. added network message for countermeasures
33 * 43 4/13/98 5:11p Mike
34 * More improvement to countermeasure code.
36 * 42 4/13/98 2:14p Mike
37 * Countermeasure balance testing for Jim.
39 * 41 4/10/98 11:02p Mike
40 * Make countermeasures less effective against aspect seekers than against
42 * Make AI ships match bank with each other when attacking a faraway
44 * Make ships not do silly loop-de-loop sometimes when attacking a faraway
47 * 40 3/31/98 5:11p John
48 * Removed demo/save/restore. Made NDEBUG defined compile. Removed a
49 * bunch of debug stuff out of player file. Made model code be able to
50 * unload models and malloc out only however many models are needed.
52 * 39 3/17/98 3:49p John
53 * Turned off lighting on counter measures.
55 * 38 2/26/98 10:07p Hoffoss
56 * Rewrote state saving and restoring to fix bugs and simplify the code.
58 * 37 2/23/98 5:44p Johnson
59 * Resolve build error.
61 * 36 2/23/98 4:30p Mike
62 * Make homing missiles detonate after they pass up their target. Make
63 * countermeasures less effective.
65 * 35 2/09/98 8:04p Lawrance
66 * Add objnum to cmeasure struct, correctly set source_objnum
68 * 34 2/05/98 11:20p Lawrance
69 * save/restore countermeasure data
71 * 33 2/05/98 12:51a Mike
72 * Early asteroid stuff.
74 * 32 2/04/98 12:20p Mike
75 * Make countermeasures detonate in a smaller radius. Make all in radius,
76 * not just homing one, detonate.
78 * 31 1/29/98 11:48a John
79 * Added new counter measure rendering as model code. Made weapons be
80 * able to have impact explosion.
82 * 30 1/29/98 11:11a John
83 * Put in code to show dummy counter measure object.
85 * 29 1/23/98 5:06p John
86 * Took L out of vertex structure used B (blue) instead. Took all small
87 * fireballs out of fireball types and used particles instead. Fixed some
88 * debris explosion things. Restructured fireball code. Restructured
89 * some lighting code. Made dynamic lighting on by default. Made groups
90 * of lasers only cast one light. Made fireballs not cast light.
92 * 28 1/23/98 9:43a Mike
93 * Debug-C to disallow countermeasure firing.
94 * Fix bug in countermeasure tracking by aspect seekers.
96 * 27 1/20/98 9:47a Mike
97 * Suppress optimized compiler warnings.
98 * Some secondary weapon work.
100 * 26 1/16/98 11:43a Mike
101 * Fix countermeasures.
103 * 25 12/30/97 6:44p John
104 * Made g3_Draw_bitmap functions account for aspect of bitmap.
106 * 24 11/29/97 2:05p John
107 * made g3_draw_bitmap and g3_draw_rotated bitmap take w&h, not w/2 & h/2,
108 * like they used to incorrectly assume. Added code to model to read in
111 * 23 10/27/97 3:24p Lawrance
112 * ensure countermeasures keep their initial velocity
114 * 22 9/14/97 4:50p Lawrance
115 * added some demo debugging code
117 * 21 9/04/97 5:09p Andsager
118 * implement physics using moment of inertia and mass (from BSPgen).
119 * Added to phys_info struct. Updated ship_info, polymodel structs.
120 * Updated weapon ($Mass and $Force) and ship ($Mass -> $Density) tables
122 * 20 8/20/97 11:09a Mike
123 * Make countermeasure lifetime based on skill level.
125 * 19 8/13/97 9:50p Allender
126 * split *_move into *_process_pre and *_process_post functions.
127 * process_pre functions called before object is moved. _process_post
128 * functions called after object is moved. Reordered code in ship_post
129 * and weapon_post for multiplayer
131 * 18 8/13/97 4:45p Allender
132 * fixed ship_fire_primary and fire_secondary to not take parameter for
133 * determining whether to count ammo or not. Fixed countermeasure firing
136 * 17 8/13/97 12:06p Lawrance
137 * supporting multiple types of fireball explosions
139 * 16 8/11/97 6:03p Mike
140 * Make ships with no shields not claim to have shields in target box.
142 * 15 8/08/97 4:29p Allender
143 * countermeasure stuff for multiplayer
145 * 14 7/31/97 5:55p John
146 * made so you pass flags to obj_create.
147 * Added new collision code that ignores any pairs that will never
150 * 13 7/15/97 12:03p Andsager
153 * 12 7/11/97 11:54a John
154 * added rotated 3d bitmaps.
156 * 11 6/24/97 10:04a Allender
157 * major multiplayer improvements. Better sequencing before game.
158 * Dealing with weapon/fireball/counter measure objects between
161 * 10 6/24/97 12:38a Lawrance
162 * fix minor bug with cycling cmeasure
164 * 9 6/05/97 1:37a Lawrance
165 * change syntax of a snd_play()
167 * 8 5/22/97 5:45p Mike
168 * Better countermeasure firing, key off availability, specify in
171 * 7 5/22/97 12:06p Lawrance
172 * include Sound.h for playing sound fx
174 * 6 5/22/97 12:04p Lawrance
175 * added soundhook for cmeasure cycle
177 * 5 5/15/97 5:05p Mike
178 * In the midst of changing subsystem targetnig from type-based to
180 * Also allowed you to view a target while dead.
182 * 4 5/14/97 4:08p Lawrance
183 * removing my_index from game arrays
185 * 3 5/14/97 10:50a Mike
186 * More countermeasure stuff.
188 * 2 5/12/97 5:58p Mike
189 * Add countermeasures.
191 * 1 5/12/97 2:23p Mike
197 #include "systemvars.h"
198 #include "cmeasure.h"
199 #include "freespace.h"
205 #include "floating.h"
209 #include "fireballs.h"
211 #include "missionparse.h" // For MAX_SPECIES_NAMES
213 #include "objectsnd.h"
215 #include "staticrand.h"
217 cmeasure_info Cmeasure_info[MAX_CMEASURE_TYPES];
218 cmeasure Cmeasures[MAX_CMEASURES];
220 int Num_cmeasure_types = 0;
221 int Num_cmeasures = 0;
222 int Cmeasure_inited = 0;
223 int Cmeasures_homing_check = 0;
224 int Countermeasures_enabled = 1; // Debug, set to 0 means no one can fire countermeasures.
226 // This will get called at the start of each level.
231 if ( !Cmeasure_inited ) {
234 /* // Do all the processing that happens only once
235 if ( Debris_model < 0 ) {
236 if (Debris_model>-1) {
238 pm = model_get(Debris_model);
239 Debris_num_submodels = pm->n_models;
243 for (i=0; i<MAX_SPECIES_NAMES; i++ ) {
244 Debris_textures[i] = bm_load( Debris_texture_files[i] );
245 if ( Debris_textures[i] < 0 ) {
246 Warning( LOCATION, "Couldn't load species %d debris\ntexture, '%s'\n", i, Debris_texture_files[i] );
252 // Reset everything between levels
255 for (i=0; i<MAX_CMEASURES; i++ ) {
256 Cmeasures[i].subtype = CMEASURE_UNUSED;
261 void cmeasure_render(object * objp)
263 // JAS TODO: Replace with proper fireball
267 cmp = &Cmeasures[objp->instance];
268 cmip = &Cmeasure_info[cmp->subtype];
270 if ( cmp->subtype == CMEASURE_UNUSED ) {
271 Int3(); // Hey, what are we doing in here?
275 // float size = -1.0f;
277 // g3_rotate_vertex(&p, &objp->pos );
278 // if ( rand() > RAND_MAX/2 ) {
279 // gr_set_color( 255, 0, 0 );
281 // gr_set_color( 255, 255, 255 );
283 // g3_draw_sphere(&p, 100.0f );
285 if ( cmip->model_num > -1 ) {
286 model_clear_instance(cmip->model_num);
287 model_render(cmip->model_num, &objp->orient, &objp->pos, MR_NO_LIGHTING );
289 mprintf(( "Not rendering countermeasure because model_num is negative\n" ));
294 // JAS TODO: Replace with proper fireball
302 cmp = &Cmeasures[objp->instance];
303 fd = &Fireball_data[FIREBALL_SHIP_EXPLODE1];
305 switch (cmp->subtype) {
306 case CMEASURE_UNUSED:
307 Int3(); // Hey, what are we doing in here?
310 framenum = (int) (fd->num_frames * Cmeasures[objp->instance].lifeleft*4) % fd->num_frames;
315 Assert(framenum != -1);
316 Assert(size != -1.0f);
318 gr_set_bitmap(fd->bitmap_id + framenum);
319 g3_rotate_vertex(&p, &objp->pos );
320 g3_draw_bitmap(&p, 0, size*0.5f, TMAP_FLAG_TEXTURED );
324 void cmeasure_delete( object * objp )
328 num = objp->instance;
330 // Assert( Cmeasures[num].objnum == OBJ_INDEX(objp));
332 Cmeasures[num].subtype = CMEASURE_UNUSED;
334 Assert( Num_cmeasures >= 0 );
337 // broke cmeasure_move into two functions -- process_pre and process_post (as was done with
338 // all *_move functions). Nothing to do for process_pre
340 void cmeasure_process_pre( object *objp, float frame_time)
344 void cmeasure_process_post(object * objp, float frame_time)
347 num = objp->instance;
349 // Assert( Cmeasures[num].objnum == objnum );
350 cmeasure *cmp = &Cmeasures[num];
352 if ( cmp->lifeleft >= 0.0f) {
353 cmp->lifeleft -= frame_time;
354 if ( cmp->lifeleft < 0.0f ) {
355 objp->flags |= OF_SHOULD_BE_DEAD;
356 // demo_do_flag_dead(OBJ_INDEX(objp));
362 float Skill_level_cmeasure_life_scale[NUM_SKILL_LEVELS] = {3.0f, 2.0f, 1.5f, 1.25f, 1.0f};
364 // creates one countermeasure. A ship fires 1 of these per launch. rand_val is used
365 // in multiplayer. If -1, then create a random number. If non-negative, use this
366 // number for static_rand functions
367 int cmeasure_create( object * source_obj, vector * pos, int cm_type, int rand_val )
369 int n, objnum, parent_objnum, arand;
373 cmeasure_info *cmeasurep;
376 if (!Countermeasures_enabled || !Ai_firing_enabled)
380 Cmeasures_homing_check = 2; // Tell homing code to scan everything for two frames. If only one frame, get sync problems due to objects being created at end of frame!
382 parent_objnum = OBJ_INDEX(source_obj);
384 Assert( source_obj->type == OBJ_SHIP );
385 Assert( source_obj->instance >= 0 && source_obj->instance < MAX_SHIPS );
387 shipp = &Ships[source_obj->instance];
389 if ( Num_cmeasures >= MAX_CMEASURES)
392 for (n=0; n<MAX_CMEASURES; n++ )
393 if ( Cmeasures[n].subtype == CMEASURE_UNUSED)
395 if ( n == MAX_CMEASURES)
398 nprintf(("Network", "Cmeasure created by %s\n", Ships[source_obj->instance].ship_name));
401 cmeasurep = &Cmeasure_info[cm_type];
404 pos = &source_obj->pos;
406 objnum = obj_create( OBJ_CMEASURE, parent_objnum, n, &source_obj->orient, pos, 1.0f, OF_RENDERS | OF_PHYSICS );
408 Assert( objnum >= 0 && objnum < MAX_OBJECTS );
410 // Create Debris piece n!
411 if ( rand_val == -1 )
412 arand = myrand(); // use a random number to get lifeleft, and random vector for displacement from ship
416 cmp->lifeleft = static_randf(arand) * (cmeasurep->life_max - cmeasurep->life_min) / cmeasurep->life_min;
417 if (source_obj->flags & OF_PLAYER_SHIP){
418 cmp->lifeleft *= Skill_level_cmeasure_life_scale[Game_skill_level];
420 cmp->lifeleft = cmeasurep->life_min + cmp->lifeleft * (cmeasurep->life_max - cmeasurep->life_min);
422 // cmp->objnum = objnum;
423 cmp->team = shipp->team;
424 cmp->subtype = cm_type;
425 cmp->objnum = objnum;
426 cmp->source_objnum = parent_objnum;
427 cmp->source_sig = Objects[objnum].signature;
431 nprintf(("Jim", "Frame %i: Launching countermeasure #%i\n", Framecount, Objects[objnum].signature));
433 obj = &Objects[objnum];
437 vector vel, rand_vec;
439 vm_vec_scale_add(&vel, &source_obj->phys_info.vel, &source_obj->orient.fvec, -25.0f);
441 static_randvec(arand+1, &rand_vec);
443 vm_vec_scale_add2(&vel, &rand_vec, 2.0f);
445 obj->phys_info.vel = vel;
447 vm_vec_zero(&obj->phys_info.rotvel);
449 // blow out his reverse thrusters. Or drag, same thing.
450 obj->phys_info.rotdamp = 10000.0f;
451 obj->phys_info.side_slip_time_const = 10000.0f;
453 vm_vec_zero(&obj->phys_info.max_vel); // make so he can't turn on his own VOLITION anymore.
454 obj->phys_info.max_vel.z = -25.0f;
455 vm_vec_copy_scale(&obj->phys_info.desired_vel, &obj->orient.fvec, obj->phys_info.max_vel.z );
457 vm_vec_zero(&obj->phys_info.max_rotvel); // make so he can't change speed on his own VOLITION anymore.
459 // obj->phys_info.flags |= PF_USE_VEL;
461 return arand; // need to return this value for multiplayer purposes
464 void cmeasure_select_next(object *objp)
468 Assert(objp->type == OBJ_SHIP);
470 shipp = &Ships[objp->instance];
471 shipp->current_cmeasure++;
473 if (shipp->current_cmeasure >= Num_cmeasure_types)
474 shipp->current_cmeasure = 0;
476 //snd_play( &Snds[SND_CMEASURE_CYCLE] );
478 mprintf(("Countermeasure type set to %i in frame %i\n", shipp->current_cmeasure, Framecount));