2 * $Logfile: /Freespace2/code/Fireball/FireBalls.cpp $
7 * Code to move, render and otherwise deal with fireballs.
10 * Revision 1.1 2002/05/03 03:28:08 root
14 * 19 9/14/99 1:27a Andsager
15 * Better LOD for fireballs when behind. Move point ahead to get vertex
16 * ahead and then find size.
18 * 18 9/12/99 11:42p Dave
20 * 17 9/13/99 10:09a Andsager
21 * Add debug console commands to lower model render detail and fireball
22 * LOD for big ship explosiosns.
24 * 16 9/09/99 8:53p Dave
25 * Fixed multiplayer degenerate orientation case problem. Make sure warp
26 * effect never goes lower than LOD 1.
28 * 15 9/07/99 12:20a Andsager
29 * LOD less agressive at lower hardware detail level
31 * 14 9/06/99 6:47p Jamesa
34 * 13 9/06/99 3:23p Andsager
35 * Make fireball and weapon expl ani LOD choice look at resolution of the
38 * 12 9/01/99 10:09a Dave
41 * 11 8/31/99 10:13p Andsager
42 * Add Knossos warp effect fireball
44 * 10 8/30/99 9:59a Dave
45 * Removed explosion LOD stuff.
47 * 9 8/28/99 4:54p Dave
48 * Fixed directives display for multiplayer clients for wings with
49 * multiple waves. Fixed hud threat indicator rendering color.
51 * 8 8/27/99 9:07p Dave
52 * LOD explosions. Improved beam weapon accuracy.
54 * 7 7/09/99 5:54p Dave
55 * Seperated cruiser types into individual types. Added tons of new
56 * briefing icons. Campaign screen.
58 * 6 4/28/99 11:13p Dave
59 * Temporary checkin of artillery code.
61 * 5 4/23/99 12:01p Johnson
64 * 4 11/05/98 5:55p Dave
65 * Big pass at reducing #includes
67 * 3 10/23/98 3:51p Dave
68 * Full support for tstrings.tbl and foreign languages. All that remains
69 * is to make it active in Fred.
71 * 2 10/07/98 10:52a Dave
74 * 1 10/07/98 10:48a Dave
76 * 75 5/18/98 2:49p Lawrance
77 * Allow up to double instance of sound for warp holes
79 * 74 5/15/98 3:54p John
80 * Added code so that only "perishable" fireballs get removed.
82 * 73 4/15/98 9:42a Adam
83 * added 2 more explosion types (1, actually, but placeholder for 2)
85 * 72 4/12/98 9:56a John
86 * Made lighting detail flags work. Made explosions cast light on
89 * 71 4/09/98 7:58p John
90 * Cleaned up tmapper code a bit. Put NDEBUG around some ndebug stuff.
91 * Took out XPARENT flag settings in all the alpha-blended texture stuff.
93 * 70 3/31/98 5:11p John
94 * Removed demo/save/restore. Made NDEBUG defined compile. Removed a
95 * bunch of debug stuff out of player file. Made model code be able to
96 * unload models and malloc out only however many models are needed.
98 * 69 3/30/98 4:02p John
99 * Made machines with < 32 MB of RAM use every other frame of certain
100 * bitmaps. Put in code to keep track of how much RAM we've malloc'd.
102 * 68 3/29/98 12:39p John
103 * Made warp in glow page in
105 * 67 3/27/98 2:17p Lawrance
106 * Don't play warphole closing for non-captial sized warp effects
108 * 66 3/26/98 5:44p Lawrance
109 * take out debug comments for warphole sounds playing
111 * 65 3/26/98 5:21p John
112 * Added new code to preload all bitmaps at the start of a level.
113 * Commented it out, though.
115 * 64 3/25/98 5:30p Lawrance
116 * Fix bug that was not playing wormhole open sound effect at correct
119 * 63 3/25/98 10:56a Lawrance
120 * Make a sound for warphole close as well as warphole open, move to
123 * 62 3/18/98 12:36p John
124 * Made hardware have nicer looking warp effect
126 * 61 3/18/98 12:01p John
127 * Made warp grid grow faster
129 * 60 2/26/98 10:07p Hoffoss
130 * Rewrote state saving and restoring to fix bugs and simplify the code.
132 * 59 2/22/98 12:19p John
133 * Externalized some strings
135 * 58 2/19/98 4:32p Lawrance
136 * Add asteroid explosion
138 * 57 2/12/98 11:53p Lawrance
139 * comment out use of current_frame since not used anywhere
141 * 56 2/05/98 9:21p John
142 * Some new Direct3D code. Added code to monitor a ton of stuff in the
145 * 55 1/23/98 5:06p John
146 * Took L out of vertex structure used B (blue) instead. Took all small
147 * fireballs out of fireball types and used particles instead. Fixed some
148 * debris explosion things. Restructured fireball code. Restructured
149 * some lighting code. Made dynamic lighting on by default. Made groups
150 * of lasers only cast one light. Made fireballs not cast light.
152 * 54 1/19/98 9:37p Allender
153 * Great Compiler Warning Purge of Jan, 1998. Used pragma's in a couple
154 * of places since I was unsure of what to do with code.
156 * 53 1/15/98 4:58p John
157 * Made warp effect use a looping ani. Made the scaling up & down be in
160 * 52 1/15/98 2:32p John
161 * Added code to optionally take a velocity for a fireball.
163 * 51 1/11/98 2:15p John
164 * Changed a lot of stuff that had to do with bitmap loading. Made cfile
165 * not do callbacks, I put that in global code. Made only bitmaps that
166 * need to load for a level load.
168 * 50 1/02/98 5:04p John
169 * Several explosion related changes. Made fireballs not be used as
170 * ani's. Made ship spark system expell particles. Took away impact
171 * explosion for weapon hitting ship... this needs to get added to weapon
172 * info and makes shield hit more obvious. Only make sparks when hit
175 * 49 12/31/97 4:48p John
176 * added some debug info
178 * 48 12/30/97 6:44p John
179 * Made g3_Draw_bitmap functions account for aspect of bitmap.
181 * 47 12/08/97 11:15a John
182 * added parameter to warpout for life.
184 * 46 12/02/97 3:59p John
185 * Added first rev of thruster glow, along with variable levels of
186 * translucency, which retquired some restructing of palman.
188 * 45 11/30/97 2:03p John
189 * made warp effect not use an ani for height map.
191 * 44 11/16/97 12:20p John
192 * added code to make ships instantly warp in/out if fireball effect
193 * fails. But, made it so the fireball effect will kill off old sparks
194 * so it can go, so this should never happen.
196 * 43 11/16/97 10:48a John
197 * added code to remove the oldest fireball if there weren't enough slots
200 * 42 11/01/97 1:49p John
201 * added code to page fireballs in during level load. Made player warpout
202 * use Adam's new camera movement pattern. Make ships docked to warping
203 * out ships render correctly.
205 * 41 10/29/97 5:05p John
206 * Changed dynamic lighting to only rotate and calculate lighting for
207 * point lights that are close to an object. Changed lower framerate cap
210 * 40 10/24/97 6:24p John
211 * added code to return the life left of a fireball
213 * 39 9/14/97 4:49p Lawrance
214 * add some demo debugging code
216 * 38 9/12/97 4:02p John
217 * put in ship warp out effect.
218 * put in dynamic lighting for warp in/out
220 * 37 9/09/97 4:49p John
221 * Almost done ship warp in code
223 * 36 9/08/97 8:39a John
224 * added in code structure for grid
226 * 35 9/03/97 5:04p Lawrance
227 * add error checking when restoring structs
229 * 34 9/03/97 4:32p John
230 * changed bmpman to only accept ani and pcx's. made passing .pcx or .ani
231 * to bm_load functions not needed. Made bmpman keep track of palettes
232 * for bitmaps not mapped into game palettes.
234 * 33 8/29/97 2:26p John
235 * first rev of ship warp in effect. Nothing more than a fireball inside
236 * of freespace, but textest.cpp contains the correct effect code that
237 * needs to be transferred into the game next.
239 * 32 8/21/97 5:11p Lawrance
240 * frame numbering for ANI's now is from 0 -> total_frames-1.
242 * 31 8/13/97 9:50p Allender
243 * split *_move into *_process_pre and *_process_post functions.
244 * process_pre functions called before object is moved. _process_post
245 * functions called after object is moved. Reordered code in ship_post
246 * and weapon_post for multiplayer
248 * 30 8/13/97 12:06p Lawrance
249 * supporting multiple types of fireball explosions
251 * 29 8/05/97 10:18a Lawrance
252 * my_rand() being used temporarily instead of rand()
254 * 28 7/31/97 5:55p John
255 * made so you pass flags to obj_create.
256 * Added new collision code that ignores any pairs that will never
259 * 27 7/24/97 9:54a Lawrance
260 * don't free fireball system if not inited
262 * 26 7/23/97 11:35a Lawrance
263 * ensure fireball animations are always freed properly
265 * 25 7/21/97 11:41a Lawrance
266 * clean up fireballs at the end of each level
268 * 24 7/20/97 6:58p Lawrance
269 * call anim_get_frame() to take advantage of key-framed animation
271 * 23 7/11/97 3:57p John
272 * made fireballs translucent. alpha=1.3x intesity. only for d3d.
274 * 22 7/11/97 12:08p John
275 * made fireballs randomly be rotated.
277 * 21 7/11/97 11:54a John
278 * added rotated 3d bitmaps.
280 * 20 7/11/97 11:19a Lawrance
281 * fix mem leaks, move save code from State.cpp here
283 * 19 7/10/97 1:51p Lawrance
284 * sorting anim fireballs
286 * 18 6/24/97 6:21p John
287 * added detail flags.
288 * sped up motion debris system a bit.
290 * 17 5/14/97 4:08p Lawrance
291 * removing my_index from game arrays
293 * 16 5/05/97 10:40p Mike
294 * Make missile exhaust trails look a tad nicer.
296 * 15 3/11/97 10:47p Mike
297 * Add a slew of secondary weapons.
298 * Support exhaust blobs.
299 * Add weapons that spawn weapons.
300 * Add remotely detonatable weapons.
301 * Add heat-seeking missiles.
303 * 14 2/17/97 5:18p John
304 * Added a bunch of RCS headers to a bunch of old files that don't have
320 #include "floating.h"
322 #include "lighting.h"
325 #include "systemvars.h"
326 #include "fireballs.h"
327 #include "linklist.h"
329 #include "localize.h"
331 #define WARPHOLE_GROW_TIME (1.5f) // time for warphole to reach max size (also time to shrink to nothing once it begins to shrink)
333 #define MAX_FIREBALL_LOD 4
335 typedef struct fireball_lod {
336 char filename[MAX_FILENAME_LEN];
342 typedef struct fireball_info {
347 // flag values for fireball struct flags member
348 #define FBF_WARP_CLOSE_SOUND_PLAYED (1<<0)
349 #define FBF_WARP_CAPTIAL_SIZE (1<<1)
350 #define FBF_WARP_CRUISER_SIZE (1<<2)
352 typedef struct fireball {
353 int objnum; // If -1 this object is unused
354 int fireball_info_index; // Index into Fireball_info array
356 int orient; // For fireballs, which orientation. For warps, 0 is warpin, 1 is warpout
357 int flags; // see #define FBF_*
358 char lod; // current LOD
359 float time_elapsed; // in seconds
360 float total_time; // total lifetime of animation in seconds
363 #define MAX_FIREBALLS 200
365 fireball Fireballs[MAX_FIREBALLS];
367 fireball_info Fireball_info[MAX_FIREBALL_TYPES];
369 int Num_fireballs = 0;
371 int fireballs_inited = 0;
373 int Warp_glow_bitmap = -1;
375 #define FB_INDEX(fb) (fb-Fireballs)
377 // play warp in sound for warp effect
378 void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
381 float range_multiplier = 1.0f;
382 object *fireball_objp;
384 Assert((fb != NULL) && (fb->objnum >= 0));
385 if((fb == NULL) || (fb->objnum < 0)){
388 fireball_objp = &Objects[fb->objnum];
390 sound_index = SND_WARP_IN;
392 if((ship_class >= 0) && (ship_class < Num_ship_types)){
393 if ( Ship_info[ship_class].flags & SIF_HUGE_SHIP ) {
394 sound_index = SND_CAPITAL_WARP_IN;
395 fb->flags |= FBF_WARP_CAPTIAL_SIZE;
396 } else if ( Ship_info[ship_class].flags & SIF_BIG_SHIP ) {
397 range_multiplier = 6.0f;
398 fb->flags |= FBF_WARP_CRUISER_SIZE;
402 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
405 // play warp out sound for warp effect
406 void fireball_play_warphole_close_sound(fireball *fb)
410 object *fireball_objp;
412 fireball_objp = &Objects[fb->objnum];
414 sound_index = SND_WARP_OUT;
416 if ( fb->flags & FBF_WARP_CAPTIAL_SIZE ) {
417 sound_index = SND_CAPITAL_WARP_OUT;
419 // AL 27-3-98: Decided that warphole closing is only required for captial ship sized warp effects.
423 snd_play_3d(&Snds[sound_index], &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
426 void fireball_parse_tbl()
429 char base_filename[256] = "";
434 if ((rval = setjmp(parse_abort)) != 0) {
435 Error(LOCATION, "Unable to parse fireball.tbl! Code = %i.\n", rval);
438 read_file_text(NOX("fireball.tbl"));
443 required_string("#Start");
444 while (required_string_either("#End","$Name:")) {
445 Assert( ntypes < MAX_FIREBALL_TYPES);
448 required_string("$Name:");
449 stuff_string(base_filename, F_NAME, NULL);
451 // # of lod levels - make sure old fireball.tbl is compatible
452 Fireball_info[ntypes].lod_count = 1;
453 if(optional_string("$LOD:")){
454 stuff_int(&Fireball_info[ntypes].lod_count);
457 // stuff default filename
458 strcpy(Fireball_info[ntypes].lod[0].filename, base_filename);
460 // stuff LOD level filenames
461 for(idx=1; idx<Fireball_info[ntypes].lod_count; idx++){
462 if(idx >= MAX_FIREBALL_LOD){
466 sprintf(Fireball_info[ntypes].lod[idx].filename, "%s_%d", base_filename, idx);
471 required_string("#End");
473 // close localization
478 void fireball_load_data()
483 for ( i = 0; i < MAX_FIREBALL_TYPES; i++ ) {
484 fd = &Fireball_info[i];
486 for(idx=0; idx<fd->lod_count; idx++){
487 fd->lod[idx].bitmap_id = bm_load_animation( fd->lod[idx].filename, &fd->lod[idx].num_frames, &fd->lod[idx].fps, 1 );
488 if ( fd->lod[idx].bitmap_id < 0 ) {
489 Error(LOCATION, "Could not load %s anim file\n", fd->lod[idx].filename);
494 if ( Warp_glow_bitmap == -1 ) {
495 Warp_glow_bitmap = bm_load( NOX("warpglow01") );
500 void fireball_preload()
502 // Do nothing. Called before level init, this used to page in warp effect.
503 // Not needed with new BmpMan system.
506 // This will get called at the start of each level.
511 if ( !fireballs_inited ) {
512 fireballs_inited = 1;
514 // Do all the processing that happens only once
515 fireball_parse_tbl();
516 fireball_load_data();
519 // Reset everything between levels
521 for (i=0; i<MAX_FIREBALLS; i++ ) {
522 Fireballs[i].objnum = -1;
528 MONITOR( NumFireballsRend );
530 //extern int tcache_hit(int);
531 //extern int Glide_expl_textures_in_frame;
532 //extern float Glide_avg_exp_text_per_sec;
534 void fireball_render(object * obj)
541 MONITOR_INC( NumFireballsRend, 1 );
544 fb = &Fireballs[num];
545 fd = &Fireball_info[fb->fireball_info_index];
547 if ( Fireballs[num].current_bitmap < 0 )
550 // gr_set_color( 0, 100, 0 );
551 // g3_draw_sphere_ez( &obj->pos, obj->radius );
555 if(The_mission.flags & MISSION_FLAG_FULLNEB){
556 gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
559 g3_rotate_vertex(&p, &obj->pos );
561 switch( fb->fireball_info_index ) {
563 case FIREBALL_EXPLOSION_MEDIUM:
564 gr_set_bitmap(Fireballs[num].current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f );
565 g3_draw_bitmap(&p, fb->orient, obj->radius, TMAP_FLAG_TEXTURED );
568 case FIREBALL_EXPLOSION_LARGE1:
569 case FIREBALL_EXPLOSION_LARGE2:
570 // case FIREBALL_EXPLOSION_LARGE3:
572 if (!tcache_hit(Fireballs[num].current_bitmap)) {
573 // if we're over 200k exp vram upload this frame, change to lower lod
574 if (Glide_expl_textures_in_frame > 1024 * 200) {
575 // change fireball instance to lower LOD or don't draw
577 // get current LOD and number of LODs
578 int cur_lod = Fireballs[num].lod;
579 int num_lods = Fireball_info[Fireballs[num].fireball_info_index].lod_count;
581 if (num_lods > cur_lod+1) {
583 int frame = Fireballs[num].current_bitmap - Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod].bitmap_id;
584 Fireballs[num].lod++;
585 Fireballs[num].current_bitmap = Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod+1].bitmap_id + frame;
586 mprintf(("bumping down lod for fireball %s, frame %d\n", Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod].filename, frame));
591 case FIREBALL_ASTEROID:
592 // Make the big explosions rotate with the viewer.
593 gr_set_bitmap(Fireballs[num].current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f );
594 g3_draw_rotated_bitmap(&p, (i2fl(fb->orient)*PI)/180.0f, obj->radius, TMAP_FLAG_TEXTURED );
597 case FIREBALL_WARP_EFFECT:
598 case FIREBALL_KNOSSOS_EFFECT: {
600 float percent_life = fb->time_elapsed / fb->total_time;
604 // Code to make effect grow/shrink.
605 float t = fb->time_elapsed;
607 if ( t < WARPHOLE_GROW_TIME ) {
608 rad = (float)pow(t/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
609 //rad = t*obj->radius/WARPHOLE_GROW_TIME;
610 //mprintf(( "T=%.2f, Rad = %.2f\n", t, rad ));
611 } else if ( t < fb->total_time - WARPHOLE_GROW_TIME ) {
614 rad = (float)pow((fb->total_time - t)/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
615 //rad = (fb->total_time - t )*obj->radius/WARPHOLE_GROW_TIME;
620 warpin_render(&obj->orient, &obj->pos, Fireballs[num].current_bitmap, rad, percent_life, obj->radius );
630 // -----------------------------------------------------------------
633 // Delete a fireball. Called by object_delete() code... do not call
636 void fireball_delete( object * obj )
642 fb = &Fireballs[num];
644 Assert( fb->objnum == OBJ_INDEX(obj));
646 Fireballs[num].objnum = -1;
648 Assert( Num_fireballs >= 0 );
651 // -----------------------------------------------------------------
652 // fireball_delete_all()
654 // Delete all active fireballs, by calling obj_delete directly.
656 void fireball_delete_all()
661 for ( i = 0; i < MAX_FIREBALLS; i++ ) {
663 if ( fb->objnum != -1 ) {
664 obj_delete(fb->objnum);
669 void fireball_set_framenum(int num)
676 fb = &Fireballs[num];
677 fd = &Fireball_info[Fireballs[num].fireball_info_index];
681 if((fb->lod >= 0) && (fb->lod < fd->lod_count)){
682 fl = &Fireball_info[Fireballs[num].fireball_info_index].lod[fb->lod];
689 if ( fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT ) {
690 float total_time = i2fl(fl->num_frames) / fl->fps; // in seconds
692 framenum = fl2i(fb->time_elapsed * fl->num_frames / total_time + 0.5);
694 if ( framenum < 0 ) framenum = 0;
696 framenum = framenum % fl->num_frames;
699 // warp out effect plays backwards
700 framenum = fl->num_frames-framenum-1;
701 fb->current_bitmap = fl->bitmap_id + framenum;
703 fb->current_bitmap = fl->bitmap_id + framenum;
707 framenum = fl2i(fb->time_elapsed / fb->total_time * fl->num_frames + 0.5);
709 // ensure we don't go past the number of frames of animation
710 if ( framenum > (fl->num_frames-1) ) {
711 framenum = (fl->num_frames-1);
712 Objects[fb->objnum].flags |= OF_SHOULD_BE_DEAD;
715 if ( framenum < 0 ) framenum = 0;
716 fb->current_bitmap = fl->bitmap_id + framenum;
720 int fireball_is_perishable(object * obj)
727 objnum = OBJ_INDEX(obj);
728 Assert( Fireballs[num].objnum == objnum );
730 fb = &Fireballs[num];
732 if ( fb->fireball_info_index == FIREBALL_EXPLOSION_MEDIUM )
735 if ( !((fb->fireball_info_index == FIREBALL_WARP_EFFECT) || (fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT)) ) {
736 if ( !(obj->flags & OF_WAS_RENDERED)) {
745 // -----------------------------------------------------------------
746 // fireball_free_one()
748 // There are too many fireballs, so delete the oldest small one
749 // to free up a slot. Returns the fireball slot freed.
751 int fireball_free_one()
756 int oldest_objnum = -1, oldest_slotnum = -1;
757 float lifeleft, oldest_lifeleft = 0.0f;
759 for ( i = 0; i < MAX_FIREBALLS; i++ ) {
762 // only remove the ones that aren't warp effects
763 if ( (fb->objnum>-1) && fireball_is_perishable(&Objects[fb->objnum]) ) {
765 lifeleft = fb->total_time - fb->time_elapsed;
766 if ( (oldest_objnum < 0) || (lifeleft < oldest_lifeleft) ) {
768 oldest_lifeleft = lifeleft;
769 oldest_objnum = fb->objnum;
775 if ( oldest_objnum > -1 ) {
776 obj_delete(oldest_objnum);
778 return oldest_slotnum;
781 // broke fireball_move into fireball_process_pre and fireball_process_post as was done
782 // with all *_move functions on 8/13 by Mike K. and Mark A.
783 void fireball_process_pre( object *objp, float frame_time)
787 int fireball_is_warp(object * obj)
793 objnum = OBJ_INDEX(obj);
794 Assert( Fireballs[num].objnum == objnum );
796 fb = &Fireballs[num];
798 if ( fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT)
804 // mabye play sound effect for warp hole closing
805 void fireball_maybe_play_warp_close_sound(fireball *fb)
809 // If not a warphole fireball, do a quick out
810 if ( !(fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT)) {
814 // If the warhole close sound has been played, don't play it again!
815 if ( fb->flags & FBF_WARP_CLOSE_SOUND_PLAYED ) {
819 life_left = fb->total_time - fb->time_elapsed;
821 if ( life_left < WARPHOLE_GROW_TIME ) {
822 fireball_play_warphole_close_sound(fb);
823 fb->flags |= FBF_WARP_CLOSE_SOUND_PLAYED;
827 MONITOR( NumFireballs );
829 void fireball_process_post(object * obj, float frame_time)
834 MONITOR_INC( NumFireballs, 1 );
837 objnum = OBJ_INDEX(obj);
838 Assert( Fireballs[num].objnum == objnum );
840 fb = &Fireballs[num];
842 fb->time_elapsed += frame_time;
843 if ( fb->time_elapsed > fb->total_time ) {
844 obj->flags |= OF_SHOULD_BE_DEAD;
847 fireball_maybe_play_warp_close_sound(fb);
849 fireball_set_framenum(num);
852 // Returns life left of a fireball in seconds
853 float fireball_lifeleft( object *obj )
859 objnum = OBJ_INDEX(obj);
860 Assert( Fireballs[num].objnum == objnum );
862 fb = &Fireballs[num];
864 return fb->total_time - fb->time_elapsed;
867 // Returns life left of a fireball in percent
868 float fireball_lifeleft_percent( object *obj )
874 objnum = OBJ_INDEX(obj);
875 Assert( Fireballs[num].objnum == objnum );
877 fb = &Fireballs[num];
879 return (fb->total_time - fb->time_elapsed) / fb->total_time;
882 // determine LOD to use
883 int fireball_get_lod(vector *pos, fireball_info *fd, float size)
886 int x, y, w, h, bm_size;
897 extern float Viewer_zoom;
904 g3_set_view_matrix(&Eye_position, &Eye_matrix, Viewer_zoom);
906 // get extents of the rotated bitmap
907 g3_rotate_vertex(&v, pos);
909 // if vertex is behind, find size if in front, then drop down 1 LOD
910 if (v.codes & CC_BEHIND) {
911 float dist = vm_vec_dist_quick(&Eye_position, pos);
915 vm_vec_scale_add(&temp, &Eye_position, &Eye_matrix.fvec, dist);
916 g3_rotate_vertex(&v, &temp);
918 // if still behind, bail and go with default
919 if (v.codes & CC_BEHIND) {
924 if(!g3_get_bitmap_dims(fd->lod[0].bitmap_id, &v, size, &x, &y, &w, &h, &bm_size)) {
925 if (Detail.hardware_textures == 4) {
929 } else if(w <= bm_size/2){
931 } else if(w <= (1.56*bm_size)){
937 // less aggressive LOD for lower detail settings
940 } else if(w <= bm_size/3){
942 } else if(w <= (1.2*bm_size)){
950 // if it's behind, bump up LOD by 1
960 // return the best lod
961 return min(ret_lod, fd->lod_count - 1);
964 // Create a fireball, return object index.
965 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)
967 int n, objnum, fb_lod;
973 Assert( fireball_type > -1 );
974 Assert( fireball_type < MAX_FIREBALL_TYPES );
976 fd = &Fireball_info[fireball_type];
978 if ( !(Game_detail_flags & DETAIL_FLAG_FIREBALLS) ) {
979 if ( !((fireball_type == FIREBALL_WARP_EFFECT) || (fireball_type == FIREBALL_KNOSSOS_EFFECT)) ) {
984 if ( (Num_fireballs >= MAX_FIREBALLS) || (num_objects >= MAX_OBJECTS) ) {
985 // who cares if we don't create a spark.
986 // JAS - Should this code be in? Is it better to remove an old spark
987 // and start a new one, or just not start the new one?
988 //if ( fd->type == FIREBALL_TYPE_SMALL ) {
992 //mprintf(( "Out of fireball slots, trying to free one up!\n" ));
993 // out of slots, so free one up.
994 n = fireball_free_one();
996 // If there's still no free slots, then exit
997 //mprintf(( "ERROR: Couldn't free one up!!\n" ));
1000 //mprintf(( "Freed one up just fine!!\n" ));
1003 for ( n = 0; n < MAX_FIREBALLS; n++ ) {
1004 if ( Fireballs[n].objnum < 0 ) {
1008 Assert( n != MAX_FIREBALLS );
1013 // get an lod to use
1014 fb_lod = fireball_get_lod(pos, fd, size);
1016 // change lod if low res is desired
1019 fb_lod = min(fb_lod, fd->lod_count - 1);
1022 // if this is a warpout fireball, never go higher than LOD 1
1023 if(fireball_type == FIREBALL_WARP_EFFECT){
1031 fl = &fd->lod[fb_lod];
1033 fb->lod = (char)fb_lod;
1036 if(orient_override != NULL){
1037 orient = *orient_override;
1039 if ( parent_obj < 0 ) {
1040 orient = vmd_identity_matrix;
1042 orient = Objects[parent_obj].orient;
1046 objnum = obj_create(OBJ_FIREBALL, parent_obj, n, &orient, pos, size, OF_RENDERS);
1049 Int3(); // Get John, we ran out of objects for fireballs
1053 obj = &Objects[objnum];
1055 fb->fireball_info_index = fireball_type;
1056 fb->time_elapsed = 0.0f;
1057 fb->objnum = objnum;
1058 fb->current_bitmap = -1;
1060 switch( fb->fireball_info_index ) {
1062 case FIREBALL_EXPLOSION_MEDIUM:
1063 fb->orient = (myrand()>>8) & 7; // 0 - 7
1066 case FIREBALL_EXPLOSION_LARGE1:
1067 case FIREBALL_EXPLOSION_LARGE2:
1068 // case FIREBALL_EXPLOSION_LARGE3:
1069 case FIREBALL_ASTEROID:
1070 fb->orient = (myrand()>>8) % 360; // 0 - 359
1073 case FIREBALL_WARP_EFFECT:
1074 case FIREBALL_KNOSSOS_EFFECT:
1075 // Play sound effect for warp hole opening up
1076 fireball_play_warphole_open_sound(ship_class, fb);
1081 // if warp out, then reverse the orientation
1082 vm_vec_scale( &obj->orient.fvec, -1.0f ); // Reverse the forward vector
1083 vm_vec_scale( &obj->orient.rvec, -1.0f ); // Reverse the right vector
1094 if ( fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT ) {
1095 Assert( warp_lifetime > 4.0f ); // Warp lifetime must be at least 4 seconds!
1096 fb->total_time = warp_lifetime; // in seconds
1098 fb->total_time = i2fl(fl->num_frames) / fl->fps; // in seconds
1101 fireball_set_framenum(n);
1104 // Make the explosion move at a constant velocity.
1105 obj->flags |= OF_PHYSICS;
1106 obj->phys_info.mass = 1.0f;
1107 obj->phys_info.side_slip_time_const = 0.0f;
1108 obj->phys_info.rotdamp = 0.0f;
1109 obj->phys_info.vel = *velocity;
1110 obj->phys_info.max_vel = *velocity;
1111 obj->phys_info.desired_vel = *velocity;
1112 obj->phys_info.speed = vm_vec_mag(velocity);
1113 vm_vec_zero(&obj->phys_info.max_rotvel);
1120 // -----------------------------------------------------------------
1123 // Called at game shutdown to clean up the fireball system
1125 void fireball_close()
1127 if ( !fireballs_inited )
1130 fireball_delete_all();
1133 // -----------------------------------------------------------------
1134 // fireball_level_close()
1136 // Called when a mission ends... frees up any animations that might
1137 // be partially played
1139 void fireball_level_close()
1141 if ( !fireballs_inited )
1144 fireball_delete_all();
1147 void fireballs_page_in()
1152 for ( i = 0; i < MAX_FIREBALL_TYPES ; i++ ) {
1153 fd = &Fireball_info[i];
1155 for(idx=0; idx<fd->lod_count; idx++){
1156 bm_page_in_texture( fd->lod[idx].bitmap_id, fd->lod[idx].num_frames );
1160 bm_page_in_texture( Warp_glow_bitmap );