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)
431 int sound_index = SND_WARP_OUT;
433 object *fireball_objp;
435 fireball_objp = &Objects[fb->objnum];
437 if ( fb->flags & FBF_WARP_CAPTIAL_SIZE ) {
438 sound_index = SND_CAPITAL_WARP_OUT;
440 // AL 27-3-98: Decided that warphole closing is only required for captial ship sized warp effects.
444 snd_play_3d(&Snds[sound_index], &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
447 void fireball_parse_tbl()
450 char base_filename[256] = "";
456 read_file_text(NOX("fireball.tbl"));
460 required_string("#Start");
461 while (required_string_either("#End","$Name:")) {
462 SDL_assert( ntypes < MAX_FIREBALL_TYPES);
465 required_string("$Name:");
466 stuff_string(base_filename, F_NAME, NULL);
468 // # of lod levels - make sure old fireball.tbl is compatible
469 Fireball_info[ntypes].lod_count = 1;
470 if(optional_string("$LOD:")){
471 stuff_int(&Fireball_info[ntypes].lod_count);
474 // stuff default filename
475 SDL_strlcpy(Fireball_info[ntypes].lod[0].filename, base_filename, SDL_arraysize(Fireball_info[0].lod[0].filename));
477 // stuff LOD level filenames
478 for(idx=1; idx<Fireball_info[ntypes].lod_count; idx++){
479 if(idx >= MAX_FIREBALL_LOD){
483 SDL_snprintf(Fireball_info[ntypes].lod[idx].filename, MAX_FILENAME_LEN, "%s_%d", base_filename, idx);
488 required_string("#End");
489 } catch (parse_error_t rval) {
490 Error(LOCATION, "Unable to parse fireball.tbl! Code = %i.\n", (int)rval);
494 // close localization
499 void fireball_load_data()
504 for ( i = 0; i < MAX_FIREBALL_TYPES; i++ ) {
505 fd = &Fireball_info[i];
507 for(idx=0; idx<fd->lod_count; idx++){
508 fd->lod[idx].bitmap_id = bm_load_animation( fd->lod[idx].filename, &fd->lod[idx].num_frames, &fd->lod[idx].fps, 1 );
509 if ( fd->lod[idx].bitmap_id < 0 ) {
510 Error(LOCATION, "Could not load %s anim file\n", fd->lod[idx].filename);
515 if ( Warp_glow_bitmap == -1 ) {
516 Warp_glow_bitmap = bm_load( NOX("warpglow01") );
521 void fireball_preload()
523 // Do nothing. Called before level init, this used to page in warp effect.
524 // Not needed with new BmpMan system.
527 // This will get called at the start of each level.
532 if ( !fireballs_inited ) {
533 fireballs_inited = 1;
535 // Do all the processing that happens only once
536 fireball_parse_tbl();
537 fireball_load_data();
540 // Reset everything between levels
542 for (i=0; i<MAX_FIREBALLS; i++ ) {
543 Fireballs[i].objnum = -1;
549 MONITOR( NumFireballsRend );
551 //extern int tcache_hit(int);
552 //extern int Glide_expl_textures_in_frame;
553 //extern float Glide_avg_exp_text_per_sec;
555 void fireball_render(object * obj)
561 MONITOR_INC( NumFireballsRend, 1 );
564 fb = &Fireballs[num];
566 if ( Fireballs[num].current_bitmap < 0 )
569 // gr_set_color( 0, 100, 0 );
570 // g3_draw_sphere_ez( &obj->pos, obj->radius );
574 if(The_mission.flags & MISSION_FLAG_FULLNEB){
575 gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0, -1.0f, -1.0f);
578 g3_rotate_vertex(&p, &obj->pos );
580 switch( fb->fireball_info_index ) {
582 case FIREBALL_EXPLOSION_MEDIUM:
583 gr_set_bitmap(Fireballs[num].current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f, -1, -1 );
584 g3_draw_bitmap(&p, fb->orient, obj->radius, TMAP_FLAG_TEXTURED );
587 case FIREBALL_EXPLOSION_LARGE1:
588 case FIREBALL_EXPLOSION_LARGE2:
589 // case FIREBALL_EXPLOSION_LARGE3:
591 if (!tcache_hit(Fireballs[num].current_bitmap)) {
592 // if we're over 200k exp vram upload this frame, change to lower lod
593 if (Glide_expl_textures_in_frame > 1024 * 200) {
594 // change fireball instance to lower LOD or don't draw
596 // get current LOD and number of LODs
597 int cur_lod = Fireballs[num].lod;
598 int num_lods = Fireball_info[Fireballs[num].fireball_info_index].lod_count;
600 if (num_lods > cur_lod+1) {
602 int frame = Fireballs[num].current_bitmap - Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod].bitmap_id;
603 Fireballs[num].lod++;
604 Fireballs[num].current_bitmap = Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod+1].bitmap_id + frame;
605 mprintf(("bumping down lod for fireball %s, frame %d\n", Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod].filename, frame));
610 case FIREBALL_ASTEROID:
611 // Make the big explosions rotate with the viewer.
612 gr_set_bitmap(Fireballs[num].current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f, -1, -1 );
613 g3_draw_rotated_bitmap(&p, (i2fl(fb->orient)*PI)/180.0f, obj->radius, TMAP_FLAG_TEXTURED );
616 case FIREBALL_WARP_EFFECT:
617 case FIREBALL_KNOSSOS_EFFECT: {
619 float percent_life = fb->time_elapsed / fb->total_time;
623 // Code to make effect grow/shrink.
624 float t = fb->time_elapsed;
626 if ( t < WARPHOLE_GROW_TIME ) {
627 rad = (float)pow(t/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
628 //rad = t*obj->radius/WARPHOLE_GROW_TIME;
629 //mprintf(( "T=%.2f, Rad = %.2f\n", t, rad ));
630 } else if ( t < fb->total_time - WARPHOLE_GROW_TIME ) {
633 rad = (float)pow((fb->total_time - t)/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
634 //rad = (fb->total_time - t )*obj->radius/WARPHOLE_GROW_TIME;
639 warpin_render(&obj->orient, &obj->pos, Fireballs[num].current_bitmap, rad, percent_life, obj->radius );
649 // -----------------------------------------------------------------
652 // Delete a fireball. Called by object_delete() code... do not call
655 void fireball_delete( object * obj )
661 SDL_assert( Fireballs[num].objnum == OBJ_INDEX(obj));
663 Fireballs[num].objnum = -1;
665 SDL_assert( Num_fireballs >= 0 );
668 // -----------------------------------------------------------------
669 // fireball_delete_all()
671 // Delete all active fireballs, by calling obj_delete directly.
673 void fireball_delete_all()
678 for ( i = 0; i < MAX_FIREBALLS; i++ ) {
680 if ( fb->objnum != -1 ) {
681 obj_delete(fb->objnum);
686 void fireball_set_framenum(int num)
693 fb = &Fireballs[num];
694 fd = &Fireball_info[Fireballs[num].fireball_info_index];
698 if((fb->lod >= 0) && (fb->lod < fd->lod_count)){
699 fl = &Fireball_info[Fireballs[num].fireball_info_index].lod[(int)fb->lod];
706 if ( fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT ) {
707 float total_time = i2fl(fl->num_frames) / fl->fps; // in seconds
709 framenum = fl2i(fb->time_elapsed * fl->num_frames / total_time + 0.5);
711 if ( framenum < 0 ) framenum = 0;
713 framenum = framenum % fl->num_frames;
716 // warp out effect plays backwards
717 framenum = fl->num_frames-framenum-1;
718 fb->current_bitmap = fl->bitmap_id + framenum;
720 fb->current_bitmap = fl->bitmap_id + framenum;
724 framenum = fl2i(fb->time_elapsed / fb->total_time * fl->num_frames + 0.5);
726 // ensure we don't go past the number of frames of animation
727 if ( framenum > (fl->num_frames-1) ) {
728 framenum = (fl->num_frames-1);
729 Objects[fb->objnum].flags |= OF_SHOULD_BE_DEAD;
732 if ( framenum < 0 ) framenum = 0;
733 fb->current_bitmap = fl->bitmap_id + framenum;
737 int fireball_is_perishable(object * obj)
745 SDL_assert( Fireballs[num].objnum == OBJ_INDEX(obj) );
747 fb = &Fireballs[num];
749 if ( fb->fireball_info_index == FIREBALL_EXPLOSION_MEDIUM )
752 if ( !((fb->fireball_info_index == FIREBALL_WARP_EFFECT) || (fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT)) ) {
753 if ( !(obj->flags & OF_WAS_RENDERED)) {
762 // -----------------------------------------------------------------
763 // fireball_free_one()
765 // There are too many fireballs, so delete the oldest small one
766 // to free up a slot. Returns the fireball slot freed.
768 int fireball_free_one()
773 int oldest_objnum = -1, oldest_slotnum = -1;
774 // float lifeleft, oldest_lifeleft = 0.0f;
776 for ( i = 0; i < MAX_FIREBALLS; i++ ) {
779 // only remove the ones that aren't warp effects
780 if ( (fb->objnum>-1) && fireball_is_perishable(&Objects[fb->objnum]) ) {
782 // lifeleft = fb->total_time - fb->time_elapsed;
783 // if ( (oldest_objnum < 0) || (lifeleft < oldest_lifeleft) ) {
785 // oldest_lifeleft = lifeleft;
786 oldest_objnum = fb->objnum;
792 if ( oldest_objnum > -1 ) {
793 obj_delete(oldest_objnum);
795 return oldest_slotnum;
798 // broke fireball_move into fireball_process_pre and fireball_process_post as was done
799 // with all *_move functions on 8/13 by Mike K. and Mark A.
800 void fireball_process_pre( object *objp, float frame_time)
804 int fireball_is_warp(object * obj)
811 SDL_assert( Fireballs[num].objnum == OBJ_INDEX(obj) );
813 fb = &Fireballs[num];
815 if ( fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT)
821 // mabye play sound effect for warp hole closing
822 void fireball_maybe_play_warp_close_sound(fireball *fb)
826 // If not a warphole fireball, do a quick out
827 if ( !(fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT)) {
831 // If the warhole close sound has been played, don't play it again!
832 if ( fb->flags & FBF_WARP_CLOSE_SOUND_PLAYED ) {
836 life_left = fb->total_time - fb->time_elapsed;
838 if ( life_left < WARPHOLE_GROW_TIME ) {
839 fireball_play_warphole_close_sound(fb);
840 fb->flags |= FBF_WARP_CLOSE_SOUND_PLAYED;
844 MONITOR( NumFireballs );
846 void fireball_process_post(object * obj, float frame_time)
851 MONITOR_INC( NumFireballs, 1 );
855 SDL_assert( Fireballs[num].objnum == OBJ_INDEX(obj) );
857 fb = &Fireballs[num];
859 fb->time_elapsed += frame_time;
860 if ( fb->time_elapsed > fb->total_time ) {
861 obj->flags |= OF_SHOULD_BE_DEAD;
864 fireball_maybe_play_warp_close_sound(fb);
866 fireball_set_framenum(num);
869 // Returns life left of a fireball in seconds
870 float fireball_lifeleft( object *obj )
877 SDL_assert( Fireballs[num].objnum == OBJ_INDEX(obj) );
879 fb = &Fireballs[num];
881 return fb->total_time - fb->time_elapsed;
884 // Returns life left of a fireball in percent
885 float fireball_lifeleft_percent( object *obj )
892 SDL_assert( Fireballs[num].objnum == OBJ_INDEX(obj) );
894 fb = &Fireballs[num];
896 return (fb->total_time - fb->time_elapsed) / fb->total_time;
899 // determine LOD to use
900 int fireball_get_lod(vector *pos, fireball_info *fd, float size)
903 int x, y, w, h, bm_size;
914 extern float Viewer_zoom;
921 g3_set_view_matrix(&Eye_position, &Eye_matrix, Viewer_zoom);
923 // get extents of the rotated bitmap
924 g3_rotate_vertex(&v, pos);
926 // if vertex is behind, find size if in front, then drop down 1 LOD
927 if (v.codes & CC_BEHIND) {
928 float dist = vm_vec_dist_quick(&Eye_position, pos);
932 vm_vec_scale_add(&temp, &Eye_position, &Eye_matrix.v.fvec, dist);
933 g3_rotate_vertex(&v, &temp);
935 // if still behind, bail and go with default
936 if (v.codes & CC_BEHIND) {
941 if(!g3_get_bitmap_dims(fd->lod[0].bitmap_id, &v, size, &x, &y, &w, &h, &bm_size)) {
942 if (Detail.hardware_textures == 4) {
946 } else if(w <= bm_size/2){
948 } else if(w <= (1.56*bm_size)){
954 // less aggressive LOD for lower detail settings
957 } else if(w <= bm_size/3){
959 } else if(w <= (1.2*bm_size)){
967 // if it's behind, bump up LOD by 1
977 // return the best lod
978 return SDL_min(ret_lod, fd->lod_count - 1);
981 // Create a fireball, return object index.
982 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)
984 int n, objnum, fb_lod;
990 SDL_assert( fireball_type > -1 );
991 SDL_assert( fireball_type < MAX_FIREBALL_TYPES );
993 fd = &Fireball_info[fireball_type];
995 if ( !(Game_detail_flags & DETAIL_FLAG_FIREBALLS) ) {
996 if ( !((fireball_type == FIREBALL_WARP_EFFECT) || (fireball_type == FIREBALL_KNOSSOS_EFFECT)) ) {
1001 if ( (Num_fireballs >= MAX_FIREBALLS) || (num_objects >= MAX_OBJECTS) ) {
1002 // who cares if we don't create a spark.
1003 // JAS - Should this code be in? Is it better to remove an old spark
1004 // and start a new one, or just not start the new one?
1005 //if ( fd->type == FIREBALL_TYPE_SMALL ) {
1009 //mprintf(( "Out of fireball slots, trying to free one up!\n" ));
1010 // out of slots, so free one up.
1011 n = fireball_free_one();
1013 // If there's still no free slots, then exit
1014 //mprintf(( "ERROR: Couldn't free one up!!\n" ));
1017 //mprintf(( "Freed one up just fine!!\n" ));
1020 for ( n = 0; n < MAX_FIREBALLS; n++ ) {
1021 if ( Fireballs[n].objnum < 0 ) {
1025 SDL_assert( n != MAX_FIREBALLS );
1030 // get an lod to use
1031 fb_lod = fireball_get_lod(pos, fd, size);
1033 // change lod if low res is desired
1036 fb_lod = SDL_min(fb_lod, fd->lod_count - 1);
1039 // if this is a warpout fireball, never go higher than LOD 1
1040 if(fireball_type == FIREBALL_WARP_EFFECT){
1048 fl = &fd->lod[fb_lod];
1050 fb->lod = (char)fb_lod;
1053 if(orient_override != NULL){
1054 orient = *orient_override;
1056 if ( parent_obj < 0 ) {
1057 orient = vmd_identity_matrix;
1059 orient = Objects[parent_obj].orient;
1063 objnum = obj_create(OBJ_FIREBALL, parent_obj, n, &orient, pos, size, OF_RENDERS);
1066 Int3(); // Get John, we ran out of objects for fireballs
1070 obj = &Objects[objnum];
1072 fb->fireball_info_index = fireball_type;
1073 fb->time_elapsed = 0.0f;
1074 fb->objnum = objnum;
1075 fb->current_bitmap = -1;
1077 switch( fb->fireball_info_index ) {
1079 case FIREBALL_EXPLOSION_MEDIUM:
1080 fb->orient = (myrand()>>8) & 7; // 0 - 7
1083 case FIREBALL_EXPLOSION_LARGE1:
1084 case FIREBALL_EXPLOSION_LARGE2:
1085 // case FIREBALL_EXPLOSION_LARGE3:
1086 case FIREBALL_ASTEROID:
1087 fb->orient = (myrand()>>8) % 360; // 0 - 359
1090 case FIREBALL_WARP_EFFECT:
1091 case FIREBALL_KNOSSOS_EFFECT:
1092 // Play sound effect for warp hole opening up
1093 fireball_play_warphole_open_sound(ship_class, fb);
1098 // if warp out, then reverse the orientation
1099 vm_vec_scale( &obj->orient.v.fvec, -1.0f ); // Reverse the forward vector
1100 vm_vec_scale( &obj->orient.v.rvec, -1.0f ); // Reverse the right vector
1111 if ( fb->fireball_info_index == FIREBALL_WARP_EFFECT || fb->fireball_info_index == FIREBALL_KNOSSOS_EFFECT ) {
1112 SDL_assert( warp_lifetime > 4.0f ); // Warp lifetime must be at least 4 seconds!
1113 fb->total_time = warp_lifetime; // in seconds
1115 fb->total_time = i2fl(fl->num_frames) / fl->fps; // in seconds
1118 fireball_set_framenum(n);
1121 // Make the explosion move at a constant velocity.
1122 obj->flags |= OF_PHYSICS;
1123 obj->phys_info.mass = 1.0f;
1124 obj->phys_info.side_slip_time_const = 0.0f;
1125 obj->phys_info.rotdamp = 0.0f;
1126 obj->phys_info.vel = *velocity;
1127 obj->phys_info.max_vel = *velocity;
1128 obj->phys_info.desired_vel = *velocity;
1129 obj->phys_info.speed = vm_vec_mag(velocity);
1130 vm_vec_zero(&obj->phys_info.max_rotvel);
1137 // -----------------------------------------------------------------
1140 // Called at game shutdown to clean up the fireball system
1142 void fireball_close()
1144 if ( !fireballs_inited )
1147 fireball_delete_all();
1150 // -----------------------------------------------------------------
1151 // fireball_level_close()
1153 // Called when a mission ends... frees up any animations that might
1154 // be partially played
1156 void fireball_level_close()
1158 if ( !fireballs_inited )
1161 fireball_delete_all();
1164 void fireballs_page_in()
1169 for ( i = 0; i < MAX_FIREBALL_TYPES ; i++ ) {
1170 fd = &Fireball_info[i];
1172 for(idx=0; idx<fd->lod_count; idx++){
1173 bm_page_in_texture( fd->lod[idx].bitmap_id, fd->lod[idx].num_frames );
1177 bm_page_in_texture( Warp_glow_bitmap );