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