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.4 2002/06/17 06:33:08 relnev
19 * ryan's struct patch for gcc 2.95
21 * Revision 1.3 2002/06/09 04:41:16 relnev
22 * added copyright header
24 * Revision 1.2 2002/05/07 03:16:43 theoddone33
25 * The Great Newline Fix
27 * Revision 1.1.1.1 2002/05/03 03:28:08 root
31 * 19 9/14/99 1:27a Andsager
32 * Better LOD for fireballs when behind. Move point ahead to get vertex
33 * ahead and then find size.
35 * 18 9/12/99 11:42p Dave
37 * 17 9/13/99 10:09a Andsager
38 * Add debug console commands to lower model render detail and fireball
39 * LOD for big ship explosiosns.
41 * 16 9/09/99 8:53p Dave
42 * Fixed multiplayer degenerate orientation case problem. Make sure warp
43 * effect never goes lower than LOD 1.
45 * 15 9/07/99 12:20a Andsager
46 * LOD less agressive at lower hardware detail level
48 * 14 9/06/99 6:47p Jamesa
51 * 13 9/06/99 3:23p Andsager
52 * Make fireball and weapon expl ani LOD choice look at resolution of the
55 * 12 9/01/99 10:09a Dave
58 * 11 8/31/99 10:13p Andsager
59 * Add Knossos warp effect fireball
61 * 10 8/30/99 9:59a Dave
62 * Removed explosion LOD stuff.
64 * 9 8/28/99 4:54p Dave
65 * Fixed directives display for multiplayer clients for wings with
66 * multiple waves. Fixed hud threat indicator rendering color.
68 * 8 8/27/99 9:07p Dave
69 * LOD explosions. Improved beam weapon accuracy.
71 * 7 7/09/99 5:54p Dave
72 * Seperated cruiser types into individual types. Added tons of new
73 * briefing icons. Campaign screen.
75 * 6 4/28/99 11:13p Dave
76 * Temporary checkin of artillery code.
78 * 5 4/23/99 12:01p Johnson
81 * 4 11/05/98 5:55p Dave
82 * Big pass at reducing #includes
84 * 3 10/23/98 3:51p Dave
85 * Full support for tstrings.tbl and foreign languages. All that remains
86 * is to make it active in Fred.
88 * 2 10/07/98 10:52a Dave
91 * 1 10/07/98 10:48a Dave
93 * 75 5/18/98 2:49p Lawrance
94 * Allow up to double instance of sound for warp holes
96 * 74 5/15/98 3:54p John
97 * Added code so that only "perishable" fireballs get removed.
99 * 73 4/15/98 9:42a Adam
100 * added 2 more explosion types (1, actually, but placeholder for 2)
102 * 72 4/12/98 9:56a John
103 * Made lighting detail flags work. Made explosions cast light on
106 * 71 4/09/98 7:58p John
107 * Cleaned up tmapper code a bit. Put NDEBUG around some ndebug stuff.
108 * Took out XPARENT flag settings in all the alpha-blended texture stuff.
110 * 70 3/31/98 5:11p John
111 * Removed demo/save/restore. Made NDEBUG defined compile. Removed a
112 * bunch of debug stuff out of player file. Made model code be able to
113 * unload models and malloc out only however many models are needed.
115 * 69 3/30/98 4:02p John
116 * Made machines with < 32 MB of RAM use every other frame of certain
117 * bitmaps. Put in code to keep track of how much RAM we've malloc'd.
119 * 68 3/29/98 12:39p John
120 * Made warp in glow page in
122 * 67 3/27/98 2:17p Lawrance
123 * Don't play warphole closing for non-captial sized warp effects
125 * 66 3/26/98 5:44p Lawrance
126 * take out debug comments for warphole sounds playing
128 * 65 3/26/98 5:21p John
129 * Added new code to preload all bitmaps at the start of a level.
130 * Commented it out, though.
132 * 64 3/25/98 5:30p Lawrance
133 * Fix bug that was not playing wormhole open sound effect at correct
136 * 63 3/25/98 10:56a Lawrance
137 * Make a sound for warphole close as well as warphole open, move to
140 * 62 3/18/98 12:36p John
141 * Made hardware have nicer looking warp effect
143 * 61 3/18/98 12:01p John
144 * Made warp grid grow faster
146 * 60 2/26/98 10:07p Hoffoss
147 * Rewrote state saving and restoring to fix bugs and simplify the code.
149 * 59 2/22/98 12:19p John
150 * Externalized some strings
152 * 58 2/19/98 4:32p Lawrance
153 * Add asteroid explosion
155 * 57 2/12/98 11:53p Lawrance
156 * comment out use of current_frame since not used anywhere
158 * 56 2/05/98 9:21p John
159 * Some new Direct3D code. Added code to monitor a ton of stuff in the
162 * 55 1/23/98 5:06p John
163 * Took L out of vertex structure used B (blue) instead. Took all small
164 * fireballs out of fireball types and used particles instead. Fixed some
165 * debris explosion things. Restructured fireball code. Restructured
166 * some lighting code. Made dynamic lighting on by default. Made groups
167 * of lasers only cast one light. Made fireballs not cast light.
169 * 54 1/19/98 9:37p Allender
170 * Great Compiler Warning Purge of Jan, 1998. Used pragma's in a couple
171 * of places since I was unsure of what to do with code.
173 * 53 1/15/98 4:58p John
174 * Made warp effect use a looping ani. Made the scaling up & down be in
177 * 52 1/15/98 2:32p John
178 * Added code to optionally take a velocity for a fireball.
180 * 51 1/11/98 2:15p John
181 * Changed a lot of stuff that had to do with bitmap loading. Made cfile
182 * not do callbacks, I put that in global code. Made only bitmaps that
183 * need to load for a level load.
185 * 50 1/02/98 5:04p John
186 * Several explosion related changes. Made fireballs not be used as
187 * ani's. Made ship spark system expell particles. Took away impact
188 * explosion for weapon hitting ship... this needs to get added to weapon
189 * info and makes shield hit more obvious. Only make sparks when hit
192 * 49 12/31/97 4:48p John
193 * added some debug info
195 * 48 12/30/97 6:44p John
196 * Made g3_Draw_bitmap functions account for aspect of bitmap.
198 * 47 12/08/97 11:15a John
199 * added parameter to warpout for life.
201 * 46 12/02/97 3:59p John
202 * Added first rev of thruster glow, along with variable levels of
203 * translucency, which retquired some restructing of palman.
205 * 45 11/30/97 2:03p John
206 * made warp effect not use an ani for height map.
208 * 44 11/16/97 12:20p John
209 * added code to make ships instantly warp in/out if fireball effect
210 * fails. But, made it so the fireball effect will kill off old sparks
211 * so it can go, so this should never happen.
213 * 43 11/16/97 10:48a John
214 * added code to remove the oldest fireball if there weren't enough slots
217 * 42 11/01/97 1:49p John
218 * added code to page fireballs in during level load. Made player warpout
219 * use Adam's new camera movement pattern. Make ships docked to warping
220 * out ships render correctly.
222 * 41 10/29/97 5:05p John
223 * Changed dynamic lighting to only rotate and calculate lighting for
224 * point lights that are close to an object. Changed lower framerate cap
227 * 40 10/24/97 6:24p John
228 * added code to return the life left of a fireball
230 * 39 9/14/97 4:49p Lawrance
231 * add some demo debugging code
233 * 38 9/12/97 4:02p John
234 * put in ship warp out effect.
235 * put in dynamic lighting for warp in/out
237 * 37 9/09/97 4:49p John
238 * Almost done ship warp in code
240 * 36 9/08/97 8:39a John
241 * added in code structure for grid
243 * 35 9/03/97 5:04p Lawrance
244 * add error checking when restoring structs
246 * 34 9/03/97 4:32p John
247 * changed bmpman to only accept ani and pcx's. made passing .pcx or .ani
248 * to bm_load functions not needed. Made bmpman keep track of palettes
249 * for bitmaps not mapped into game palettes.
251 * 33 8/29/97 2:26p John
252 * first rev of ship warp in effect. Nothing more than a fireball inside
253 * of freespace, but textest.cpp contains the correct effect code that
254 * needs to be transferred into the game next.
256 * 32 8/21/97 5:11p Lawrance
257 * frame numbering for ANI's now is from 0 -> total_frames-1.
259 * 31 8/13/97 9:50p Allender
260 * split *_move into *_process_pre and *_process_post functions.
261 * process_pre functions called before object is moved. _process_post
262 * functions called after object is moved. Reordered code in ship_post
263 * and weapon_post for multiplayer
265 * 30 8/13/97 12:06p Lawrance
266 * supporting multiple types of fireball explosions
268 * 29 8/05/97 10:18a Lawrance
269 * my_rand() being used temporarily instead of rand()
271 * 28 7/31/97 5:55p John
272 * made so you pass flags to obj_create.
273 * Added new collision code that ignores any pairs that will never
276 * 27 7/24/97 9:54a Lawrance
277 * don't free fireball system if not inited
279 * 26 7/23/97 11:35a Lawrance
280 * ensure fireball animations are always freed properly
282 * 25 7/21/97 11:41a Lawrance
283 * clean up fireballs at the end of each level
285 * 24 7/20/97 6:58p Lawrance
286 * call anim_get_frame() to take advantage of key-framed animation
288 * 23 7/11/97 3:57p John
289 * made fireballs translucent. alpha=1.3x intesity. only for d3d.
291 * 22 7/11/97 12:08p John
292 * made fireballs randomly be rotated.
294 * 21 7/11/97 11:54a John
295 * added rotated 3d bitmaps.
297 * 20 7/11/97 11:19a Lawrance
298 * fix mem leaks, move save code from State.cpp here
300 * 19 7/10/97 1:51p Lawrance
301 * sorting anim fireballs
303 * 18 6/24/97 6:21p John
304 * added detail flags.
305 * sped up motion debris system a bit.
307 * 17 5/14/97 4:08p Lawrance
308 * removing my_index from game arrays
310 * 16 5/05/97 10:40p Mike
311 * Make missile exhaust trails look a tad nicer.
313 * 15 3/11/97 10:47p Mike
314 * Add a slew of secondary weapons.
315 * Support exhaust blobs.
316 * Add weapons that spawn weapons.
317 * Add remotely detonatable weapons.
318 * Add heat-seeking missiles.
320 * 14 2/17/97 5:18p John
321 * Added a bunch of RCS headers to a bunch of old files that don't have
337 #include "floating.h"
339 #include "lighting.h"
342 #include "systemvars.h"
343 #include "fireballs.h"
344 #include "linklist.h"
346 #include "localize.h"
348 #define WARPHOLE_GROW_TIME (1.5f) // time for warphole to reach max size (also time to shrink to nothing once it begins to shrink)
350 #define MAX_FIREBALL_LOD 4
352 typedef struct fireball_lod {
353 char filename[MAX_FILENAME_LEN];
359 typedef struct fireball_info {
364 // flag values for fireball struct flags member
365 #define FBF_WARP_CLOSE_SOUND_PLAYED (1<<0)
366 #define FBF_WARP_CAPTIAL_SIZE (1<<1)
367 #define FBF_WARP_CRUISER_SIZE (1<<2)
369 typedef struct fireball {
370 int objnum; // If -1 this object is unused
371 int fireball_info_index; // Index into Fireball_info array
373 int orient; // For fireballs, which orientation. For warps, 0 is warpin, 1 is warpout
374 int flags; // see #define FBF_*
375 char lod; // current LOD
376 float time_elapsed; // in seconds
377 float total_time; // total lifetime of animation in seconds
380 #define MAX_FIREBALLS 200
382 fireball Fireballs[MAX_FIREBALLS];
384 fireball_info Fireball_info[MAX_FIREBALL_TYPES];
386 int Num_fireballs = 0;
388 int fireballs_inited = 0;
390 int Warp_glow_bitmap = -1;
392 #define FB_INDEX(fb) (fb-Fireballs)
394 // play warp in sound for warp effect
395 void fireball_play_warphole_open_sound(int ship_class, fireball *fb)
398 float range_multiplier = 1.0f;
399 object *fireball_objp;
401 Assert((fb != NULL) && (fb->objnum >= 0));
402 if((fb == NULL) || (fb->objnum < 0)){
405 fireball_objp = &Objects[fb->objnum];
407 sound_index = SND_WARP_IN;
409 if((ship_class >= 0) && (ship_class < Num_ship_types)){
410 if ( Ship_info[ship_class].flags & SIF_HUGE_SHIP ) {
411 sound_index = SND_CAPITAL_WARP_IN;
412 fb->flags |= FBF_WARP_CAPTIAL_SIZE;
413 } else if ( Ship_info[ship_class].flags & SIF_BIG_SHIP ) {
414 range_multiplier = 6.0f;
415 fb->flags |= FBF_WARP_CRUISER_SIZE;
419 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
422 // play warp out sound for warp effect
423 void fireball_play_warphole_close_sound(fireball *fb)
427 object *fireball_objp;
429 fireball_objp = &Objects[fb->objnum];
431 sound_index = SND_WARP_OUT;
433 if ( fb->flags & FBF_WARP_CAPTIAL_SIZE ) {
434 sound_index = SND_CAPITAL_WARP_OUT;
436 // AL 27-3-98: Decided that warphole closing is only required for captial ship sized warp effects.
440 snd_play_3d(&Snds[sound_index], &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
443 void fireball_parse_tbl()
446 char base_filename[256] = "";
451 if ((rval = setjmp(parse_abort)) != 0) {
452 Error(LOCATION, "Unable to parse fireball.tbl! Code = %i.\n", rval);
455 read_file_text(NOX("fireball.tbl"));
460 required_string("#Start");
461 while (required_string_either("#End","$Name:")) {
462 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 strcpy(Fireball_info[ntypes].lod[0].filename, base_filename);
477 // stuff LOD level filenames
478 for(idx=1; idx<Fireball_info[ntypes].lod_count; idx++){
479 if(idx >= MAX_FIREBALL_LOD){
483 sprintf(Fireball_info[ntypes].lod[idx].filename, "%s_%d", base_filename, idx);
488 required_string("#End");
490 // close localization
495 void fireball_load_data()
500 for ( i = 0; i < MAX_FIREBALL_TYPES; i++ ) {
501 fd = &Fireball_info[i];
503 for(idx=0; idx<fd->lod_count; idx++){
504 fd->lod[idx].bitmap_id = bm_load_animation( fd->lod[idx].filename, &fd->lod[idx].num_frames, &fd->lod[idx].fps, 1 );
505 if ( fd->lod[idx].bitmap_id < 0 ) {
506 Error(LOCATION, "Could not load %s anim file\n", fd->lod[idx].filename);
511 if ( Warp_glow_bitmap == -1 ) {
512 Warp_glow_bitmap = bm_load( NOX("warpglow01") );
517 void fireball_preload()
519 // Do nothing. Called before level init, this used to page in warp effect.
520 // Not needed with new BmpMan system.
523 // This will get called at the start of each level.
528 if ( !fireballs_inited ) {
529 fireballs_inited = 1;
531 // Do all the processing that happens only once
532 fireball_parse_tbl();
533 fireball_load_data();
536 // Reset everything between levels
538 for (i=0; i<MAX_FIREBALLS; i++ ) {
539 Fireballs[i].objnum = -1;
545 MONITOR( NumFireballsRend );
547 //extern int tcache_hit(int);
548 //extern int Glide_expl_textures_in_frame;
549 //extern float Glide_avg_exp_text_per_sec;
551 void fireball_render(object * obj)
558 MONITOR_INC( NumFireballsRend, 1 );
561 fb = &Fireballs[num];
562 fd = &Fireball_info[fb->fireball_info_index];
564 if ( Fireballs[num].current_bitmap < 0 )
567 // gr_set_color( 0, 100, 0 );
568 // g3_draw_sphere_ez( &obj->pos, obj->radius );
572 if(The_mission.flags & MISSION_FLAG_FULLNEB){
573 gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
576 g3_rotate_vertex(&p, &obj->pos );
578 switch( fb->fireball_info_index ) {
580 case FIREBALL_EXPLOSION_MEDIUM:
581 gr_set_bitmap(Fireballs[num].current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f );
582 g3_draw_bitmap(&p, fb->orient, obj->radius, TMAP_FLAG_TEXTURED );
585 case FIREBALL_EXPLOSION_LARGE1:
586 case FIREBALL_EXPLOSION_LARGE2:
587 // case FIREBALL_EXPLOSION_LARGE3:
589 if (!tcache_hit(Fireballs[num].current_bitmap)) {
590 // if we're over 200k exp vram upload this frame, change to lower lod
591 if (Glide_expl_textures_in_frame > 1024 * 200) {
592 // change fireball instance to lower LOD or don't draw
594 // get current LOD and number of LODs
595 int cur_lod = Fireballs[num].lod;
596 int num_lods = Fireball_info[Fireballs[num].fireball_info_index].lod_count;
598 if (num_lods > cur_lod+1) {
600 int frame = Fireballs[num].current_bitmap - Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod].bitmap_id;
601 Fireballs[num].lod++;
602 Fireballs[num].current_bitmap = Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod+1].bitmap_id + frame;
603 mprintf(("bumping down lod for fireball %s, frame %d\n", Fireball_info[Fireballs[num].fireball_info_index].lod[cur_lod].filename, frame));
608 case FIREBALL_ASTEROID:
609 // Make the big explosions rotate with the viewer.
610 gr_set_bitmap(Fireballs[num].current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f );
611 g3_draw_rotated_bitmap(&p, (i2fl(fb->orient)*PI)/180.0f, obj->radius, TMAP_FLAG_TEXTURED );
614 case FIREBALL_WARP_EFFECT:
615 case FIREBALL_KNOSSOS_EFFECT: {
617 float percent_life = fb->time_elapsed / fb->total_time;
621 // Code to make effect grow/shrink.
622 float t = fb->time_elapsed;
624 if ( t < WARPHOLE_GROW_TIME ) {
625 rad = (float)pow(t/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
626 //rad = t*obj->radius/WARPHOLE_GROW_TIME;
627 //mprintf(( "T=%.2f, Rad = %.2f\n", t, rad ));
628 } else if ( t < fb->total_time - WARPHOLE_GROW_TIME ) {
631 rad = (float)pow((fb->total_time - t)/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
632 //rad = (fb->total_time - t )*obj->radius/WARPHOLE_GROW_TIME;
637 warpin_render(&obj->orient, &obj->pos, Fireballs[num].current_bitmap, rad, percent_life, obj->radius );
647 // -----------------------------------------------------------------
650 // Delete a fireball. Called by object_delete() code... do not call
653 void fireball_delete( object * obj )
659 fb = &Fireballs[num];
661 Assert( fb->objnum == OBJ_INDEX(obj));
663 Fireballs[num].objnum = -1;
665 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[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)
744 objnum = OBJ_INDEX(obj);
745 Assert( Fireballs[num].objnum == objnum );
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)
810 objnum = OBJ_INDEX(obj);
811 Assert( Fireballs[num].objnum == objnum );
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 );
854 objnum = OBJ_INDEX(obj);
855 Assert( Fireballs[num].objnum == objnum );
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 )
876 objnum = OBJ_INDEX(obj);
877 Assert( Fireballs[num].objnum == objnum );
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 )
891 objnum = OBJ_INDEX(obj);
892 Assert( Fireballs[num].objnum == objnum );
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 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 Assert( fireball_type > -1 );
991 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 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 = 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 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 );