2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/Fireball/FireBalls.cpp $
15 * Code to move, render and otherwise deal with fireballs.
18 * Revision 1.6 2004/09/20 01:31:44 theoddone33
21 * Revision 1.5 2004/07/04 11:31:43 taylor
22 * amd64 support, compiler warning fixes, don't use software rendering
24 * Revision 1.4 2002/06/17 06:33:08 relnev
25 * ryan's struct patch for gcc 2.95
27 * Revision 1.3 2002/06/09 04:41:16 relnev
28 * added copyright header
30 * Revision 1.2 2002/05/07 03:16:43 theoddone33
31 * The Great Newline Fix
33 * Revision 1.1.1.1 2002/05/03 03:28:08 root
37 * 19 9/14/99 1:27a Andsager
38 * Better LOD for fireballs when behind. Move point ahead to get vertex
39 * ahead and then find size.
41 * 18 9/12/99 11:42p Dave
43 * 17 9/13/99 10:09a Andsager
44 * Add debug console commands to lower model render detail and fireball
45 * LOD for big ship explosiosns.
47 * 16 9/09/99 8:53p Dave
48 * Fixed multiplayer degenerate orientation case problem. Make sure warp
49 * effect never goes lower than LOD 1.
51 * 15 9/07/99 12:20a Andsager
52 * LOD less agressive at lower hardware detail level
54 * 14 9/06/99 6:47p Jamesa
57 * 13 9/06/99 3:23p Andsager
58 * Make fireball and weapon expl ani LOD choice look at resolution of the
61 * 12 9/01/99 10:09a Dave
64 * 11 8/31/99 10:13p Andsager
65 * Add Knossos warp effect fireball
67 * 10 8/30/99 9:59a Dave
68 * Removed explosion LOD stuff.
70 * 9 8/28/99 4:54p Dave
71 * Fixed directives display for multiplayer clients for wings with
72 * multiple waves. Fixed hud threat indicator rendering color.
74 * 8 8/27/99 9:07p Dave
75 * LOD explosions. Improved beam weapon accuracy.
77 * 7 7/09/99 5:54p Dave
78 * Seperated cruiser types into individual types. Added tons of new
79 * briefing icons. Campaign screen.
81 * 6 4/28/99 11:13p Dave
82 * Temporary checkin of artillery code.
84 * 5 4/23/99 12:01p Johnson
87 * 4 11/05/98 5:55p Dave
88 * Big pass at reducing #includes
90 * 3 10/23/98 3:51p Dave
91 * Full support for tstrings.tbl and foreign languages. All that remains
92 * is to make it active in Fred.
94 * 2 10/07/98 10:52a Dave
97 * 1 10/07/98 10:48a Dave
99 * 75 5/18/98 2:49p Lawrance
100 * Allow up to double instance of sound for warp holes
102 * 74 5/15/98 3:54p John
103 * Added code so that only "perishable" fireballs get removed.
105 * 73 4/15/98 9:42a Adam
106 * added 2 more explosion types (1, actually, but placeholder for 2)
108 * 72 4/12/98 9:56a John
109 * Made lighting detail flags work. Made explosions cast light on
112 * 71 4/09/98 7:58p John
113 * Cleaned up tmapper code a bit. Put NDEBUG around some ndebug stuff.
114 * Took out XPARENT flag settings in all the alpha-blended texture stuff.
116 * 70 3/31/98 5:11p John
117 * Removed demo/save/restore. Made NDEBUG defined compile. Removed a
118 * bunch of debug stuff out of player file. Made model code be able to
119 * unload models and malloc out only however many models are needed.
121 * 69 3/30/98 4:02p John
122 * Made machines with < 32 MB of RAM use every other frame of certain
123 * bitmaps. Put in code to keep track of how much RAM we've malloc'd.
125 * 68 3/29/98 12:39p John
126 * Made warp in glow page in
128 * 67 3/27/98 2:17p Lawrance
129 * Don't play warphole closing for non-captial sized warp effects
131 * 66 3/26/98 5:44p Lawrance
132 * take out debug comments for warphole sounds playing
134 * 65 3/26/98 5:21p John
135 * Added new code to preload all bitmaps at the start of a level.
136 * Commented it out, though.
138 * 64 3/25/98 5:30p Lawrance
139 * Fix bug that was not playing wormhole open sound effect at correct
142 * 63 3/25/98 10:56a Lawrance
143 * Make a sound for warphole close as well as warphole open, move to
146 * 62 3/18/98 12:36p John
147 * Made hardware have nicer looking warp effect
149 * 61 3/18/98 12:01p John
150 * Made warp grid grow faster
152 * 60 2/26/98 10:07p Hoffoss
153 * Rewrote state saving and restoring to fix bugs and simplify the code.
155 * 59 2/22/98 12:19p John
156 * Externalized some strings
158 * 58 2/19/98 4:32p Lawrance
159 * Add asteroid explosion
161 * 57 2/12/98 11:53p Lawrance
162 * comment out use of current_frame since not used anywhere
164 * 56 2/05/98 9:21p John
165 * Some new Direct3D code. Added code to monitor a ton of stuff in the
168 * 55 1/23/98 5:06p John
169 * Took L out of vertex structure used B (blue) instead. Took all small
170 * fireballs out of fireball types and used particles instead. Fixed some
171 * debris explosion things. Restructured fireball code. Restructured
172 * some lighting code. Made dynamic lighting on by default. Made groups
173 * of lasers only cast one light. Made fireballs not cast light.
175 * 54 1/19/98 9:37p Allender
176 * Great Compiler Warning Purge of Jan, 1998. Used pragma's in a couple
177 * of places since I was unsure of what to do with code.
179 * 53 1/15/98 4:58p John
180 * Made warp effect use a looping ani. Made the scaling up & down be in
183 * 52 1/15/98 2:32p John
184 * Added code to optionally take a velocity for a fireball.
186 * 51 1/11/98 2:15p John
187 * Changed a lot of stuff that had to do with bitmap loading. Made cfile
188 * not do callbacks, I put that in global code. Made only bitmaps that
189 * need to load for a level load.
191 * 50 1/02/98 5:04p John
192 * Several explosion related changes. Made fireballs not be used as
193 * ani's. Made ship spark system expell particles. Took away impact
194 * explosion for weapon hitting ship... this needs to get added to weapon
195 * info and makes shield hit more obvious. Only make sparks when hit
198 * 49 12/31/97 4:48p John
199 * added some debug info
201 * 48 12/30/97 6:44p John
202 * Made g3_Draw_bitmap functions account for aspect of bitmap.
204 * 47 12/08/97 11:15a John
205 * added parameter to warpout for life.
207 * 46 12/02/97 3:59p John
208 * Added first rev of thruster glow, along with variable levels of
209 * translucency, which retquired some restructing of palman.
211 * 45 11/30/97 2:03p John
212 * made warp effect not use an ani for height map.
214 * 44 11/16/97 12:20p John
215 * added code to make ships instantly warp in/out if fireball effect
216 * fails. But, made it so the fireball effect will kill off old sparks
217 * so it can go, so this should never happen.
219 * 43 11/16/97 10:48a John
220 * added code to remove the oldest fireball if there weren't enough slots
223 * 42 11/01/97 1:49p John
224 * added code to page fireballs in during level load. Made player warpout
225 * use Adam's new camera movement pattern. Make ships docked to warping
226 * out ships render correctly.
228 * 41 10/29/97 5:05p John
229 * Changed dynamic lighting to only rotate and calculate lighting for
230 * point lights that are close to an object. Changed lower framerate cap
233 * 40 10/24/97 6:24p John
234 * added code to return the life left of a fireball
236 * 39 9/14/97 4:49p Lawrance
237 * add some demo debugging code
239 * 38 9/12/97 4:02p John
240 * put in ship warp out effect.
241 * put in dynamic lighting for warp in/out
243 * 37 9/09/97 4:49p John
244 * Almost done ship warp in code
246 * 36 9/08/97 8:39a John
247 * added in code structure for grid
249 * 35 9/03/97 5:04p Lawrance
250 * add error checking when restoring structs
252 * 34 9/03/97 4:32p John
253 * changed bmpman to only accept ani and pcx's. made passing .pcx or .ani
254 * to bm_load functions not needed. Made bmpman keep track of palettes
255 * for bitmaps not mapped into game palettes.
257 * 33 8/29/97 2:26p John
258 * first rev of ship warp in effect. Nothing more than a fireball inside
259 * of freespace, but textest.cpp contains the correct effect code that
260 * needs to be transferred into the game next.
262 * 32 8/21/97 5:11p Lawrance
263 * frame numbering for ANI's now is from 0 -> total_frames-1.
265 * 31 8/13/97 9:50p Allender
266 * split *_move into *_process_pre and *_process_post functions.
267 * process_pre functions called before object is moved. _process_post
268 * functions called after object is moved. Reordered code in ship_post
269 * and weapon_post for multiplayer
271 * 30 8/13/97 12:06p Lawrance
272 * supporting multiple types of fireball explosions
274 * 29 8/05/97 10:18a Lawrance
275 * my_rand() being used temporarily instead of rand()
277 * 28 7/31/97 5:55p John
278 * made so you pass flags to obj_create.
279 * Added new collision code that ignores any pairs that will never
282 * 27 7/24/97 9:54a Lawrance
283 * don't free fireball system if not inited
285 * 26 7/23/97 11:35a Lawrance
286 * ensure fireball animations are always freed properly
288 * 25 7/21/97 11:41a Lawrance
289 * clean up fireballs at the end of each level
291 * 24 7/20/97 6:58p Lawrance
292 * call anim_get_frame() to take advantage of key-framed animation
294 * 23 7/11/97 3:57p John
295 * made fireballs translucent. alpha=1.3x intesity. only for d3d.
297 * 22 7/11/97 12:08p John
298 * made fireballs randomly be rotated.
300 * 21 7/11/97 11:54a John
301 * added rotated 3d bitmaps.
303 * 20 7/11/97 11:19a Lawrance
304 * fix mem leaks, move save code from State.cpp here
306 * 19 7/10/97 1:51p Lawrance
307 * sorting anim fireballs
309 * 18 6/24/97 6:21p John
310 * added detail flags.
311 * sped up motion debris system a bit.
313 * 17 5/14/97 4:08p Lawrance
314 * removing my_index from game arrays
316 * 16 5/05/97 10:40p Mike
317 * Make missile exhaust trails look a tad nicer.
319 * 15 3/11/97 10:47p Mike
320 * Add a slew of secondary weapons.
321 * Support exhaust blobs.
322 * Add weapons that spawn weapons.
323 * Add remotely detonatable weapons.
324 * Add heat-seeking missiles.
326 * 14 2/17/97 5:18p John
327 * Added a bunch of RCS headers to a bunch of old files that don't have
343 #include "floating.h"
345 #include "lighting.h"
348 #include "systemvars.h"
349 #include "fireballs.h"
350 #include "linklist.h"
352 #include "localize.h"
354 #define WARPHOLE_GROW_TIME (1.5f) // time for warphole to reach max size (also time to shrink to nothing once it begins to shrink)
356 #define MAX_FIREBALL_LOD 4
358 typedef struct fireball_lod {
359 char filename[MAX_FILENAME_LEN];
365 typedef struct fireball_info {
370 // flag values for fireball struct flags member
371 #define FBF_WARP_CLOSE_SOUND_PLAYED (1<<0)
372 #define FBF_WARP_CAPTIAL_SIZE (1<<1)
373 #define FBF_WARP_CRUISER_SIZE (1<<2)
375 typedef struct fireball {
376 int objnum; // If -1 this object is unused
377 int fireball_info_index; // Index into Fireball_info array
379 int orient; // For fireballs, which orientation. For warps, 0 is warpin, 1 is warpout
380 int flags; // see #define FBF_*
381 char lod; // current LOD
382 float time_elapsed; // in seconds
383 float total_time; // total lifetime of animation in seconds
386 #define MAX_FIREBALLS 200
388 fireball Fireballs[MAX_FIREBALLS];
390 fireball_info Fireball_info[MAX_FIREBALL_TYPES];
392 int Num_fireballs = 0;
394 int fireballs_inited = 0;
396 int Warp_glow_bitmap = -1;
398 #define FB_INDEX(fb) (fb-Fireballs)
400 // play warp in sound for warp effect
401 void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
404 float range_multiplier = 1.0f;
405 object *fireball_objp;
407 SDL_assert((fb != NULL) && (fb->objnum >= 0));
408 if((fb == NULL) || (fb->objnum < 0)){
411 fireball_objp = &Objects[fb->objnum];
413 sound_index = SND_WARP_IN;
415 if((ship_class >= 0) && (ship_class < Num_ship_types)){
416 if ( Ship_info[ship_class].flags & SIF_HUGE_SHIP ) {
417 sound_index = SND_CAPITAL_WARP_IN;
418 fb->flags |= FBF_WARP_CAPTIAL_SIZE;
419 } else if ( Ship_info[ship_class].flags & SIF_BIG_SHIP ) {
420 range_multiplier = 6.0f;
421 fb->flags |= FBF_WARP_CRUISER_SIZE;
425 snd_play_3d(&Snds[sound_index], &fireball_objp->pos, &Eye_position, fireball_objp->radius, NULL, 0, 1.0f, SND_PRIORITY_DOUBLE_INSTANCE, NULL, range_multiplier); // play warp sound effect
428 // play warp out sound for warp effect
429 void fireball_play_warphole_close_sound(fireball *fb)
433 object *fireball_objp;
435 fireball_objp = &Objects[fb->objnum];
437 sound_index = SND_WARP_OUT;
439 if ( fb->flags & FBF_WARP_CAPTIAL_SIZE ) {
440 sound_index = SND_CAPITAL_WARP_OUT;
442 // AL 27-3-98: Decided that warphole closing is only required for captial ship sized warp effects.
446 snd_play_3d(&Snds[sound_index], &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
449 void fireball_parse_tbl()
452 char base_filename[256] = "";
457 if ((rval = setjmp(parse_abort)) != 0) {
458 Error(LOCATION, "Unable to parse fireball.tbl! Code = %i.\n", rval);
461 read_file_text(NOX("fireball.tbl"));
466 required_string("#Start");
467 while (required_string_either("#End","$Name:")) {
468 SDL_assert( ntypes < MAX_FIREBALL_TYPES);
471 required_string("$Name:");
472 stuff_string(base_filename, F_NAME, NULL);
474 // # of lod levels - make sure old fireball.tbl is compatible
475 Fireball_info[ntypes].lod_count = 1;
476 if(optional_string("$LOD:")){
477 stuff_int(&Fireball_info[ntypes].lod_count);
480 // stuff default filename
481 SDL_strlcpy(Fireball_info[ntypes].lod[0].filename, base_filename, sizeof(Fireball_info[0].lod[0].filename));
483 // stuff LOD level filenames
484 for(idx=1; idx<Fireball_info[ntypes].lod_count; idx++){
485 if(idx >= MAX_FIREBALL_LOD){
489 SDL_snprintf(Fireball_info[ntypes].lod[idx].filename, MAX_FILENAME_LEN, "%s_%d", base_filename, idx);
494 required_string("#End");
496 // close localization
501 void fireball_load_data()
506 for ( i = 0; i < MAX_FIREBALL_TYPES; i++ ) {
507 fd = &Fireball_info[i];
509 for(idx=0; idx<fd->lod_count; idx++){
510 fd->lod[idx].bitmap_id = bm_load_animation( fd->lod[idx].filename, &fd->lod[idx].num_frames, &fd->lod[idx].fps, 1 );
511 if ( fd->lod[idx].bitmap_id < 0 ) {
512 Error(LOCATION, "Could not load %s anim file\n", fd->lod[idx].filename);
517 if ( Warp_glow_bitmap == -1 ) {
518 Warp_glow_bitmap = bm_load( NOX("warpglow01") );
523 void fireball_preload()
525 // Do nothing. Called before level init, this used to page in warp effect.
526 // Not needed with new BmpMan system.
529 // This will get called at the start of each level.
534 if ( !fireballs_inited ) {
535 fireballs_inited = 1;
537 // Do all the processing that happens only once
538 fireball_parse_tbl();
539 fireball_load_data();
542 // Reset everything between levels
544 for (i=0; i<MAX_FIREBALLS; i++ ) {
545 Fireballs[i].objnum = -1;
551 MONITOR( NumFireballsRend );
553 //extern int tcache_hit(int);
554 //extern int Glide_expl_textures_in_frame;
555 //extern float Glide_avg_exp_text_per_sec;
557 void fireball_render(object * obj)
563 MONITOR_INC( NumFireballsRend, 1 );
566 fb = &Fireballs[num];
568 if ( Fireballs[num].current_bitmap < 0 )
571 // gr_set_color( 0, 100, 0 );
572 // g3_draw_sphere_ez( &obj->pos, obj->radius );
576 if(The_mission.flags & MISSION_FLAG_FULLNEB){
577 gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0, -1.0f, -1.0f);
580 g3_rotate_vertex(&p, &obj->pos );
582 switch( fb->fireball_info_index ) {
584 case FIREBALL_EXPLOSION_MEDIUM:
585 gr_set_bitmap(Fireballs[num].current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f, -1, -1 );
586 g3_draw_bitmap(&p, fb->orient, obj->radius, TMAP_FLAG_TEXTURED );
589 case FIREBALL_EXPLOSION_LARGE1:
590 case FIREBALL_EXPLOSION_LARGE2:
591 // case FIREBALL_EXPLOSION_LARGE3:
593 if (!tcache_hit(Fireballs[num].current_bitmap)) {
594 // if we're over 200k exp vram upload this frame, change to lower lod
595 if (Glide_expl_textures_in_frame > 1024 * 200) {
596 // change fireball instance to lower LOD or don't draw
598 // get current LOD and number of LODs
599 int cur_lod = Fireballs[num].lod;
600 int num_lods = Fireball_info[Fireballs[num].fireball_info_index].lod_count;
602 if (num_lods > cur_lod+1) {
604 int frame = Fireballs[num].current_bitmap - Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod].bitmap_id;
605 Fireballs[num].lod++;
606 Fireballs[num].current_bitmap = Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod+1].bitmap_id + frame;
607 mprintf(("bumping down lod for fireball %s, frame %d\n", Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod].filename, frame));
612 case FIREBALL_ASTEROID:
613 // Make the big explosions rotate with the viewer.
614 gr_set_bitmap(Fireballs[num].current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f, -1, -1 );
615 g3_draw_rotated_bitmap(&p, (i2fl(fb->orient)*PI)/180.0f, obj->radius, TMAP_FLAG_TEXTURED );
618 case FIREBALL_WARP_EFFECT:
619 case FIREBALL_KNOSSOS_EFFECT: {
621 float percent_life = fb->time_elapsed / fb->total_time;
625 // Code to make effect grow/shrink.
626 float t = fb->time_elapsed;
628 if ( t < WARPHOLE_GROW_TIME ) {
629 rad = (float)pow(t/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
630 //rad = t*obj->radius/WARPHOLE_GROW_TIME;
631 //mprintf(( "T=%.2f, Rad = %.2f\n", t, rad ));
632 } else if ( t < fb->total_time - WARPHOLE_GROW_TIME ) {
635 rad = (float)pow((fb->total_time - t)/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
636 //rad = (fb->total_time - t )*obj->radius/WARPHOLE_GROW_TIME;
641 warpin_render(&obj->orient, &obj->pos, Fireballs[num].current_bitmap, rad, percent_life, obj->radius );
651 // -----------------------------------------------------------------
654 // Delete a fireball. Called by object_delete() code... do not call
657 void fireball_delete( object * obj )
663 fb = &Fireballs[num];
665 SDL_assert( fb->objnum == OBJ_INDEX(obj));
667 Fireballs[num].objnum = -1;
669 SDL_assert( Num_fireballs >= 0 );
672 // -----------------------------------------------------------------
673 // fireball_delete_all()
675 // Delete all active fireballs, by calling obj_delete directly.
677 void fireball_delete_all()
682 for ( i = 0; i < MAX_FIREBALLS; i++ ) {
684 if ( fb->objnum != -1 ) {
685 obj_delete(fb->objnum);
690 void fireball_set_framenum(int num)
697 fb = &Fireballs[num];
698 fd = &Fireball_info[Fireballs[num].fireball_info_index];
702 if((fb->lod >= 0) && (fb->lod < fd->lod_count)){
703 fl = &Fireball_info[Fireballs[num].fireball_info_index].lod[(int)fb->lod];
710 if ( fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT ) {
711 float total_time = i2fl(fl->num_frames) / fl->fps; // in seconds
713 framenum = fl2i(fb->time_elapsed * fl->num_frames / total_time + 0.5);
715 if ( framenum < 0 ) framenum = 0;
717 framenum = framenum % fl->num_frames;
720 // warp out effect plays backwards
721 framenum = fl->num_frames-framenum-1;
722 fb->current_bitmap = fl->bitmap_id + framenum;
724 fb->current_bitmap = fl->bitmap_id + framenum;
728 framenum = fl2i(fb->time_elapsed / fb->total_time * fl->num_frames + 0.5);
730 // ensure we don't go past the number of frames of animation
731 if ( framenum > (fl->num_frames-1) ) {
732 framenum = (fl->num_frames-1);
733 Objects[fb->objnum].flags |= OF_SHOULD_BE_DEAD;
736 if ( framenum < 0 ) framenum = 0;
737 fb->current_bitmap = fl->bitmap_id + framenum;
741 int fireball_is_perishable(object * obj)
748 objnum = OBJ_INDEX(obj);
749 SDL_assert( Fireballs[num].objnum == objnum );
751 fb = &Fireballs[num];
753 if ( fb->fireball_info_index == FIREBALL_EXPLOSION_MEDIUM )
756 if ( !((fb->fireball_info_index == FIREBALL_WARP_EFFECT) || (fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT)) ) {
757 if ( !(obj->flags & OF_WAS_RENDERED)) {
766 // -----------------------------------------------------------------
767 // fireball_free_one()
769 // There are too many fireballs, so delete the oldest small one
770 // to free up a slot. Returns the fireball slot freed.
772 int fireball_free_one()
777 int oldest_objnum = -1, oldest_slotnum = -1;
778 float lifeleft, oldest_lifeleft = 0.0f;
780 for ( i = 0; i < MAX_FIREBALLS; i++ ) {
783 // only remove the ones that aren't warp effects
784 if ( (fb->objnum>-1) && fireball_is_perishable(&Objects[fb->objnum]) ) {
786 lifeleft = fb->total_time - fb->time_elapsed;
787 if ( (oldest_objnum < 0) || (lifeleft < oldest_lifeleft) ) {
789 oldest_lifeleft = lifeleft;
790 oldest_objnum = fb->objnum;
796 if ( oldest_objnum > -1 ) {
797 obj_delete(oldest_objnum);
799 return oldest_slotnum;
802 // broke fireball_move into fireball_process_pre and fireball_process_post as was done
803 // with all *_move functions on 8/13 by Mike K. and Mark A.
804 void fireball_process_pre( object *objp, float frame_time)
808 int fireball_is_warp(object * obj)
814 objnum = OBJ_INDEX(obj);
815 SDL_assert( Fireballs[num].objnum == objnum );
817 fb = &Fireballs[num];
819 if ( fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT)
825 // mabye play sound effect for warp hole closing
826 void fireball_maybe_play_warp_close_sound(fireball *fb)
830 // If not a warphole fireball, do a quick out
831 if ( !(fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT)) {
835 // If the warhole close sound has been played, don't play it again!
836 if ( fb->flags & FBF_WARP_CLOSE_SOUND_PLAYED ) {
840 life_left = fb->total_time - fb->time_elapsed;
842 if ( life_left < WARPHOLE_GROW_TIME ) {
843 fireball_play_warphole_close_sound(fb);
844 fb->flags |= FBF_WARP_CLOSE_SOUND_PLAYED;
848 MONITOR( NumFireballs );
850 void fireball_process_post(object * obj, float frame_time)
855 MONITOR_INC( NumFireballs, 1 );
858 objnum = OBJ_INDEX(obj);
859 SDL_assert( Fireballs[num].objnum == objnum );
861 fb = &Fireballs[num];
863 fb->time_elapsed += frame_time;
864 if ( fb->time_elapsed > fb->total_time ) {
865 obj->flags |= OF_SHOULD_BE_DEAD;
868 fireball_maybe_play_warp_close_sound(fb);
870 fireball_set_framenum(num);
873 // Returns life left of a fireball in seconds
874 float fireball_lifeleft( object *obj )
880 objnum = OBJ_INDEX(obj);
881 SDL_assert( Fireballs[num].objnum == objnum );
883 fb = &Fireballs[num];
885 return fb->total_time - fb->time_elapsed;
888 // Returns life left of a fireball in percent
889 float fireball_lifeleft_percent( object *obj )
895 objnum = OBJ_INDEX(obj);
896 SDL_assert( Fireballs[num].objnum == objnum );
898 fb = &Fireballs[num];
900 return (fb->total_time - fb->time_elapsed) / fb->total_time;
903 // determine LOD to use
904 int fireball_get_lod(vector *pos, fireball_info *fd, float size)
907 int x, y, w, h, bm_size;
918 extern float Viewer_zoom;
925 g3_set_view_matrix(&Eye_position, &Eye_matrix, Viewer_zoom);
927 // get extents of the rotated bitmap
928 g3_rotate_vertex(&v, pos);
930 // if vertex is behind, find size if in front, then drop down 1 LOD
931 if (v.codes & CC_BEHIND) {
932 float dist = vm_vec_dist_quick(&Eye_position, pos);
936 vm_vec_scale_add(&temp, &Eye_position, &Eye_matrix.v.fvec, dist);
937 g3_rotate_vertex(&v, &temp);
939 // if still behind, bail and go with default
940 if (v.codes & CC_BEHIND) {
945 if(!g3_get_bitmap_dims(fd->lod[0].bitmap_id, &v, size, &x, &y, &w, &h, &bm_size)) {
946 if (Detail.hardware_textures == 4) {
950 } else if(w <= bm_size/2){
952 } else if(w <= (1.56*bm_size)){
958 // less aggressive LOD for lower detail settings
961 } else if(w <= bm_size/3){
963 } else if(w <= (1.2*bm_size)){
971 // if it's behind, bump up LOD by 1
981 // return the best lod
982 return min(ret_lod, fd->lod_count - 1);
985 // Create a fireball, return object index.
986 int fireball_create( vector * pos, int fireball_type, int parent_obj, float size, int reverse, vector *velocity, float warp_lifetime, int ship_class, matrix *orient_override, int low_res)
988 int n, objnum, fb_lod;
994 SDL_assert( fireball_type > -1 );
995 SDL_assert( fireball_type < MAX_FIREBALL_TYPES );
997 fd = &Fireball_info[fireball_type];
999 if ( !(Game_detail_flags & DETAIL_FLAG_FIREBALLS) ) {
1000 if ( !((fireball_type == FIREBALL_WARP_EFFECT) || (fireball_type == FIREBALL_KNOSSOS_EFFECT)) ) {
1005 if ( (Num_fireballs >= MAX_FIREBALLS) || (num_objects >= MAX_OBJECTS) ) {
1006 // who cares if we don't create a spark.
1007 // JAS - Should this code be in? Is it better to remove an old spark
1008 // and start a new one, or just not start the new one?
1009 //if ( fd->type == FIREBALL_TYPE_SMALL ) {
1013 //mprintf(( "Out of fireball slots, trying to free one up!\n" ));
1014 // out of slots, so free one up.
1015 n = fireball_free_one();
1017 // If there's still no free slots, then exit
1018 //mprintf(( "ERROR: Couldn't free one up!!\n" ));
1021 //mprintf(( "Freed one up just fine!!\n" ));
1024 for ( n = 0; n < MAX_FIREBALLS; n++ ) {
1025 if ( Fireballs[n].objnum < 0 ) {
1029 SDL_assert( n != MAX_FIREBALLS );
1034 // get an lod to use
1035 fb_lod = fireball_get_lod(pos, fd, size);
1037 // change lod if low res is desired
1040 fb_lod = min(fb_lod, fd->lod_count - 1);
1043 // if this is a warpout fireball, never go higher than LOD 1
1044 if(fireball_type == FIREBALL_WARP_EFFECT){
1052 fl = &fd->lod[fb_lod];
1054 fb->lod = (char)fb_lod;
1057 if(orient_override != NULL){
1058 orient = *orient_override;
1060 if ( parent_obj < 0 ) {
1061 orient = vmd_identity_matrix;
1063 orient = Objects[parent_obj].orient;
1067 objnum = obj_create(OBJ_FIREBALL, parent_obj, n, &orient, pos, size, OF_RENDERS);
1070 Int3(); // Get John, we ran out of objects for fireballs
1074 obj = &Objects[objnum];
1076 fb->fireball_info_index = fireball_type;
1077 fb->time_elapsed = 0.0f;
1078 fb->objnum = objnum;
1079 fb->current_bitmap = -1;
1081 switch( fb->fireball_info_index ) {
1083 case FIREBALL_EXPLOSION_MEDIUM:
1084 fb->orient = (myrand()>>8) & 7; // 0 - 7
1087 case FIREBALL_EXPLOSION_LARGE1:
1088 case FIREBALL_EXPLOSION_LARGE2:
1089 // case FIREBALL_EXPLOSION_LARGE3:
1090 case FIREBALL_ASTEROID:
1091 fb->orient = (myrand()>>8) % 360; // 0 - 359
1094 case FIREBALL_WARP_EFFECT:
1095 case FIREBALL_KNOSSOS_EFFECT:
1096 // Play sound effect for warp hole opening up
1097 fireball_play_warphole_open_sound(ship_class, fb);
1102 // if warp out, then reverse the orientation
1103 vm_vec_scale( &obj->orient.v.fvec, -1.0f ); // Reverse the forward vector
1104 vm_vec_scale( &obj->orient.v.rvec, -1.0f ); // Reverse the right vector
1115 if ( fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT ) {
1116 SDL_assert( warp_lifetime > 4.0f ); // Warp lifetime must be at least 4 seconds!
1117 fb->total_time = warp_lifetime; // in seconds
1119 fb->total_time = i2fl(fl->num_frames) / fl->fps; // in seconds
1122 fireball_set_framenum(n);
1125 // Make the explosion move at a constant velocity.
1126 obj->flags |= OF_PHYSICS;
1127 obj->phys_info.mass = 1.0f;
1128 obj->phys_info.side_slip_time_const = 0.0f;
1129 obj->phys_info.rotdamp = 0.0f;
1130 obj->phys_info.vel = *velocity;
1131 obj->phys_info.max_vel = *velocity;
1132 obj->phys_info.desired_vel = *velocity;
1133 obj->phys_info.speed = vm_vec_mag(velocity);
1134 vm_vec_zero(&obj->phys_info.max_rotvel);
1141 // -----------------------------------------------------------------
1144 // Called at game shutdown to clean up the fireball system
1146 void fireball_close()
1148 if ( !fireballs_inited )
1151 fireball_delete_all();
1154 // -----------------------------------------------------------------
1155 // fireball_level_close()
1157 // Called when a mission ends... frees up any animations that might
1158 // be partially played
1160 void fireball_level_close()
1162 if ( !fireballs_inited )
1165 fireball_delete_all();
1168 void fireballs_page_in()
1173 for ( i = 0; i < MAX_FIREBALL_TYPES ; i++ ) {
1174 fd = &Fireball_info[i];
1176 for(idx=0; idx<fd->lod_count; idx++){
1177 bm_page_in_texture( fd->lod[idx].bitmap_id, fd->lod[idx].num_frames );
1181 bm_page_in_texture( Warp_glow_bitmap );