]> icculus.org git repositories - taylor/freespace2.git/blob - src/cmeasure/cmeasure.cpp
added copyright header
[taylor/freespace2.git] / src / cmeasure / cmeasure.cpp
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/CMeasure/CMeasure.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Counter measures.  Created by Mike Kulas, May 12, 1997.
16  *
17  * $Log$
18  * Revision 1.2  2002/06/09 04:41:15  relnev
19  * added copyright header
20  *
21  * Revision 1.1.1.1  2002/05/03 03:28:08  root
22  * Initial import.
23  *
24  * 
25  * 5     9/05/99 11:25p Mikek
26  * Debug code (only on NDEBUG).  Don't drop countermeasures if
27  * Ai_firing_enabled not set.
28  * 
29  * 4     11/05/98 5:55p Dave
30  * Big pass at reducing #includes
31  * 
32  * 3     10/13/98 9:28a Dave
33  * Started neatening up freespace.h. Many variables renamed and
34  * reorganized. Added AlphaColors.[h,cpp]
35  * 
36  * 2     10/07/98 10:52a Dave
37  * Initial checkin.
38  * 
39  * 1     10/07/98 10:48a Dave
40  * 
41  * 44    4/29/98 9:36p Allender
42  * ingame join tweaks.  added network message for countermeasures
43  * 
44  * 43    4/13/98 5:11p Mike
45  * More improvement to countermeasure code.
46  * 
47  * 42    4/13/98 2:14p Mike
48  * Countermeasure balance testing for Jim.
49  * 
50  * 41    4/10/98 11:02p Mike
51  * Make countermeasures less effective against aspect seekers than against
52  * heat seekers.
53  * Make AI ships match bank with each other when attacking a faraway
54  * target.
55  * Make ships not do silly loop-de-loop sometimes when attacking a faraway
56  * target.
57  * 
58  * 40    3/31/98 5:11p John
59  * Removed demo/save/restore.  Made NDEBUG defined compile.  Removed a
60  * bunch of debug stuff out of player file.  Made model code be able to
61  * unload models and malloc out only however many models are needed.
62  * 
63  * 39    3/17/98 3:49p John
64  * Turned off lighting on counter measures.
65  * 
66  * 38    2/26/98 10:07p Hoffoss
67  * Rewrote state saving and restoring to fix bugs and simplify the code.
68  * 
69  * 37    2/23/98 5:44p Johnson
70  * Resolve build error.
71  * 
72  * 36    2/23/98 4:30p Mike
73  * Make homing missiles detonate after they pass up their target.  Make
74  * countermeasures less effective.
75  * 
76  * 35    2/09/98 8:04p Lawrance
77  * Add objnum to cmeasure struct, correctly set source_objnum
78  * 
79  * 34    2/05/98 11:20p Lawrance
80  * save/restore countermeasure data
81  * 
82  * 33    2/05/98 12:51a Mike
83  * Early asteroid stuff.
84  * 
85  * 32    2/04/98 12:20p Mike
86  * Make countermeasures detonate in a smaller radius.  Make all in radius,
87  * not just homing one, detonate.
88  * 
89  * 31    1/29/98 11:48a John
90  * Added new counter measure rendering as model code.   Made weapons be
91  * able to have impact explosion.
92  * 
93  * 30    1/29/98 11:11a John
94  * Put in code to show dummy counter measure object.
95  * 
96  * 29    1/23/98 5:06p John
97  * Took L out of vertex structure used B (blue) instead.   Took all small
98  * fireballs out of fireball types and used particles instead.  Fixed some
99  * debris explosion things.  Restructured fireball code.   Restructured
100  * some lighting code.   Made dynamic lighting on by default. Made groups
101  * of lasers only cast one light.  Made fireballs not cast light.
102  * 
103  * 28    1/23/98 9:43a Mike
104  * Debug-C to disallow countermeasure firing.
105  * Fix bug in countermeasure tracking by aspect seekers.
106  * 
107  * 27    1/20/98 9:47a Mike
108  * Suppress optimized compiler warnings.
109  * Some secondary weapon work.
110  * 
111  * 26    1/16/98 11:43a Mike
112  * Fix countermeasures.
113  * 
114  * 25    12/30/97 6:44p John
115  * Made g3_Draw_bitmap functions account for aspect of bitmap.
116  * 
117  * 24    11/29/97 2:05p John
118  * made g3_draw_bitmap and g3_draw_rotated bitmap take w&h, not w/2 & h/2,
119  * like they used to incorrectly assume.   Added code to model to read in
120  * thruster radius's.
121  * 
122  * 23    10/27/97 3:24p Lawrance
123  * ensure countermeasures keep their initial velocity
124  * 
125  * 22    9/14/97 4:50p Lawrance
126  * added some demo debugging code
127  * 
128  * 21    9/04/97 5:09p Andsager
129  * implement physics using moment of inertia and mass (from BSPgen).
130  * Added to phys_info struct.  Updated ship_info, polymodel structs.
131  * Updated weapon ($Mass and $Force) and ship ($Mass -> $Density) tables
132  * 
133  * 20    8/20/97 11:09a Mike
134  * Make countermeasure lifetime based on skill level.
135  * 
136  * 19    8/13/97 9:50p Allender
137  * split *_move into *_process_pre and *_process_post functions.
138  * process_pre functions called before object is moved.  _process_post
139  * functions called after object is moved.  Reordered code in ship_post
140  * and weapon_post for multiplayer
141  * 
142  * 18    8/13/97 4:45p Allender
143  * fixed ship_fire_primary and fire_secondary to not take parameter for
144  * determining whether to count ammo or not.  Fixed countermeasure firing
145  * for multiplayer
146  * 
147  * 17    8/13/97 12:06p Lawrance
148  * supporting multiple types of fireball explosions
149  * 
150  * 16    8/11/97 6:03p Mike
151  * Make ships with no shields not claim to have shields in target box.
152  * 
153  * 15    8/08/97 4:29p Allender
154  * countermeasure stuff for multiplayer
155  * 
156  * 14    7/31/97 5:55p John
157  * made so you pass flags to obj_create.
158  * Added new collision code that ignores any pairs that will never
159  * collide.
160  * 
161  * 13    7/15/97 12:03p Andsager
162  * New physics stuff
163  * 
164  * 12    7/11/97 11:54a John
165  * added rotated 3d bitmaps.
166  * 
167  * 11    6/24/97 10:04a Allender
168  * major multiplayer improvements.  Better sequencing before game.
169  * Dealing with weapon/fireball/counter measure objects between
170  * client/host.  
171  * 
172  * 10    6/24/97 12:38a Lawrance
173  * fix minor bug with cycling cmeasure
174  * 
175  * 9     6/05/97 1:37a Lawrance
176  * change syntax of a snd_play()
177  * 
178  * 8     5/22/97 5:45p Mike
179  * Better countermeasure firing, key off availability, specify in
180  * weapons.tbl
181  * 
182  * 7     5/22/97 12:06p Lawrance
183  * include Sound.h for playing sound fx
184  * 
185  * 6     5/22/97 12:04p Lawrance
186  * added soundhook for cmeasure cycle
187  * 
188  * 5     5/15/97 5:05p Mike
189  * In the midst of changing subsystem targetnig from type-based to
190  * pointer-based.
191  * Also allowed you to view a target while dead.
192  * 
193  * 4     5/14/97 4:08p Lawrance
194  * removing my_index from game arrays
195  * 
196  * 3     5/14/97 10:50a Mike
197  * More countermeasure stuff.
198  * 
199  * 2     5/12/97 5:58p Mike
200  * Add countermeasures.
201  * 
202  * 1     5/12/97 2:23p Mike
203  *
204  * $NoKeywords: $
205  */
206
207 #include "pstypes.h"
208 #include "systemvars.h"
209 #include "cmeasure.h"
210 #include "freespace.h"
211 #include "vecmat.h"
212 #include "2d.h"
213 #include "3d.h"
214 #include "model.h"
215 #include "physics.h"
216 #include "floating.h"
217 #include "model.h"
218 #include "ship.h"
219 #include "timer.h"
220 #include "fireballs.h"
221 #include "radar.h"
222 #include "missionparse.h"               // For MAX_SPECIES_NAMES
223 #include "gamesnd.h"
224 #include "objectsnd.h"
225 #include "sound.h"
226 #include "staticrand.h"
227
228 cmeasure_info Cmeasure_info[MAX_CMEASURE_TYPES];
229 cmeasure Cmeasures[MAX_CMEASURES];
230
231 int     Num_cmeasure_types = 0;
232 int     Num_cmeasures = 0;
233 int     Cmeasure_inited = 0;
234 int     Cmeasures_homing_check = 0;
235 int     Countermeasures_enabled = 1;                    //      Debug, set to 0 means no one can fire countermeasures.
236
237 // This will get called at the start of each level.
238 void cmeasure_init()
239 {
240         int i;
241
242         if ( !Cmeasure_inited ) {
243                 Cmeasure_inited = 1;
244
245 /*              // Do all the processing that happens only once
246                 if ( Debris_model < 0 )         {
247                         if (Debris_model>-1)    {
248                                 polymodel * pm;
249                                 pm = model_get(Debris_model);
250                                 Debris_num_submodels = pm->n_models;
251                         }
252                 }
253
254                 for (i=0; i<MAX_SPECIES_NAMES; i++ )    {
255                         Debris_textures[i] = bm_load( Debris_texture_files[i] );
256                         if ( Debris_textures[i] < 0 ) { 
257                                 Warning( LOCATION, "Couldn't load species %d debris\ntexture, '%s'\n", i, Debris_texture_files[i] );
258                         }
259                 }
260 */      
261         }
262
263         // Reset everything between levels
264         Num_cmeasures = 0;
265
266         for (i=0; i<MAX_CMEASURES; i++ )        {
267                 Cmeasures[i].subtype = CMEASURE_UNUSED;
268         }
269                 
270 }
271
272 void cmeasure_render(object * objp)
273 {
274         // JAS TODO: Replace with proper fireball
275         cmeasure                        *cmp;
276         cmeasure_info   *cmip;
277         
278         cmp = &Cmeasures[objp->instance];
279         cmip = &Cmeasure_info[cmp->subtype];
280
281         if ( cmp->subtype == CMEASURE_UNUSED )  {
282                 Int3(); //      Hey, what are we doing in here?
283                 return;
284         }
285
286 //      float                           size = -1.0f;
287 //      vertex                  p;
288 //      g3_rotate_vertex(&p, &objp->pos );
289 //      if ( rand() > RAND_MAX/2 )      {
290 //              gr_set_color( 255, 0, 0 );
291 //      } else {
292 //              gr_set_color( 255, 255, 255 );
293 //      }
294 //      g3_draw_sphere(&p, 100.0f );
295         
296         if ( cmip->model_num > -1 )     {
297                 model_clear_instance(cmip->model_num);
298                 model_render(cmip->model_num, &objp->orient, &objp->pos, MR_NO_LIGHTING );
299         } else {
300                 mprintf(( "Not rendering countermeasure because model_num is negative\n" ));
301         }
302
303
304 /*
305         // JAS TODO: Replace with proper fireball
306         int                             framenum = -1;
307         float                           size = -1.0f;
308         vertex                  p;
309         cmeasure                        *cmp;
310
311         fireball_data   *fd;
312
313         cmp = &Cmeasures[objp->instance];
314         fd = &Fireball_data[FIREBALL_SHIP_EXPLODE1];
315
316         switch (cmp->subtype) {
317         case CMEASURE_UNUSED:
318                 Int3(); //      Hey, what are we doing in here?
319                 break;
320         default:
321                 framenum = (int) (fd->num_frames * Cmeasures[objp->instance].lifeleft*4) % fd->num_frames;
322                 size = objp->radius;
323                 break;
324         }
325
326         Assert(framenum != -1);
327         Assert(size != -1.0f);
328
329         gr_set_bitmap(fd->bitmap_id + framenum);
330         g3_rotate_vertex(&p, &objp->pos );
331         g3_draw_bitmap(&p, 0, size*0.5f, TMAP_FLAG_TEXTURED );
332 */
333 }
334
335 void cmeasure_delete( object * objp )
336 {
337         int num;
338
339         num = objp->instance;
340
341 //      Assert( Cmeasures[num].objnum == OBJ_INDEX(objp));
342
343         Cmeasures[num].subtype = CMEASURE_UNUSED;
344         Num_cmeasures--;
345         Assert( Num_cmeasures >= 0 );
346 }
347
348 // broke cmeasure_move into two functions -- process_pre and process_post (as was done with
349 // all *_move functions).  Nothing to do for process_pre
350
351 void cmeasure_process_pre( object *objp, float frame_time)
352 {
353 }
354
355 void cmeasure_process_post(object * objp, float frame_time)
356 {
357         int num;
358         num = objp->instance;
359         
360 //      Assert( Cmeasures[num].objnum == objnum );
361         cmeasure *cmp = &Cmeasures[num];
362
363         if ( cmp->lifeleft >= 0.0f) {
364                 cmp->lifeleft -= frame_time;
365                 if ( cmp->lifeleft < 0.0f )     {
366                         objp->flags |= OF_SHOULD_BE_DEAD;
367 //                      demo_do_flag_dead(OBJ_INDEX(objp));
368                 }
369         }
370
371 }
372
373 float Skill_level_cmeasure_life_scale[NUM_SKILL_LEVELS] = {3.0f, 2.0f, 1.5f, 1.25f, 1.0f};
374
375 // creates one countermeasure.  A ship fires 1 of these per launch.  rand_val is used
376 // in multiplayer.  If -1, then create a random number.  If non-negative, use this
377 // number for static_rand functions
378 int cmeasure_create( object * source_obj, vector * pos, int cm_type, int rand_val )
379 {
380         int             n, objnum, parent_objnum, arand;
381         object  * obj;
382         ship            *shipp;
383         cmeasure        *cmp;
384         cmeasure_info   *cmeasurep;
385
386 #ifndef NDEBUG
387         if (!Countermeasures_enabled || !Ai_firing_enabled)
388                 return -1;
389 #endif
390
391         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!
392
393         parent_objnum = OBJ_INDEX(source_obj);
394
395         Assert( source_obj->type == OBJ_SHIP ); 
396         Assert( source_obj->instance >= 0 && source_obj->instance < MAX_SHIPS );        
397         
398         shipp = &Ships[source_obj->instance];
399
400         if ( Num_cmeasures >= MAX_CMEASURES)
401                 return -1;
402
403         for (n=0; n<MAX_CMEASURES; n++ )        
404                 if ( Cmeasures[n].subtype == CMEASURE_UNUSED)
405                         break;
406         if ( n == MAX_CMEASURES)
407                 return -1;
408
409         nprintf(("Network", "Cmeasure created by %s\n", Ships[source_obj->instance].ship_name));
410
411         cmp = &Cmeasures[n];
412         cmeasurep = &Cmeasure_info[cm_type];
413
414         if ( pos == NULL )
415                 pos = &source_obj->pos;
416
417         objnum = obj_create( OBJ_CMEASURE, parent_objnum, n, &source_obj->orient, pos, 1.0f, OF_RENDERS | OF_PHYSICS );
418         
419         Assert( objnum >= 0 && objnum < MAX_OBJECTS );
420
421         // Create Debris piece n!
422         if ( rand_val == -1 )
423                 arand = myrand();                               // use a random number to get lifeleft, and random vector for displacement from ship
424         else
425                 arand = rand_val;
426
427         cmp->lifeleft = static_randf(arand) * (cmeasurep->life_max - cmeasurep->life_min) / cmeasurep->life_min;
428         if (source_obj->flags & OF_PLAYER_SHIP){
429                 cmp->lifeleft *= Skill_level_cmeasure_life_scale[Game_skill_level];
430         }
431         cmp->lifeleft = cmeasurep->life_min + cmp->lifeleft * (cmeasurep->life_max - cmeasurep->life_min);
432
433         //      cmp->objnum = objnum;
434         cmp->team = shipp->team;
435         cmp->subtype = cm_type;
436         cmp->objnum = objnum;
437         cmp->source_objnum = parent_objnum;
438         cmp->source_sig = Objects[objnum].signature;
439
440         cmp->flags = 0;
441
442         nprintf(("Jim", "Frame %i: Launching countermeasure #%i\n", Framecount, Objects[objnum].signature));
443
444         obj = &Objects[objnum];
445         
446         Num_cmeasures++;
447
448         vector vel, rand_vec;
449
450         vm_vec_scale_add(&vel, &source_obj->phys_info.vel, &source_obj->orient.fvec, -25.0f);
451
452         static_randvec(arand+1, &rand_vec);
453
454         vm_vec_scale_add2(&vel, &rand_vec, 2.0f);
455
456         obj->phys_info.vel = vel;
457
458         vm_vec_zero(&obj->phys_info.rotvel);
459
460         // blow out his reverse thrusters. Or drag, same thing.
461         obj->phys_info.rotdamp = 10000.0f;
462         obj->phys_info.side_slip_time_const = 10000.0f;
463
464         vm_vec_zero(&obj->phys_info.max_vel);           // make so he can't turn on his own VOLITION anymore.
465         obj->phys_info.max_vel.z = -25.0f;
466         vm_vec_copy_scale(&obj->phys_info.desired_vel, &obj->orient.fvec, obj->phys_info.max_vel.z );
467
468         vm_vec_zero(&obj->phys_info.max_rotvel);        // make so he can't change speed on his own VOLITION anymore.
469
470 //      obj->phys_info.flags |= PF_USE_VEL;
471
472         return arand;                                                                           // need to return this value for multiplayer purposes
473 }
474
475 void cmeasure_select_next(object *objp)
476 {
477         ship    *shipp;
478
479         Assert(objp->type == OBJ_SHIP);
480
481         shipp = &Ships[objp->instance];
482         shipp->current_cmeasure++;
483
484         if (shipp->current_cmeasure >= Num_cmeasure_types)
485                 shipp->current_cmeasure = 0;
486
487         //snd_play( &Snds[SND_CMEASURE_CYCLE] );
488
489         mprintf(("Countermeasure type set to %i in frame %i\n", shipp->current_cmeasure, Framecount));
490 }
491