mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 12:41:35 -10:00
scale render/detail box limits with detail level setting make sure that we reset culling and zbuffer after each model buffer that gets rendered
1003 lines
28 KiB
C++
1003 lines
28 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* $Logfile: /Freespace2/code/Weapon/Shockwave.cpp $
|
|
* $Revision: 2.32 $
|
|
* $Date: 2006-11-06 06:33:48 $
|
|
* $Author: taylor $
|
|
*
|
|
* C file for creating and managing shockwaves
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
* Revision 2.31 2006/11/06 06:19:17 taylor
|
|
* rename set_warp_globals() to model_set_warp_globals()
|
|
* remove two old/unused MR flags (MR_ALWAYS_REDRAW, used for caching that doesn't work; MR_SHOW_DAMAGE, didn't do anything)
|
|
* add MR_FULL_DETAIL to render an object regardless of render/detail box setting
|
|
* change "model_current_LOD" to a global "Interp_detail_level" and the static "Interp_detail_level" to "Interp_detail_level_locked", a bit more descriptive
|
|
* minor bits of cleanup
|
|
* change a couple of vm_vec_scale_add2() calls to just vm_vec_add2() calls in ship.cpp, since that was the final result anyway
|
|
*
|
|
* Revision 2.30 2006/10/06 09:33:56 taylor
|
|
* if shockwaves weren't loaded then don't try to unload them (fixes standalone crash)
|
|
*
|
|
* Revision 2.29 2006/09/11 05:37:33 taylor
|
|
* make sure that we properly page in textures for 3d shockwave models
|
|
*
|
|
* Revision 2.28 2006/08/20 00:51:07 taylor
|
|
* maybe optimize the (PI/2), (PI*2) and (RAND_MAX/2) stuff a little bit
|
|
*
|
|
* Revision 2.27 2006/07/06 22:01:50 taylor
|
|
* add some minor error catches for invalid values
|
|
*
|
|
* Revision 2.26 2006/05/27 16:45:11 taylor
|
|
* some minor cleanup
|
|
* remove -nobeampierce
|
|
* update for geometry batcher changes
|
|
*
|
|
* Revision 2.25 2006/03/18 09:25:55 wmcoolmon
|
|
* Allow "none" in $Shockwave Model to disable shockwave
|
|
*
|
|
* Revision 2.24 2006/02/13 00:20:46 Goober5000
|
|
* more tweaks, plus clarification of checks for the existence of files
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.23 2005/12/28 22:17:02 taylor
|
|
* deal with cf_find_file_location() changes
|
|
* add a central parse_modular_table() function which anything can use
|
|
* fix up weapon_expl so that it can properly handle modular tables and LOD count changes
|
|
* add support for for a fireball TBM (handled a little different than a normal TBM is since it only changes rather than adds)
|
|
*
|
|
* Revision 2.22 2005/12/04 19:02:36 wmcoolmon
|
|
* Better XMT beam section handling ("+Index:"); weapon shockwave armor support; countermeasures as weapons
|
|
*
|
|
* Revision 2.21 2005/12/01 07:45:21 Goober5000
|
|
* bypass annoying warnings when loading optional models
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.20 2005/10/30 06:44:59 wmcoolmon
|
|
* Codebase commit - nebula.tbl, scripting, new dinky explosion/shockwave stuff, moving muzzle flashes
|
|
*
|
|
* Revision 2.19 2005/08/25 22:40:04 taylor
|
|
* basic cleaning, removing old/useless code, sanity stuff, etc:
|
|
* - very minor performance boost from not doing stupid things :)
|
|
* - minor change to 3d shockwave sizing to better approximate 2d effect movements
|
|
* - for shields, Gobal_tris was only holding half as many as the game can/will use, buffer is now set to full size to avoid possible rendering issues
|
|
* - removed extra tcache_set on OGL spec map code, not sure how that slipped in
|
|
*
|
|
* Revision 2.18 2005/08/07 09:25:55 taylor
|
|
* some minor cleanup
|
|
* don't load the default 2d shockwave graphics if we have a default 3d shockwave, they won't get used and only take up memory
|
|
*
|
|
* Revision 2.17 2005/08/05 15:33:45 taylor
|
|
* fix 3-D shockwave frame detection so that it will use the proper number of frames for the animation (not less, not more)
|
|
*
|
|
* Revision 2.16 2005/07/31 20:31:41 wmcoolmon
|
|
* MR_NO_FOGGING for shockwaves
|
|
*
|
|
* Revision 2.15 2005/07/25 08:22:00 Goober5000
|
|
* more bugs and tweaks
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.14 2005/07/24 06:01:37 wmcoolmon
|
|
* Multiple shockwaves support.
|
|
*
|
|
* Revision 2.13 2005/07/24 00:32:45 wmcoolmon
|
|
* Synced 3D shockwaves' glowmaps with the model, tossed in some medals.tbl
|
|
* support for the demo/FS1
|
|
*
|
|
* Revision 2.12 2005/04/05 05:53:25 taylor
|
|
* s/vector/vec3d/g, better support for different compilers (Jens Granseuer)
|
|
*
|
|
* Revision 2.11 2005/03/10 08:00:17 taylor
|
|
* change min/max to MIN/MAX to fix GCC problems
|
|
* add lab stuff to Makefile
|
|
* build unbreakage for everything that's not MSVC++ 6
|
|
* lots of warning fixes
|
|
* fix OpenGL rendering problem with ship insignias
|
|
* no Warnings() in non-debug mode for Linux (like Windows)
|
|
* some campaign savefile fixage to stop reverting everyones data
|
|
*
|
|
* Revision 2.10 2004/07/26 20:47:56 Kazan
|
|
* remove MCD complete
|
|
*
|
|
* Revision 2.9 2004/07/12 16:33:09 Kazan
|
|
* MCD - define _MCD_CHECK to use memory tracking
|
|
*
|
|
* Revision 2.8 2004/03/05 09:01:54 Goober5000
|
|
* Uber pass at reducing #includes
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.7 2004/01/30 07:39:09 Goober5000
|
|
* whew - I just went through all the code I ever added (or at least, that I could
|
|
* find that I commented with a Goober5000 tag) and added a bunch of Asserts
|
|
* and error-checking
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.6 2003/10/23 18:03:25 randomtiger
|
|
* Bobs changes (take 2)
|
|
*
|
|
* Revision 2.5 2003/09/26 14:37:16 bobboau
|
|
* commiting Hardware T&L code, everything is ifdefed out with the compile flag HTL
|
|
* still needs a lot of work, ubt the frame rates were getting with it are incredable
|
|
* the biggest problem it still has is a bad lightmanegment system, and the zbuffer
|
|
* doesn't work well with things still getting rendered useing the sofware pipeline, like thrusters,
|
|
* and weapons, I think these should be modifyed to be sent through hardware,
|
|
* it would be slightly faster and it would likely fix the problem
|
|
*
|
|
* also the thruster glow/particle stuff I did is now in.
|
|
*
|
|
* Revision 2.4 2003/08/31 06:00:42 bobboau
|
|
* an asortment of bugfixes, mostly with the specular code,
|
|
* HUD flickering should be completly gone now
|
|
*
|
|
* Revision 2.3 2003/08/22 07:35:09 bobboau
|
|
* specular code should be bugless now,
|
|
* cell shadeing has been added activated via the comand line '-cell',
|
|
* 3D shockwave models, and a transparency method I'm calling edge and center alpha that could be usefull for other things, ask for details
|
|
*
|
|
* Revision 2.2 2003/03/18 08:44:06 Goober5000
|
|
* added explosion-effect sexp and did some other minor housekeeping
|
|
* --Goober5000
|
|
*
|
|
* Revision 2.1 2002/08/01 01:41:11 penguin
|
|
* The big include file move
|
|
*
|
|
* Revision 2.0 2002/06/03 04:02:29 penguin
|
|
* Warpcore CVS sync
|
|
*
|
|
* Revision 1.1 2002/05/02 18:03:13 mharris
|
|
* Initial checkin - converted filenames and includes to lower case
|
|
*
|
|
*
|
|
* 7 9/01/99 10:15a Dave
|
|
*
|
|
* 6 7/18/99 12:32p Dave
|
|
* Randomly oriented shockwaves.
|
|
*
|
|
* 5 3/23/99 2:29p Andsager
|
|
* Fix shockwaves for kamikazi and Fred defined. Collect together
|
|
* shockwave_create_info struct.
|
|
*
|
|
* 4 2/26/99 4:14p Dave
|
|
* Put in the ability to have multiple shockwaves for ships.
|
|
*
|
|
* 3 11/05/98 5:55p Dave
|
|
* Big pass at reducing #includes
|
|
*
|
|
* 2 10/07/98 10:54a Dave
|
|
* Initial checkin.
|
|
*
|
|
* 1 10/07/98 10:51a Dave
|
|
*
|
|
* 49 5/18/98 3:04p Lawrance
|
|
* Play shockwave impact sound
|
|
*
|
|
* 48 5/18/98 12:59a Lawrance
|
|
* Replace shockwave impact sound with a new "whoosh" sound that
|
|
* originates from the shockwave center
|
|
*
|
|
* 47 4/15/98 10:17p Mike
|
|
* Training mission #5.
|
|
* Fix application of subsystem damage.
|
|
*
|
|
* 46 4/09/98 7:58p John
|
|
* Cleaned up tmapper code a bit. Put NDEBUG around some ndebug stuff.
|
|
* Took out XPARENT flag settings in all the alpha-blended texture stuff.
|
|
*
|
|
* 45 3/31/98 5:19p John
|
|
* Removed demo/save/restore. Made NDEBUG defined compile. Removed a
|
|
* bunch of debug stuff out of player file. Made model code be able to
|
|
* unload models and malloc out only however many models are needed.
|
|
*
|
|
*
|
|
* 44 3/30/98 4:02p John
|
|
* Made machines with < 32 MB of RAM use every other frame of certain
|
|
* bitmaps. Put in code to keep track of how much RAM we've malloc'd.
|
|
*
|
|
* 43 3/26/98 5:26p John
|
|
* added new paging code. nonfunctional.
|
|
*
|
|
* 42 3/04/98 4:11p Lawrance
|
|
* Have area effects affect asteroids, have asteroids cast an area effect,
|
|
* fix ship shockwaves
|
|
*
|
|
* 41 2/26/98 10:08p Hoffoss
|
|
* Rewrote state saving and restoring to fix bugs and simplify the code.
|
|
*
|
|
* 40 2/22/98 12:19p John
|
|
* Externalized some strings
|
|
*
|
|
* 39 2/20/98 8:32p Lawrance
|
|
* Make shockwaves affect subsystems more realistically.
|
|
*
|
|
* 38 2/16/98 11:26a Lawrance
|
|
* ensure shockwave lasts full duration
|
|
*
|
|
* 37 2/16/98 10:04a Lawrance
|
|
* Fix broken shockwave damage.
|
|
*
|
|
* 36 2/14/98 4:42p Lawrance
|
|
* pass shockwave object (not parent) to ship_apply_global_damage()
|
|
*
|
|
* 35 2/12/98 11:54p Lawrance
|
|
* restructure rendering code to use an animation
|
|
*
|
|
* 34 2/11/98 5:38p Dave
|
|
* Put in a global inited flag for shockwaves.
|
|
*
|
|
* 33 2/02/98 8:47a Andsager
|
|
* Ship death area damage applied as instantaneous damage for small ships
|
|
* and shockwaves for large (>50 radius) ships.
|
|
*
|
|
* 32 1/26/98 11:54a Lawrance
|
|
* Don't allow Navbuoys to be affected by area-effect damage and blasts.
|
|
*
|
|
* 31 1/22/98 11:43p Lawrance
|
|
* Play sound effect when player is hit by shockwave.
|
|
*
|
|
* 30 1/14/98 4:31p Dave
|
|
* Made shockwaves apply damage correctly.
|
|
*
|
|
* 29 1/14/98 2:59p Allender
|
|
* if shockwave came from a weapon, make the shockwave's parent be the
|
|
* weapons parent.
|
|
*
|
|
* 28 12/30/97 6:44p John
|
|
* Made g3_Draw_bitmap functions account for aspect of bitmap.
|
|
*
|
|
* 27 12/02/97 4:00p John
|
|
* Added first rev of thruster glow, along with variable levels of
|
|
* translucency, which retquired some restructing of palman.
|
|
*
|
|
* 26 11/29/97 2:06p John
|
|
* made g3_draw_bitmap and g3_draw_rotated bitmap take w&h, not w/2 & h/2,
|
|
* like they used to incorrectly assume. Added code to model to read in
|
|
* thruster radius's.
|
|
*
|
|
* 25 11/19/97 10:20p Lawrance
|
|
* remove ship_shockwave from ship struct, handled in physics now
|
|
*
|
|
* 24 11/16/97 8:52p Andsager
|
|
* For shockwaves, update physics damping info in physics code.
|
|
*
|
|
* 23 9/18/97 10:48p Lawrance
|
|
* comment out unused struct member
|
|
*
|
|
* 22 9/18/97 4:08p John
|
|
* Cleaned up & restructured ship damage stuff.
|
|
*
|
|
* 21 9/17/97 5:12p John
|
|
* Restructured collision routines. Probably broke a lot of stuff.
|
|
*
|
|
* 20 9/04/97 5:10p Andsager
|
|
* implement physics using moment of inertia and mass (from BSPgen).
|
|
* Added to phys_info struct. Updated ship_info, polymodel structs.
|
|
* Updated weapon ($Mass and $Force) and ship ($Mass -> $Density) tables
|
|
*
|
|
* 19 9/03/97 4:33p John
|
|
* changed bmpman to only accept ani and pcx's. made passing .pcx or .ani
|
|
* to bm_load functions not needed. Made bmpman keep track of palettes
|
|
* for bitmaps not mapped into game palettes.
|
|
*
|
|
* 18 8/26/97 3:31p Andsager
|
|
* scaled shockwave shake duration according to damage
|
|
*
|
|
* 17 8/05/97 1:25a Mike
|
|
* Make ship death roll be shortened by more damage.
|
|
*
|
|
* 16 7/31/97 5:55p John
|
|
* made so you pass flags to obj_create.
|
|
* Added new collision code that ignores any pairs that will never
|
|
* collide.
|
|
*
|
|
* 15 7/25/97 4:30p Andsager
|
|
* Save shockwave info
|
|
*
|
|
* 14 7/25/97 1:04p Andsager
|
|
* Modified physics flag PF_REDUCED_DAMP for damping when object is hit.
|
|
* Flag is now set in physics_apply_whack/shock and turned off in
|
|
* physics_sim_vel. Weapons should not directly set this flag.
|
|
*
|
|
* 13 7/22/97 2:40p Andsager
|
|
* shockwaves now cause proper rotation of ships
|
|
*
|
|
* 12 7/20/97 7:01p Lawrance
|
|
* changed names of anim_ files to be more consistent
|
|
*
|
|
* 11 7/18/97 10:52a Lawrance
|
|
* let player have some control when shockwave hits
|
|
*
|
|
* 10 7/17/97 8:02p Lawrance
|
|
* tweaking shockwave effect
|
|
*
|
|
* 9 7/16/97 5:51p Lawrance
|
|
* make shockwaves translucent
|
|
*
|
|
* 8 7/16/97 4:00p Lawrance
|
|
* render shockwaves by default
|
|
*
|
|
* 7 7/16/97 3:50p Lawrance
|
|
* render shockwaves first, to fake transparency
|
|
*
|
|
* 6 7/16/97 2:52p Lawrance
|
|
* make shockwaves objects
|
|
*
|
|
* 5 7/15/97 7:26p Lawrance
|
|
* make shockwave blast persist over time
|
|
*
|
|
* 4 7/09/97 1:56p Lawrance
|
|
* add savegame support for shockwaves
|
|
*
|
|
* 3 7/09/97 10:33a Lawrance
|
|
* make area-effect spheres translucent
|
|
*
|
|
* 2 7/08/97 6:00p Lawrance
|
|
* implementing shockwaves
|
|
*
|
|
* 1 7/08/97 1:30p Lawrance
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include "weapon/shockwave.h"
|
|
#include "render/3d.h"
|
|
#include "weapon/weapon.h"
|
|
#include "ship/ship.h"
|
|
#include "io/timer.h"
|
|
#include "globalincs/linklist.h"
|
|
#include "ship/shiphit.h"
|
|
#include "gamesnd/gamesnd.h"
|
|
#include "asteroid/asteroid.h"
|
|
#include "object/object.h"
|
|
|
|
|
|
|
|
// -----------------------------------------------------------
|
|
// Data structures
|
|
// -----------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------
|
|
// Module-wide globals
|
|
// -----------------------------------------------------------
|
|
|
|
static char Shockwave_filenames[MAX_SHOCKWAVE_TYPES][NAME_LENGTH] =
|
|
{
|
|
"shockwave01",
|
|
"\0",
|
|
"\0",
|
|
"\0",
|
|
"\0",
|
|
"\0",
|
|
"\0",
|
|
"\0"
|
|
};
|
|
|
|
shockwave Shockwaves[MAX_SHOCKWAVES];
|
|
shockwave_info Shockwave_info[MAX_SHOCKWAVE_TYPES];
|
|
|
|
shockwave Shockwave_list;
|
|
int Shockwave_inited = 0;
|
|
static int Default_shockwave_loaded = 0;
|
|
|
|
static int default_shockwave_model = -1;
|
|
|
|
// -----------------------------------------------------------
|
|
// Function macros
|
|
// -----------------------------------------------------------
|
|
#define SW_INDEX(sw) (sw-Shockwaves)
|
|
|
|
// -----------------------------------------------------------
|
|
// Externals
|
|
// -----------------------------------------------------------
|
|
extern int Show_area_effect;
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_create()
|
|
//
|
|
// Call to create a shockwave
|
|
//
|
|
// input: parent_objnum => object number of object spawning the shockwave
|
|
// pos => vector specifing global position of shockwave center
|
|
// speed => speed at which shockwave expands (m/s)
|
|
// inner_radius => radius at which damage applied is at maximum
|
|
// outer_radius => damage decreases linearly to zero from inner_radius to
|
|
// outer_radius. Outside outer_radius, damage is 0.
|
|
// damage => the maximum damage (ie within inner_radius)
|
|
// blast => the maximux blast (within inner_radius)
|
|
// sw_flag => indicates whether shockwave is from weapon or ship explosion
|
|
// delay => delay in ms before the shockwave actually starts
|
|
//
|
|
// return: success => object number of shockwave
|
|
// failure => -1
|
|
//
|
|
// Goober5000 - now parent_objnum can be allowed to be -1
|
|
int shockwave_create(int parent_objnum, vec3d *pos, shockwave_create_info *sci, int flag, int delay)
|
|
{
|
|
int i, objnum, real_parent;
|
|
shockwave *sw;
|
|
shockwave_info *si;
|
|
matrix orient;
|
|
|
|
for ( i = 0; i < MAX_SHOCKWAVES; i++ ) {
|
|
if ( !(Shockwaves[i].flags & SW_USED) ){
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( i == MAX_SHOCKWAVES ) {
|
|
return -1;
|
|
}
|
|
|
|
//Find the info_index and model
|
|
int info_index = 0;
|
|
int model = -1;
|
|
bool no_model = false;
|
|
if(strlen(sci->name))
|
|
{
|
|
info_index = shockwave_add(sci->name);
|
|
if(info_index < 0) {
|
|
info_index = 0;
|
|
}
|
|
}
|
|
if(strlen(sci->pof_name)) {
|
|
if(stricmp("none", sci->pof_name))
|
|
model = model_load(sci->pof_name, 0, NULL);
|
|
else
|
|
no_model = true;
|
|
}
|
|
|
|
// real_parent is the guy who caused this shockwave to happen
|
|
if (parent_objnum == -1) { // Goober5000
|
|
real_parent = -1;
|
|
} else if ( Objects[parent_objnum].type == OBJ_WEAPON ){
|
|
real_parent = Objects[parent_objnum].parent;
|
|
} else {
|
|
real_parent = parent_objnum;
|
|
}
|
|
|
|
sw = &Shockwaves[i];
|
|
|
|
if(!no_model)
|
|
sw->model = (model < 0) ? default_shockwave_model : model;
|
|
else
|
|
sw->model = -1;
|
|
|
|
sw->flags = (SW_USED | flag);
|
|
sw->speed = sci->speed;
|
|
sw->inner_radius = sci->inner_rad;
|
|
sw->outer_radius = sci->outer_rad;
|
|
sw->damage = sci->damage;
|
|
sw->blast = sci->blast;
|
|
sw->radius = 1.0f;
|
|
sw->pos = *pos;
|
|
sw->num_objs_hit = 0;
|
|
sw->shockwave_info_index=info_index; // only one type for now... type could be passed is as a parameter
|
|
sw->current_bitmap=-1;
|
|
|
|
sw->time_elapsed=0.0f;
|
|
sw->delay_stamp = delay;
|
|
|
|
sw->rot_angles = sci->rot_angles;
|
|
sw->damage_type_idx = sci->damage_type_idx;
|
|
|
|
si = &Shockwave_info[sw->shockwave_info_index];
|
|
// sw->total_time = i2fl(si->num_frames) / si->fps; // in seconds
|
|
sw->total_time = sw->outer_radius / sw->speed;
|
|
|
|
if ( (parent_objnum != -1) && Objects[parent_objnum].type == OBJ_WEAPON ) { // Goober5000: allow -1
|
|
sw->weapon_info_index = Weapons[Objects[parent_objnum].instance].weapon_info_index;
|
|
}
|
|
else {
|
|
sw->weapon_info_index = -1;
|
|
}
|
|
|
|
orient = vmd_identity_matrix;
|
|
vm_angles_2_matrix(&orient, &sw->rot_angles);
|
|
// angles a;
|
|
// a.p = sw->rot_angle*(PI/180);
|
|
// a.b = frand_range(0.0f, PI2);
|
|
// a.h = frand_range(0.0f, PI2);
|
|
// vm_angles_2_matrix(&orient, &a);
|
|
objnum = obj_create( OBJ_SHOCKWAVE, real_parent, i, &orient, &sw->pos, sw->outer_radius, OF_RENDERS );
|
|
|
|
if ( objnum == -1 ){
|
|
Int3();
|
|
}
|
|
|
|
sw->objnum = objnum;
|
|
|
|
list_append(&Shockwave_list, sw);
|
|
|
|
return objnum;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_delete()
|
|
//
|
|
// Delete a shockwave
|
|
//
|
|
// input: object *objp => pointer to shockwave object
|
|
//
|
|
void shockwave_delete(object *objp)
|
|
{
|
|
Assert(objp->type == OBJ_SHOCKWAVE);
|
|
Assert(objp->instance >= 0 && objp->instance < MAX_SHOCKWAVES);
|
|
|
|
Shockwaves[objp->instance].flags = 0;
|
|
Shockwaves[objp->instance].objnum = -1;
|
|
list_remove(&Shockwave_list, &Shockwaves[objp->instance]);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_delete_all()
|
|
//
|
|
//
|
|
void shockwave_delete_all()
|
|
{
|
|
shockwave *sw, *next;
|
|
|
|
sw = GET_FIRST(&Shockwave_list);
|
|
while ( sw != &Shockwave_list ) {
|
|
next = sw->next;
|
|
Assert(sw->objnum != -1);
|
|
Objects[sw->objnum].flags |= OF_SHOULD_BE_DEAD;
|
|
sw = next;
|
|
}
|
|
}
|
|
|
|
// Set the correct frame of animation for the shockwave
|
|
void shockwave_set_framenum(int index)
|
|
{
|
|
int framenum;
|
|
shockwave *sw;
|
|
shockwave_info *si;
|
|
|
|
Assert( (index >= 0) && (index < MAX_SHOCKWAVES) );
|
|
|
|
sw = &Shockwaves[index];
|
|
si = &Shockwave_info[sw->shockwave_info_index];
|
|
|
|
// skip this if it's a 3d shockwave since it won't have the maps managed here
|
|
if (si->bitmap_id < 0)
|
|
return;
|
|
|
|
framenum = fl2i(sw->time_elapsed / sw->total_time * si->num_frames + 0.5);
|
|
|
|
// ensure we don't go past the number of frames of animation
|
|
if ( framenum > (si->num_frames-1) ) {
|
|
framenum = (si->num_frames-1);
|
|
Objects[sw->objnum].flags |= OF_SHOULD_BE_DEAD;
|
|
}
|
|
|
|
if ( framenum < 0 ) {
|
|
framenum = 0;
|
|
}
|
|
|
|
sw->current_bitmap = si->bitmap_id + framenum;
|
|
}
|
|
|
|
// given a shockwave index and the number of frames in an animation return what
|
|
// the current frame # should be (for use with 3d shockwaves)
|
|
int shockwave_get_framenum(int index, int num_frames)
|
|
{
|
|
int framenum;
|
|
shockwave *sw;
|
|
|
|
if ( (index < 0) || (index >= MAX_SHOCKWAVES) ) {
|
|
Int3();
|
|
return 0;
|
|
}
|
|
|
|
sw = &Shockwaves[index];
|
|
|
|
framenum = fl2i(sw->time_elapsed / sw->total_time * num_frames + 0.5);
|
|
|
|
// ensure we don't go past the number of frames of animation
|
|
if ( framenum > (num_frames-1) ) {
|
|
framenum = (num_frames-1);
|
|
Objects[sw->objnum].flags |= OF_SHOULD_BE_DEAD;
|
|
}
|
|
|
|
if ( framenum < 0 ) {
|
|
framenum = 0;
|
|
}
|
|
|
|
return framenum;
|
|
}
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_move()
|
|
//
|
|
// Simulate a single shockwave. If the shockwave radius exceeds outer_radius, then
|
|
// delete the shockwave.
|
|
//
|
|
// input: ojbp => object pointer that points to shockwave object
|
|
// frametime => time to simulate shockwave
|
|
//
|
|
void shockwave_move(object *shockwave_objp, float frametime)
|
|
{
|
|
shockwave *sw;
|
|
object *objp;
|
|
float blast,damage;
|
|
int i;
|
|
|
|
Assert(shockwave_objp->type == OBJ_SHOCKWAVE);
|
|
Assert(shockwave_objp->instance >= 0 && shockwave_objp->instance < MAX_SHOCKWAVES);
|
|
sw = &Shockwaves[shockwave_objp->instance];
|
|
|
|
// if the shockwave has a delay on it
|
|
if(sw->delay_stamp != -1){
|
|
if(timestamp_elapsed(sw->delay_stamp)){
|
|
sw->delay_stamp = -1;
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
sw->time_elapsed += frametime;
|
|
/*
|
|
if ( sw->time_elapsed > sw->total_time ) {
|
|
shockwave_objp->flags |= OF_SHOULD_BE_DEAD;
|
|
}
|
|
*/
|
|
|
|
shockwave_set_framenum(shockwave_objp->instance);
|
|
|
|
sw->radius += (frametime * sw->speed);
|
|
if ( sw->radius > sw->outer_radius ) {
|
|
sw->radius = sw->outer_radius;
|
|
shockwave_objp->flags |= OF_SHOULD_BE_DEAD;
|
|
return;
|
|
}
|
|
|
|
// blast ships and asteroids
|
|
for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
|
|
if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_ASTEROID) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( objp->type == OBJ_SHIP ) {
|
|
// don't blast navbuoys
|
|
if ( ship_get_SIF(objp->instance) & SIF_NAVBUOY ) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// only apply damage to a ship once from a shockwave
|
|
for ( i = 0; i < sw->num_objs_hit; i++ ) {
|
|
if ( objp->signature == sw->obj_sig_hitlist[i] ){
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( i < sw->num_objs_hit ){
|
|
continue;
|
|
}
|
|
|
|
if ( weapon_area_calc_damage(objp, &sw->pos, sw->inner_radius, sw->outer_radius, sw->blast, sw->damage, &blast, &damage, sw->radius) == -1 ){
|
|
continue;
|
|
}
|
|
|
|
// okay, we have damage applied, record the object signature so we don't repeatedly apply damage
|
|
Assert(sw->num_objs_hit < SW_MAX_OBJS_HIT);
|
|
if ( sw->num_objs_hit >= SW_MAX_OBJS_HIT) {
|
|
sw->num_objs_hit--;
|
|
}
|
|
|
|
switch(objp->type) {
|
|
case OBJ_SHIP:
|
|
sw->obj_sig_hitlist[sw->num_objs_hit++] = objp->signature;
|
|
ship_apply_global_damage(objp, shockwave_objp, &sw->pos, damage );
|
|
weapon_area_apply_blast(NULL, objp, &sw->pos, blast, 1);
|
|
break;
|
|
case OBJ_ASTEROID:
|
|
asteroid_hit(objp, NULL, NULL, damage);
|
|
break;
|
|
default:
|
|
Int3();
|
|
break;
|
|
}
|
|
|
|
|
|
// If this shockwave hit the player, play shockwave impact sound
|
|
if ( objp == Player_obj ) {
|
|
snd_play( &Snds[SND_SHOCKWAVE_IMPACT], 0.0f, MAX(0.4f, damage/Weapon_info[sw->weapon_info_index].damage) );
|
|
}
|
|
|
|
} // end for
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_render()
|
|
//
|
|
// Draw the shockwave identified by handle
|
|
//
|
|
// input: objp => pointer to shockwave object
|
|
//
|
|
extern int Cmdline_nohtl;
|
|
void shockwave_render(object *objp)
|
|
{
|
|
shockwave *sw;
|
|
shockwave_info *si;
|
|
vertex p;
|
|
|
|
Assert(objp->type == OBJ_SHOCKWAVE);
|
|
Assert(objp->instance >= 0 && objp->instance < MAX_SHOCKWAVES);
|
|
|
|
sw = &Shockwaves[objp->instance];
|
|
si = &Shockwave_info[sw->shockwave_info_index];
|
|
|
|
if( (sw->delay_stamp != -1) && !timestamp_elapsed(sw->delay_stamp)){
|
|
return;
|
|
}
|
|
|
|
if ( (sw->current_bitmap < 0) && (sw->model < 0) ) {
|
|
return;
|
|
}
|
|
|
|
// turn off fogging
|
|
if(The_mission.flags & MISSION_FLAG_FULLNEB){
|
|
gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
|
|
}
|
|
|
|
if (sw->model > -1) {
|
|
float model_Interp_scale_xyz = sw->radius / 50.0f;
|
|
|
|
model_set_warp_globals( model_Interp_scale_xyz, model_Interp_scale_xyz, model_Interp_scale_xyz, -1, 1.0f - (sw->radius/sw->outer_radius) );
|
|
|
|
float dist = vm_vec_dist_quick( &sw->pos, &Eye_position );
|
|
|
|
model_set_detail_level((int)(dist / (sw->radius * 10.0f)));
|
|
gr_set_cull(0);
|
|
model_render( sw->model, &Objects[sw->objnum].orient, &sw->pos, MR_NO_LIGHTING | MR_NO_FOGGING | MR_NORMAL | MR_CENTER_ALPHA | MR_NO_CULL, sw->objnum);
|
|
gr_set_cull(1);
|
|
|
|
model_set_warp_globals();
|
|
}else{
|
|
if (!Cmdline_nohtl) {
|
|
g3_transfer_vertex(&p, &sw->pos);
|
|
} else {
|
|
g3_rotate_vertex(&p, &sw->pos);
|
|
}
|
|
|
|
gr_set_bitmap(sw->current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f );
|
|
g3_draw_rotated_bitmap(&p, fl_radian(sw->rot_angles.p), sw->radius, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_load()
|
|
//
|
|
// Call to load a Shockwave_type once its name is in Shockwave_filenames
|
|
//
|
|
int shockwave_load(int info_index)
|
|
{
|
|
Assert(info_index >= 0);
|
|
Assert(info_index < MAX_SHOCKWAVE_TYPES);
|
|
|
|
shockwave_info *si = &Shockwave_info[info_index];
|
|
|
|
if ( (si->bitmap_id >= 0) && (info_index < NUM_DEFAULT_SHOCKWAVE_TYPES) ) {
|
|
// defaults are only loaded/unloaded once so bail if we are here twice
|
|
return 1;
|
|
}
|
|
|
|
if ( si->bitmap_id >= 0 ) {
|
|
Warning(LOCATION, "Attempted to load a shockwave twice!");
|
|
return 1;
|
|
}
|
|
|
|
si->bitmap_id = bm_load_animation( Shockwave_filenames[info_index], &si->num_frames, &si->fps, 1 );
|
|
|
|
if ( si->bitmap_id < 0 ) {
|
|
Error(LOCATION, "Could not load shockwave '%s'\n", Shockwave_filenames[info_index]);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_init()
|
|
//
|
|
// Call once at the start of each level (mission)
|
|
//
|
|
void shockwave_level_init()
|
|
{
|
|
int i;
|
|
shockwave_info *si;
|
|
|
|
default_shockwave_model = -1;
|
|
|
|
for (i = 0; i < MAX_SHOCKWAVE_TYPES; i++) {
|
|
if (Default_shockwave_loaded && (i < NUM_DEFAULT_SHOCKWAVE_TYPES))
|
|
continue;
|
|
|
|
si = &Shockwave_info[i];
|
|
si->bitmap_id = -1;
|
|
si->num_frames = 0;
|
|
si->fps = 0;
|
|
}
|
|
|
|
// try and load in a 3d shockwave first
|
|
mprintf(("SHOCKWAVE => Loading default shockwave model... \n"));
|
|
|
|
// Goober5000 - check for existence of file before trying to load it
|
|
if (cf_exists_full("shockwave.pof", CF_TYPE_MODELS))
|
|
{
|
|
default_shockwave_model = model_load("shockwave.pof", 0, NULL, 0);
|
|
}
|
|
|
|
if (default_shockwave_model >= 0) {
|
|
mprintf(("SHOCKWAVE => Default model load: SUCCEEDED!!\n"));
|
|
} else {
|
|
mprintf(("SHOCKWAVE => Default model load: FAILED!! Falling back to 2D effect...\n"));
|
|
|
|
// only try to load the default 2d versions if 3d load failed
|
|
for (i = 0; i < NUM_DEFAULT_SHOCKWAVE_TYPES; i++) {
|
|
shockwave_load(i);
|
|
}
|
|
|
|
Default_shockwave_loaded = 1;
|
|
}
|
|
|
|
list_init(&Shockwave_list);
|
|
|
|
for ( i = 0; i < MAX_SHOCKWAVES; i++ ) {
|
|
Shockwaves[i].flags = 0;
|
|
Shockwaves[i].objnum = -1;
|
|
Shockwaves[i].model = -1;
|
|
}
|
|
|
|
Shockwave_inited = 1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_level_close()
|
|
//
|
|
// Call at the close of each level (mission)
|
|
void shockwave_level_close()
|
|
{
|
|
if (Shockwave_inited)
|
|
shockwave_delete_all();
|
|
else
|
|
return;
|
|
|
|
//Unload all non-default shockwaves
|
|
int i;
|
|
shockwave_info *si;
|
|
|
|
for (i = NUM_DEFAULT_SHOCKWAVE_TYPES; i < MAX_SHOCKWAVE_TYPES; i++)
|
|
{
|
|
si = &Shockwave_info[i];
|
|
|
|
if (si->bitmap_id >= 0)
|
|
bm_release(si->bitmap_id);
|
|
|
|
si->bitmap_id = -1;
|
|
si->num_frames = 0;
|
|
si->fps = 0;
|
|
Shockwave_filenames[i][0] = '\0';
|
|
}
|
|
|
|
// NOTE: The model_unload() level close code will properly handle the 3d shockwaves
|
|
// for us so don't do anything about them here.
|
|
|
|
Shockwave_inited = 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_close()
|
|
//
|
|
// Called at game-shutdown to
|
|
//
|
|
void shockwave_close()
|
|
{
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_move_all()
|
|
//
|
|
// Simulate all shockwaves in Shockwave_list
|
|
//
|
|
// input: frametime => time for last frame in ms
|
|
//
|
|
void shockwave_move_all(float frametime)
|
|
{
|
|
shockwave *sw, *next;
|
|
|
|
sw = GET_FIRST(&Shockwave_list);
|
|
while ( sw != &Shockwave_list ) {
|
|
next = sw->next;
|
|
Assert(sw->objnum != -1);
|
|
shockwave_move(&Objects[sw->objnum], frametime);
|
|
sw = next;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------
|
|
// shockwave_render_all()
|
|
//
|
|
//
|
|
void shockwave_render_all()
|
|
{
|
|
shockwave *sw, *next;
|
|
|
|
sw = GET_FIRST(&Shockwave_list);
|
|
while ( sw != &Shockwave_list ) {
|
|
next = sw->next;
|
|
Assert(sw->objnum != -1);
|
|
shockwave_render(&Objects[sw->objnum]);
|
|
sw = next;
|
|
}
|
|
}
|
|
|
|
// return the weapon_info_index field for a shockwave
|
|
int shockwave_weapon_index(int index)
|
|
{
|
|
return Shockwaves[index].weapon_info_index;
|
|
}
|
|
|
|
// return the maximum radius for specified shockwave
|
|
float shockwave_max_radius(int index)
|
|
{
|
|
return Shockwaves[index].outer_radius;
|
|
}
|
|
|
|
void shockwave_page_in()
|
|
{
|
|
int i;
|
|
shockwave_info *si;
|
|
|
|
// load in shockwaves
|
|
for ( i=0; i<MAX_SHOCKWAVE_TYPES; i++ ) {
|
|
si = &Shockwave_info[i];
|
|
bm_page_in_texture( si->bitmap_id, si->num_frames );
|
|
}
|
|
|
|
if (default_shockwave_model >= 0)
|
|
model_page_in_textures(default_shockwave_model);
|
|
}
|
|
|
|
int shockwave_add(char *bm_name)
|
|
{
|
|
for(int i = 0; i < MAX_SHOCKWAVE_TYPES; i++)
|
|
{
|
|
if(!stricmp(Shockwave_filenames[i], bm_name))
|
|
{
|
|
return i;
|
|
}
|
|
else if(!strlen(Shockwave_filenames[i]))
|
|
{
|
|
strcpy(Shockwave_filenames[i], bm_name);
|
|
|
|
shockwave_load(i);
|
|
|
|
return i;
|
|
}
|
|
}
|
|
|
|
Warning(LOCATION, "Could not add shockwave type %s, as MAX_SHOCKWAVE_TYPES has been reached. Contact an fs2_open coder if you REALLY think you need more than %d shockwaves", bm_name, MAX_SHOCKWAVE_TYPES-NUM_DEFAULT_SHOCKWAVE_TYPES);
|
|
return -1;
|
|
}
|
|
|
|
//Loads a shockwave in preparation for a mission
|
|
void shockwave_create_info::load()
|
|
{
|
|
if(strlen(name))
|
|
{
|
|
shockwave_add(name);
|
|
}
|
|
if(strlen(pof_name))
|
|
{
|
|
int index = model_load(pof_name, 0, NULL);
|
|
model_page_in_textures(index);
|
|
}
|
|
}
|