Compare commits

...
66 Commits
Author SHA1 Message Date
Lari Nieminen 2b53bde255 Merge branch 'master' of https://github.com/scp-fs2open/fs2open.github.com into fotg 2015-05-04 02:32:51 +03:00
Lari Nieminen a4ac216d7a Ported all code from old zookeeper branch. 2015-05-04 02:10:01 +03:00
Fabian Woltermann 189275da56 Merge pull request #56 from asarium/coverity/1093600
Fix for Coverity 1093600: Negative array index read
2015-05-03 21:57:23 +02:00
Fabian Woltermann 4c7d80cba8 Merge pull request #63 from asarium/coverity/1093530
Fix for Coverity 1093530: Negative array index read
2015-05-03 21:56:16 +02:00
Fabian Woltermann 4a14e26256 Merge pull request #64 from asarium/coverity/1093515
Fix for Coverity 1093515: Negative array index read
2015-05-03 21:55:50 +02:00
Fabian Woltermann 0fc8e53f5f Merge pull request #65 from asarium/coverity/1237276
Fix for Coverity 1237276: Uninitialized scalar field
2015-05-03 21:55:04 +02:00
Fabian Woltermann ba2a1c9e7d Merge pull request #62 from asarium/coverity/1093555
Fix for Coverity 1093555: Negative array index read
2015-05-03 21:53:56 +02:00
Fabian Woltermann 115a2979b1 Merge pull request #67 from asarium/fix/aigoals
Fix usage of negative index
2015-05-03 21:53:01 +02:00
asarium e9b9797b6e Fix usage of negative index
I have no idea why this didn't cause any issues earlier...
2015-05-03 21:27:23 +02:00
asarium da0ef89ac5 Fix for Coverity 1237276: Uninitialized scalar field
The field will contain an arbitrary value left over from earlier computations.
In subtitle::​subtitle(int, int, char const*, char const*, float, float, color const*, int, bool, bool, int, int, bool): A scalar field is not initialized by the constructor
2015-05-03 14:55:06 +02:00
asarium fe49ef63aa Fix for Coverity 1093515: Negative array index read
A memory location at a negative offset from the beginning of the array will be read, resulting in incorrect values.
In multi_options_process_packet(unsigned char *, header *): Negative value used to index an array in a read operation
2015-05-03 14:44:26 +02:00
asarium f51bc78126 Fix for Coverity 1093530: Negative array index read
A memory location at a negative offset from the beginning of the array will be read, resulting in incorrect values.
In message_queue_process(): Negative value used to index an array in a read operation
2015-05-03 14:34:06 +02:00
m!m 711c7a7bf8 Merge pull request #61 from niffiwan/coverity-1093565
Fix Coverity 1093565: Negative array index read
2015-05-03 04:27:22 -07:00
asarium ca16b4710d Fix for Coverity 1093555: Negative array index read
A memory location at a negative offset from the beginning of the array will be read, resulting in incorrect values.
In multi_create_standalone_object(): Negative value used to index an array in a read operation

observer_create() will only fail in exceptional circumstances so a showing an error dialog should be acceptable
2015-05-03 13:12:23 +02:00
niffiwan 471cf4c988 Fix Coverity 1093565: Negative array index read
Add an assertion to catch any callers that haven't correctly set
the target_name. Also fix a minor typo in the comments
2015-05-03 20:31:16 +10:00
Goober5000 d734a36940 Merge pull request #60 from niffiwan/coverity-1093484
Fix Coverity 1093484
2015-05-03 02:14:34 -04:00
niffiwan 25079f5ed2 Fix Coverity 1093484
time_t is 64bit on 64bit systems; casting a pointer to a larger type is
dangerous, but assigning to a larger type should be fine
2015-05-03 15:42:25 +10:00
Goober5000 f0a0632d9d Merge pull request #51 from asarium/coverity/1093689
Fix for Coverity 1093689: Resource leak
2015-05-02 23:47:28 -04:00
asarium 3528dffabd Fix for Coverity 1093587: Negative array index read
The random value shouldn't be used if there are no countermeasures so this shouldn't cause any issues.
2015-05-02 23:53:39 +02:00
asarium 2aa569c1e7 Fix for Coverity 1093600: Negative array index read
hud_squadmsg_is_target_order_valid already checks if ainfo->target_objnum is less than zero so that check is not needed
2015-05-02 23:14:59 +02:00
Goober5000 584ec36f62 Merge pull request #53 from asarium/coverity/1093688
Fix for Coverity 1093688: Resource leak
2015-05-02 15:45:50 -04:00
Goober5000 93c46bd1f9 Merge pull request #55 from asarium/coverity/1093606
Fix for Coverity 1093606: Negative array index read
2015-05-02 15:45:17 -04:00
Goober5000 b6cc62c435 Merge pull request #54 from asarium/coverity/1093683
Fix for Coverity 1093683: Resource leak
2015-05-02 15:44:26 -04:00
asarium 00a288d53e Fix for Coverity 1093606: Negative array index read 2015-05-02 19:41:55 +02:00
asarium 4bfea90a17 Fix for Coverity 1093683: Resource leak 2015-05-02 19:32:39 +02:00
asarium aef3e3ac36 Fix for Coverity 1093688: Resource leak 2015-05-02 19:24:57 +02:00
asarium a7398d7f5c Fix for Coverity 1093689: Resource leak 2015-05-02 18:19:28 +02:00
Fabian Woltermann e2d740513a Merge pull request #47 from MageKing17/mantis/2971
Fix for 2971 from MageKing17: Stop executing HUD code when running as standalone.
2015-05-01 08:27:01 +02:00
MageKing17 1a29b395ab Stop standalones from executing hud_shield_quadrant_hit().
Also add some assertions to avoid (or at least help detect) similar errors in the future. Should fix Mantis 2971.
2015-04-30 22:10:17 -07:00
Goober5000 b2e01d6173 Merge pull request #42 from MageKing17/argument_sexps
*-argument sexp short-circuiting
2015-04-30 22:46:38 -04:00
Me bc17966b08 Merge pull request #46 from DahBlount/recoil
Feature: add primary weapon recoil
2015-05-01 08:02:53 +10:00
MageKing17 be9990f6a5 Fix cf_file_exists().
Was passing the pointer to *size instead of *offset, so instead of seeing if the file didn't have an offset, we were checking if it didn't have a size.
2015-04-29 23:21:49 -07:00
niffiwan c5bddac8fb Merge pull request #43 from niffiwan/cpp11_mk2
Cpp11 support for GCC
2015-04-30 14:36:20 +10:00
DahBlount 3de25b7e3a modifier value changes
We don't want to change things at run time so initialize them to
non-zero values.
2015-04-29 18:11:16 -07:00
DahBlount 2768863c36 Add ship_recoil_modifier 2015-04-29 18:01:52 -07:00
DahBlount 7b78df2363 Add "apply recoil" flag and modifier
This adds the "apply recoil" weapon flag and $Recoil Modifier:
weapons.tbl entry.
2015-04-29 17:26:33 -07:00
MageKing17 d84736be1c Revert "Made the firepoint HUD gauge light up only the firepoints which will fire next, if "dynamic primary linking" ship flag or "cycle" weapon flag is used."
This reverts commit 5042c44904.

(Apparently, "git revert" on a range is only inclusive of the end commit, not the starting commit.)
2015-04-29 16:35:41 -07:00
MageKing17 1591237acf Reverting recent string of commits.
Since they didn't go through code review (and break compilation), reverting the recent string of commits (just used "git revert -n 5042c44..05b4635").
2015-04-29 16:19:59 -07:00
zookeeper 05b4635048 Added bay arrive/depart speed multipliers to +Path Metadata.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@11271 387891d4-d844-0410-90c0-e4c51a9137d3

Conflicts:
	code/ai/ai_profiles.cpp
2015-04-29 23:19:02 +03:00
zookeeper eef1041323 Initialize bay_arrive_speed_mult and bay_depart_speed_mult.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@10731 387891d4-d844-0410-90c0-e4c51a9137d3

Conflicts:
	code/ai/ai_profiles.cpp
2015-04-29 23:17:51 +03:00
zookeeper 18058a45f7 Added ai_profiles.tbl options to force AI ships flying bay paths to gradually accelerate/decelerate instead of flying the path at max speed.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@10422 387891d4-d844-0410-90c0-e4c51a9137d3

Conflicts:
	code/ai/ai_profiles.cpp
2015-04-29 23:16:55 +03:00
zookeeper fbb76863fd Probably fixed a bug with the next/prev subsystem targeting keys not working if the target only has one subsystem.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@11209 387891d4-d844-0410-90c0-e4c51a9137d3
2015-04-29 23:12:42 +03:00
zookeeper 400fd0f9a8 Fixed $Thruster Glow Noise Mult not having effect in the ship lab.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@10789 387891d4-d844-0410-90c0-e4c51a9137d3
2015-04-29 23:07:41 +03:00
zookeeper b18337754d Added a $Model Icon Direction ship table entry for overriding the angle from which ship icons are rendered from.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@10612 387891d4-d844-0410-90c0-e4c51a9137d3
2015-04-29 23:04:25 +03:00
zookeeper 92a28b71cb Added a $Thruster Glow Noise Mult ship table entry for decreasing/increasing the effect of noise applied to the glow radius.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@10610 387891d4-d844-0410-90c0-e4c51a9137d3
2015-04-29 23:04:24 +03:00
zookeeper 0656175a72 Added a $Minimum Engine Volume ship table entry for specifying the minimum engine sound volume used when ship is stationary.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@10609 387891d4-d844-0410-90c0-e4c51a9137d3

Conflicts:
	code/object/objectsnd.cpp
2015-04-29 23:04:23 +03:00
zookeeper dc820fdfc1 Avoid loading the anchor ship model multiple times when resolving path masks.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@11235 387891d4-d844-0410-90c0-e4c51a9137d3
2015-04-29 22:45:57 +03:00
zookeeper 5042c44904 Made the firepoint HUD gauge light up only the firepoints which will fire next, if "dynamic primary linking" ship flag or "cycle" weapon flag is used.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@11256 387891d4-d844-0410-90c0-e4c51a9137d3
2015-04-29 22:42:58 +03:00
Lari Nieminen 91000b4468 Revert "Fixed +Spread From LOD not working right."
This reverts commit 4b15ec4e75.
2015-04-29 22:41:17 +03:00
Lari Nieminen 91614162f2 Merge branch 'master' of https://github.com/scp-fs2open/fs2open.github.com 2015-04-29 22:38:05 +03:00
zookeeper 4b15ec4e75 Fixed +Spread From LOD not working right.
git-svn-id: svn://svn.icculus.org/fs2open/branches/zookeeper@11268 387891d4-d844-0410-90c0-e4c51a9137d3
2015-04-29 22:36:43 +03:00
MageKing17 e84a6e8d33 Fix tech room mission lists.
get_mission_info() was returning an uninitialized int due to rval no longer being initialized to 0 by setjmp(). Since rval isn't actually needed anymore, I went ahead and removed it. The only bits of code that actually check the return value of get_mission_info() are the tech room's mission simulator and some of the multiplayer code, so this bug wasn't actually preventing missions from being played through the ready room.
2015-04-29 12:34:11 -07:00
niffiwan 763601033b Remove unused function from palman.[cpp|h] 2015-04-29 21:00:19 +10:00
niffiwan 0ff8c8191f Remove gcc -Wshadow warnings 2015-04-29 20:55:56 +10:00
niffiwan b0bb0ee3be Remove gcc -Wunused-but-set-variable warnings 2015-04-29 20:27:49 +10:00
MageKing17 ad91ba61b5 Short-circuit eval_sexp() on SEXP_NAN_FOREVER.
Since SEXP_NAN_FOREVER is supposed to indicate that the node will always evaluate to SEXP_NAN_FOREVER, we should short-circuit the process like we do for SEXP_KNOWN_TRUE and SEXP_KNOWN_FALSE.
2015-04-27 03:11:33 -07:00
MageKing17 7dea7075e7 Clean up eval_sexp() return value comparisons.
From niffiwan and myself (almost entirely niffiwan). Since eval_sexp() can't actually (and shouldn't) return certain special values, remove conditions checking for them and remove the erroneous comment claiming they should be returned.
2015-04-27 03:09:45 -07:00
MageKing17 9ec10dd3e6 Fix memory leak in for-counter.
Switch from strdup() to vm_strdup(), and make sure the allocated strings get freed after usage.
2015-04-27 03:06:28 -07:00
MageKing17 83b59fb76c Make *-argument SEXPs possible to short-circuit.
Fixes Mantis 3136. Written by niffiwan and myself. Allows the *-of SEXPs to return SEXP_KNOWN_FALSE when they can't evaluate ever again, allowing the when-argument or every-time-argument SEXP containing them to itself return SEXP_KNOWN_FALSE.
2015-04-27 03:05:18 -07:00
niffiwan e3715cc420 change var names to avoid warnings re shadowing 2014-01-01 19:58:36 +10:00
niffiwan 366f4d5642 set HAVE_CXX11 for clang 2014-01-01 19:30:05 +10:00
niffiwan 547d615552 set HAVE_CXX11 for MSVC 2014-01-01 18:56:32 +10:00
niffiwan 4f074d94d1 Add compile time catch for memmove used on non-trivial objects 2013-12-22 20:09:44 +10:00
niffiwan a4ac843d5b Add compile time catch for memcpy used on non-trivial objects 2013-12-22 19:53:52 +10:00
niffiwan 359a98410a Add compile time catch for memset used on non-trivial objects
Fix one instance of this problem in osapi/outwnd_unix.cpp
2013-12-16 19:44:23 +10:00
niffiwan 1acfc1c326 Allow gcc on Linux to compile with -std=c++11
Tested with 4.6.3, 4.7.2 & 4.8.0
2013-12-16 19:37:02 +10:00
69 changed files with 1585 additions and 649 deletions

No files matched your search

+9
View File
@@ -462,6 +462,15 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$strict turret-tagged-only targeting:", AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING, AIP_FLAG2);
profile->bay_arrive_speed_mult = 1.0f;
profile->bay_depart_speed_mult = 1.0f;
if (optional_string("$bay arrive start speed multiplier:")) {
stuff_float(&profile->bay_arrive_speed_mult);
}
if (optional_string("$bay depart end speed multiplier:")) {
stuff_float(&profile->bay_depart_speed_mult);
}
// ----------
// compatibility
+5
View File
@@ -151,6 +151,11 @@ typedef struct ai_profile_t {
int ai_path_mode;
// Ships flying bay paths will gradually accelerate/decelerate instead of
// flying the whole path at max speed
float bay_arrive_speed_mult;
float bay_depart_speed_mult;
} ai_profile_t;
+48 -2
View File
@@ -4011,11 +4011,57 @@ float ai_path_1()
dot_to_next = vm_vec_dot_to_point(&nvel_vec, &Pl_objp->pos, &gnvp);
// This path mode respects the "cap-waypoint-speed" SEXP
float max_allowed_speed = 0;
float max_allowed_speed = 0.0f;
if ( aip->waypoint_speed_cap > 0) {
max_allowed_speed = (float) aip->waypoint_speed_cap;
}
// Maybe gradually ramp up/down the speed of a ship flying a fighterbay path
if (aip->mode == AIM_BAY_EMERGE || (aip->mode == AIM_BAY_DEPART && aip->path_cur != aip->path_start)) {
SCP_string pathName(pm->paths[Path_points[aip->path_start].path_num].name);
ship_info *gsip = &Ship_info[gshipp->ship_info_index];
float speed_mult = 1.0f;
if (aip->mode == AIM_BAY_EMERGE) { // Arriving
if (gsip->pathMetadata.find(pathName) != gsip->pathMetadata.end()) {
speed_mult = gsip->pathMetadata[pathName].arrive_speed_mult;
}
if (speed_mult == FLT_MIN) {
speed_mult = The_mission.ai_profile->bay_arrive_speed_mult;
}
} else { // Departing
if (gsip->pathMetadata.find(pathName) != gsip->pathMetadata.end()) {
speed_mult = gsip->pathMetadata[pathName].depart_speed_mult;
}
if (speed_mult == FLT_MIN) {
speed_mult = The_mission.ai_profile->bay_depart_speed_mult;
}
}
if (speed_mult != 1.0f) {
// We use the distance between the first and last point on the path here; it's not accurate
// if the path is not straight, but should be good enough usually; can be changed if necessary.
float total_path_length = vm_vec_dist_quick(&Path_points[aip->path_start].pos, &Path_points[aip->path_start + num_points - 1].pos);
float dist_to_end;
if (aip->mode == AIM_BAY_EMERGE) { // Arriving
dist_to_end = vm_vec_dist_quick(&Pl_objp->pos, &Path_points[aip->path_start].pos);
} else { // Departing
dist_to_end = vm_vec_dist_quick(&Pl_objp->pos, &Path_points[aip->path_start + num_points - 1].pos);
}
// Calculate max speed, but respect the waypoint speed cap if it's lower
float max_bay_speed = sip->max_speed * (speed_mult + (1.0f - speed_mult) * (dist_to_end / total_path_length));
if (max_allowed_speed == 0.0f) {
max_allowed_speed = max_bay_speed;
} else {
max_allowed_speed = MIN(max_allowed_speed, max_bay_speed);
}
}
}
set_accel_for_docking(Pl_objp, aip, dot, dot_to_next, dist_to_next, dist_to_goal, sip, max_allowed_speed);
aip->prev_dot_to_goal = dot;
@@ -7583,7 +7629,7 @@ void update_aspect_lock_information(ai_info *aip, vec3d *vec_to_enemy, float dis
wip = &Weapon_info[swp->secondary_bank_weapons[swp->current_secondary_bank]];
if (num_weapon_types && (wip->wi_flags & WIF_LOCKED_HOMING)) {
if (num_weapon_types && (wip->wi_flags & WIF_LOCKED_HOMING) && !(shipp->flags2 & SF2_NO_SECONDARY_LOCKON)) {
if (dist_to_enemy > 300.0f - MIN(enemy_radius, 100.0f))
aip->ai_flags |= AIF_SEEK_LOCK;
else
+3 -2
View File
@@ -171,7 +171,7 @@ void ai_post_process_mission()
// Goober5000 - MK originally iterated on only the first wing; now we iterate on only the player wing
// because the player wing may not be first
for ( i = 0; i < MAX_STARTING_WINGS; i++ ) {
if ( Starting_wings[i] == Player_ship->wingnum ) {
if (Starting_wings[i] >= 0 && Starting_wings[i] == Player_ship->wingnum) {
wing *wingp;
wingp = &Wings[Starting_wings[i]];
@@ -528,7 +528,7 @@ int ai_goal_find_dockpoint(int shipnum, int dock_type)
}
// function to fix up dock point references for objects.
// passed are the pointer to goal we are working with. aip if the ai_info pointer
// passed are the pointer to goal we are working with. aip is the ai_info pointer
// of the ship with the order. aigp is a pointer to the goal (of aip) of which we are
// fixing up the docking points
void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
@@ -537,6 +537,7 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
Assert ( aip->shipnum != -1 );
shipnum = ship_name_lookup( aigp->target_name );
Assertion ( shipnum != -1, "Couldn't find ai goal's target_name (%s); get a coder!\n", aigp->target_name );
docker_index = -1;
dockee_index = -1;
+1
View File
@@ -63,6 +63,7 @@ union bm_extra_info {
// stuff for static animations
ubyte type; //!< type for individual images
char filename[MAX_FILENAME_LEN]; //!< filename for individual images
bool in_subdir; // Whether frames are in their own subdirectory
} eff;
} ani;
+100 -6
View File
@@ -34,6 +34,7 @@
#include "pngutils/pngutils.h"
#include "ship/ship.h"
#include "tgautils/tgautils.h"
#include "cfile/cfilesystem.h"
#ifdef _WIN32
#include <windows.h>
@@ -48,7 +49,20 @@
/**
* @todo upgrade this to an inline funciton, taking bitmap_entry and const char* as arguments
*/
#define EFF_FILENAME_CHECK { if ( be->type == BM_TYPE_EFF ) strcpy_s( filename, be->info.ani.eff.filename ); else strcpy_s( filename, be->filename ); }
#define EFF_FILENAME_CHECK \
{ \
if ( be->type == BM_TYPE_EFF ) { \
strcpy_s( filename, be->info.ani.eff.filename ); \
if (be->info.ani.eff.in_subdir) { \
if (!set_temp_subdir_pathtype(bm_bitmaps[be->info.ani.first_frame].filename)) { \
mprintf(("BMPMAN: Failed to set temporary pathtype for %s: EFF_FILENAME_CHECK failed!\n", be->filename)); \
} \
} \
} \
else { \
strcpy_s( filename, be->filename ); \
} \
}
// --------------------------------------------------------------------------------------------------------------------
// Monitor variables
MONITOR(NumBitmapPage)
@@ -78,6 +92,8 @@ const int BM_ANI_NUM_TYPES = sizeof(bm_ani_type_list) / sizeof(ubyte);
void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES];
// --------------------------------------------------------------------------------------------------------------------
// Declaration of protected variables (defined in cmdline.cpp).
extern int Cmdline_cache_bitmaps;
@@ -1026,8 +1042,9 @@ int bm_load(const SCP_string& filename) {
return bm_load(filename.c_str());
}
int bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, ubyte *type) {
int bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, ubyte *type, bool *in_subdir) {
int frames = 0, fps = 30, keyframe = 0;
bool subdir = false;
char ext[8];
ubyte c_type = BM_TYPE_NONE;
char file_text[1024];
@@ -1065,6 +1082,10 @@ int bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int
return -1;
}
if (optional_string( "$Subdir:" )) {
stuff_boolean(&subdir);}
// done with EFF so unpause parsing so whatever can continue
unpause_parse();
@@ -1101,6 +1122,8 @@ int bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int
if (key)
*key = keyframe;
*in_subdir = subdir;
return 0;
}
@@ -1111,6 +1134,7 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
char filename[MAX_FILENAME_LEN];
int reduced = 0;
int anim_fps = 0, anim_frames = 0, key = 0;
bool in_subdir = false;
int anim_width = 0, anim_height = 0;
ubyte type = BM_TYPE_NONE, eff_type = BM_TYPE_NONE, c_type = BM_TYPE_NONE;
int bpp = 0, mm_lvl = 0, img_size = 0;
@@ -1197,7 +1221,7 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
// it's an effect file, any readable image type with eff being txt
if (type == BM_TYPE_EFF) {
if (bm_load_and_parse_eff(filename, dir_type, &anim_frames, &anim_fps, &key, &eff_type) != 0) {
if (bm_load_and_parse_eff(filename, dir_type, &anim_frames, &anim_fps, &key, &eff_type, &in_subdir) != 0 ) {
mprintf(("BMPMAN: Error reading EFF\n"));
return -1;
} else {
@@ -1259,6 +1283,10 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
return -1;
}
if (in_subdir) {
set_temp_subdir_pathtype(filename);
}
int first_handle = bm_get_next_handle();
Assert(strlen(filename) < MAX_FILENAME_LEN);
@@ -1324,6 +1352,11 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
bm_bitmaps[n + i].num_mipmaps = mm_lvl;
bm_bitmaps[n + i].mem_taken = img_size;
bm_bitmaps[n + i].dir_type = dir_type;
bm_bitmaps[n + i].info.ani.eff.in_subdir = in_subdir;
if (in_subdir)
bm_bitmaps[n + i].dir_type = CF_TYPE_TEMP_SUBDIR_LOOKUP;
else
bm_bitmaps[n + i].dir_type = dir_type;
bm_bitmaps[n + i].load_count++;
@@ -1497,8 +1530,8 @@ bitmap * bm_lock(int handle, ubyte bpp, ubyte flags, bool nodebug) {
// read the file data
if (gr_bm_lock(be->filename, handle, bitmapnum, bpp, flags, nodebug) == -1) {
// oops, this isn't good - reset and return NULL
bm_unlock(bitmapnum);
bm_unload(bitmapnum);
bm_unlock( handle );
bm_unload( handle );
return NULL;
}
@@ -2067,6 +2100,61 @@ void bm_page_in_start() {
gr_bm_page_in_start();
}
/**
* Stuffs Pathtypes with an additional path leading to a subdir of the same name as the given file (minus file extension).
* Used for allowing frames of .eff animations to be found in their own subdirectories.
*
* Example: if called with "debris.eff" and that file is in data/maps, then Pathtypes[CF_TYPE_TEMP_SUBDIR_LOOKUP].path
* will be stuffed with data/maps/debris, allowing data/maps/debris/debris_0000.dds (etc) to be found
*/
bool set_temp_subdir_pathtype(const char *filename) {
// Gets the absolute path of the file, removes the part that is identical with the
// absolute root path and appends the filename to it (without extension), giving us
// a relative path that can be temporarily stuffed into Pathtypes so the frames can be found
char fullpath[MAX_PATH]; // Absolute path to the given file
char fullrootpath[MAX_PATH]; // Absolute root path
int size, offset; // Needed for cf_find_file_location, but not used
cf_create_default_path_string(fullrootpath, sizeof(fullrootpath) - 1, CF_TYPE_ROOT, NULL);
if (!cf_find_file_location(filename, CF_TYPE_ANY, sizeof(fullpath)-1, fullpath, &size, &offset)) {
mprintf(("BMPMAN: Failed to set temporary pathtype for %s: file not found!\n", filename));
return false;
}
#ifndef NDEBUG
if (strlen(fullpath) < strlen(fullrootpath)) {
mprintf(("BMPMAN: Path to %s was shorter than the root path, programmer thought it could never happen!\n%s\n%s\n", filename, fullpath, fullrootpath));
return false;
}
#endif
mprintf(("BMPMAN: Setting temporary pathtype for %s... ", filename));
char *trimmed_path; // The differing portion of fullpath and fullrootpath
trimmed_path = &fullpath[strlen(fullrootpath)];
char *extpos = strstr(trimmed_path, "."); // Where the file extension begins
char basepath[MAX_PATH]; // This will hold the final, relative path
// Copy the relative path of the given file to basepath, excluding the extension
strncpy(basepath, trimmed_path, extpos-trimmed_path);
// Make sure it's null-terminated right
basepath[(int)(extpos-trimmed_path)] = '\0';
// Free the old string first, if it's not the const initial empty string
if (Pathtypes[CF_TYPE_TEMP_SUBDIR_LOOKUP].path[0] != '\0') {
vm_free(Pathtypes[CF_TYPE_TEMP_SUBDIR_LOOKUP].path);
}
Pathtypes[CF_TYPE_TEMP_SUBDIR_LOOKUP].path = vm_strdup(basepath);
mprintf(("OK. Temporary pathtype is now %s.\n", Pathtypes[CF_TYPE_TEMP_SUBDIR_LOOKUP].path));
return true;
}
void bm_page_in_stop() {
int i;
@@ -2085,13 +2173,19 @@ void bm_page_in_stop() {
if ((bm_bitmaps[i].type != BM_TYPE_NONE) && (bm_bitmaps[i].type != BM_TYPE_RENDER_TARGET_DYNAMIC) && (bm_bitmaps[i].type != BM_TYPE_RENDER_TARGET_STATIC)) {
if (bm_bitmaps[i].preloaded) {
if (bm_preloading) {
if (bm_bitmaps[i].type == BM_TYPE_EFF && bm_bitmaps[i].info.ani.eff.in_subdir) {
set_temp_subdir_pathtype(bm_bitmaps[i].filename);
}
if (!gr_preload(bm_bitmaps[i].handle, (bm_bitmaps[i].preloaded == 2))) {
mprintf(("Out of VRAM. Done preloading.\n"));
bm_preloading = 0;
}
} else {
bm_lock(bm_bitmaps[i].handle, (bm_bitmaps[i].used_flags == BMP_AABITMAP) ? 8 : 16, bm_bitmaps[i].used_flags);
bm_unlock(bm_bitmaps[i].handle);
if (bm_bitmaps[i].ref_count >= 1) {
bm_unlock( bm_bitmaps[i].handle );
}
}
n++;
+11 -5
View File
@@ -415,6 +415,11 @@ void bm_get_frame_usage(int *ntotal, int *nnew);
*/
int bm_reload(int bitmap_handle, const char* filename);
/**
* @brief Stuffs Pathtypes with an additional path leading to a subdir of the same name as the given file (minus file extension)
*/
bool set_temp_subdir_pathtype(const char *filename);
/**
* @brief Tells bmpman to start keeping track of what bitmaps are used where
*/
@@ -622,16 +627,17 @@ int bm_set_render_target(int handle, int face = -1);
*
* @param[in] filename The filename of the .EFF
* @param[in] dir_type
* @param[out] nframes (optional) If given, is set to the number of frames this .EFF has
* @param[out] nfps (optional) If given, is set to the fps of this .EFF
* @param[out] key (optional) If given, is set to the keyframe index of this .EFF
* @param[out] type (optional) If given, is set to the BM_TYPE of the .EFF
* @param[out] nframes (optional) If given, is set to the number of frames this .EFF has
* @param[out] nfps (optional) If given, is set to the fps of this .EFF
* @param[out] key (optional) If given, is set to the keyframe index of this .EFF
* @param[out] type (optional) If given, is set to the BM_TYPE of the .EFF
* @param[out] in_subdir (optional) If given, is set to true if the frames of this .EFF are in a subdir
*
* @returns 0 If successful,
* @returns -1 if not successful
*
* @todo retval should be a bool
*/
int bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, ubyte *type);
int bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, ubyte *type, bool *in_subdir);
#endif
+8 -1
View File
@@ -540,8 +540,15 @@ void warp_camera::get_info(vec3d *position, matrix *orientation)
//*************************subtitle*************************
#define MAX_SUBTITLE_LINES 64
subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char* in_imageanim, float in_display_time, float in_fade_time, const color *in_text_color, int in_text_fontnum, bool center_x, bool center_y, int in_width, int in_height, bool in_post_shaded)
subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char* in_imageanim, float in_display_time,
float in_fade_time, const color *in_text_color, int in_text_fontnum, bool center_x, bool center_y, int in_width,
int in_height, bool in_post_shaded)
:display_time(-1.0f), fade_time(-1.0f), text_fontnum(-1), time_displayed(-1.0f), time_displayed_end(-1.0f),
post_shaded(false)
{
// Initialize color
gr_init_color(&text_color, 0, 0, 0);
SCP_string text_buf;
// basic init, this always has to be done
+2 -1
View File
@@ -86,6 +86,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
{ CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
{ CF_TYPE_TEMP_SUBDIR_LOOKUP, "", ".eff", CF_TYPE_DATA },
};
@@ -501,7 +502,7 @@ int cf_exists(const char *filename, int dir_type)
if ( (filename == NULL) || !strlen(filename) )
return 0;
return (cf_find_file_location(filename, dir_type, 0, NULL, &offset, NULL) && !offset);
return (cf_find_file_location(filename, dir_type, 0, NULL, NULL, &offset) && !offset);
}
// Goober5000
+2 -1
View File
@@ -78,8 +78,9 @@ typedef struct {
#define CF_TYPE_INTEL_ANIMS 34
#define CF_TYPE_SCRIPTS 35
#define CF_TYPE_FICTION 36
#define CF_TYPE_TEMP_SUBDIR_LOOKUP 37
#define CF_MAX_PATH_TYPES 37 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
#define CF_MAX_PATH_TYPES 38 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
// TRUE if type is specified and valid
+1
View File
@@ -901,6 +901,7 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
case CF_TYPE_MULTI_CACHE:
case CF_TYPE_MISSIONS:
case CF_TYPE_CACHE:
case CF_TYPE_TEMP_SUBDIR_LOOKUP:
cfs_slow_search = 1;
break;
+45 -6
View File
@@ -956,9 +956,9 @@ void control_config_reset_defaults(int presetnum)
// Reset keyboard defaults
for (i=0; i<CCFG_MAX; i++) {
// Note that key_default and joy_default are NOT overwritten here;
// they should retain the values of the first preset because
// for example the key-pressed SEXP works off the defaults of the first preset
// Note that key_default, joy_default and text_default are NOT
// overwritten here; they should retain the values of the first preset
Control_config[i].text = preset[i].text;
Control_config[i].key_id = preset[i].key_default;
Control_config[i].joy_id = preset[i].joy_default;
Control_config[i].tab = preset[i].tab;
@@ -2107,6 +2107,45 @@ void control_config_do_frame(float frametime)
List_buttons[i++].disable();
}
// If multiple controls presets are provided, display which one is in use
if (Control_config_presets.size() > 1) {
SCP_string preset_str;
int matching_preset = -1;
for (i=0; i<(int)Control_config_presets.size(); i++) {
bool this_preset_matches = true;
config_item *this_preset = Control_config_presets[i];
for (int j=0; j<CCFG_MAX; j++) {
if (!Control_config[j].disabled && Control_config[j].key_id != this_preset[j].key_default) {
this_preset_matches = false;
break;
}
}
if (this_preset_matches) {
matching_preset = i;
break;
}
}
if (matching_preset >= 0) {
sprintf(preset_str, "Controls: %s", Control_config_preset_names[matching_preset].c_str());
} else {
sprintf(preset_str, "Controls: custom");
}
gr_get_string_size(&w, NULL, preset_str.c_str());
gr_set_color_fast(&Color_text_normal);
if (gr_screen.res == GR_640) {
gr_string(16, (24 - font_height) / 2, preset_str.c_str(), GR_RESIZE_MENU);
} else {
gr_string(24, (40 - font_height) / 2, preset_str.c_str(), GR_RESIZE_MENU);
}
}
// blit help overlay if active
help_overlay_maybe_blit(Control_config_overlay_id, gr_screen.res);
@@ -2207,11 +2246,11 @@ int check_control_used(int id, int key)
// check what current modifiers are pressed
mask = 0;
if (keyd_pressed[KEY_LSHIFT] || key_down_count(KEY_LSHIFT) || keyd_pressed[KEY_RSHIFT] || key_down_count(KEY_RSHIFT)) {
if (keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]) {
mask |= KEY_SHIFTED;
}
if (keyd_pressed[KEY_LALT] || key_down_count(KEY_LALT) || keyd_pressed[KEY_RALT] || key_down_count(KEY_RALT)) {
if (keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT]) {
mask |= KEY_ALTED;
}
@@ -2226,7 +2265,7 @@ int check_control_used(int id, int key)
z &= KEY_MASK;
if (keyd_pressed[z] || key_down_count(z)) {
if (keyd_pressed[z]) {
control_used(id);
return 1;
}
+3 -1
View File
@@ -63,13 +63,14 @@ typedef struct config_item {
short joy_default; //!< default joystick button bound to action
char tab; //!< what tab (category) it belongs in
bool hasXSTR; //!< whether we should translate this with an XSTR
char *text; //!< describes the action in the config screen
char *default_text; //!< default description of the action
char type; //!< manner control should be checked in
short key_id; //!< actual key bound to action
short joy_id; //!< joystick button bound to action
int used; //!< has control been used yet in mission? If so, this is the timestamp
bool disabled; //!< whether this action should be available at all
bool continuous_ongoing;//!< whether this action is a continuous one and is currently ongoing
char *text; //!< overridable description of the action
} config_item;
/*!
@@ -292,6 +293,7 @@ extern int Control_config_overlay_id;
extern config_item Control_config[]; //!< Stores the keyboard configuration
extern SCP_vector<config_item*> Control_config_presets; // tabled control presets; pointers to config_item arrays
extern SCP_vector<SCP_string> Control_config_preset_names; // names for Control_config_presets (identical order of items)
extern char **Scan_code_text;
extern char **Joy_button_text;
+137 -120
View File
@@ -45,153 +45,153 @@ int Invert_axis_defaults[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
//XSTR:OFF
config_item Control_config[CCFG_MAX + 1] = {
// targeting a ship
{ KEY_T, -1, TARGET_TAB, true, "Target Next Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_T, -1, TARGET_TAB, true, "Target Previous Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_H, 2, TARGET_TAB, true, "Target Next Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_H, -1, TARGET_TAB, true, "Target Previous Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_H, -1, TARGET_TAB, true, "Toggle Auto Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_F, -1, TARGET_TAB, true, "Target Next Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_F, -1, TARGET_TAB, true, "Target Previous Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_Y, 4, TARGET_TAB, true, "Target Ship in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_G, -1, TARGET_TAB, true, "Target Target's Nearest Attacker", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_Y, -1, TARGET_TAB, true, "Target Last Ship to Send Transmission", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_T, -1, TARGET_TAB, true, "Turn Off Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_T, -1, TARGET_TAB, true, "Target Next Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_T, -1, TARGET_TAB, true, "Target Previous Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_H, 2, TARGET_TAB, true, "Target Next Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_H, -1, TARGET_TAB, true, "Target Previous Closest Hostile Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_H, -1, TARGET_TAB, true, "Toggle Auto Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_F, -1, TARGET_TAB, true, "Target Next Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_F, -1, TARGET_TAB, true, "Target Previous Closest Friendly Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_Y, 4, TARGET_TAB, true, "Target Ship in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_G, -1, TARGET_TAB, true, "Target Target's Nearest Attacker", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_Y, -1, TARGET_TAB, true, "Target Last Ship to Send Transmission", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_T, -1, TARGET_TAB, true, "Turn Off Targeting", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
// targeting a ship's subsystem
{ KEY_V, -1, TARGET_TAB, true, "Target Subsystem in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_S, -1, TARGET_TAB, true, "Target Next Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_S, -1, TARGET_TAB, true, "Target Previous Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_S, -1, TARGET_TAB, true, "Turn Off Targeting of Subsystems", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_V, -1, TARGET_TAB, true, "Target Subsystem in Reticle", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_S, -1, TARGET_TAB, true, "Target Next Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_S, -1, TARGET_TAB, true, "Target Previous Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_S, -1, TARGET_TAB, true, "Turn Off Targeting of Subsystems", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
// matching speed
{ KEY_M, -1, COMPUTER_TAB, true, "Match Target Speed", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_M, -1, COMPUTER_TAB, true, "Toggle Auto Speed Matching", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_M, -1, COMPUTER_TAB, true, "Match Target Speed", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_M, -1, COMPUTER_TAB, true, "Toggle Auto Speed Matching", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
// weapons
{ KEY_LCTRL, 0, WEAPON_TAB, true, "Fire Primary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SPACEBAR, 1, WEAPON_TAB, true, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PERIOD, -1, WEAPON_TAB, true, "Cycle Forward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_COMMA, -1, WEAPON_TAB, true, "Cycle Backward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Bank", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_X, 3, WEAPON_TAB, true, "Launch Countermeasure", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_LCTRL, 0, WEAPON_TAB, true, "Fire Primary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_SPACEBAR, 1, WEAPON_TAB, true, "Fire Secondary Weapon", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_PERIOD, -1, WEAPON_TAB, true, "Cycle Forward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_COMMA, -1, WEAPON_TAB, true, "Cycle Backward Primary Weapon", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Bank", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_DIVIDE, -1, WEAPON_TAB, true, "Cycle Secondary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_X, 3, WEAPON_TAB, true, "Launch Countermeasure", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
// controls
{ KEY_A, -1, SHIP_TAB, true, "Forward Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_Z, -1, SHIP_TAB, true, "Reverse Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD7, -1, SHIP_TAB, true, "Bank Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD9, -1, SHIP_TAB, true, "Bank Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD8, -1, SHIP_TAB, true, "Pitch Forward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD2, -1, SHIP_TAB, true, "Pitch Backward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD4, -1, SHIP_TAB, true, "Turn Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD6, -1, SHIP_TAB, true, "Turn Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_A, -1, SHIP_TAB, true, "Forward Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_Z, -1, SHIP_TAB, true, "Reverse Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_PAD7, -1, SHIP_TAB, true, "Bank Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_PAD9, -1, SHIP_TAB, true, "Bank Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_PAD8, -1, SHIP_TAB, true, "Pitch Forward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_PAD2, -1, SHIP_TAB, true, "Pitch Backward", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_PAD4, -1, SHIP_TAB, true, "Turn Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_PAD6, -1, SHIP_TAB, true, "Turn Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
// throttle controls
{ KEY_BACKSP, -1, SHIP_TAB, true, "Set Throttle to Zero", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SLASH, -1, SHIP_TAB, true, "Set Throttle to Max", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_LBRACKET, -1, SHIP_TAB, true, "Set Throttle to One-Third", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_RBRACKET, -1, SHIP_TAB, true, "Set Throttle to Two-Thirds", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_EQUAL, -1, SHIP_TAB, true, "Increase Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_MINUS, -1, SHIP_TAB, true, "Decrease Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_BACKSP, -1, SHIP_TAB, true, "Set Throttle to Zero", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SLASH, -1, SHIP_TAB, true, "Set Throttle to Max", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_LBRACKET, -1, SHIP_TAB, true, "Set Throttle to One-Third", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_RBRACKET, -1, SHIP_TAB, true, "Set Throttle to Two-Thirds", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_EQUAL, -1, SHIP_TAB, true, "Increase Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_MINUS, -1, SHIP_TAB, true, "Decrease Throttle 5 Percent", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
// squadmate messaging
{ KEY_SHIFTED | KEY_A, -1, COMPUTER_TAB, true, "Attack My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_Z, -1, COMPUTER_TAB, true, "Disarm My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_D, -1, COMPUTER_TAB, true, "Disable My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_V, -1, COMPUTER_TAB, true, "Attack My Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_X, -1, COMPUTER_TAB, true, "Capture My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Engage Enemy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_W, -1, COMPUTER_TAB, true, "Form on My Wing", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_I, -1, COMPUTER_TAB, true, "Ignore My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_P, -1, COMPUTER_TAB, true, "Protect My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_C, -1, COMPUTER_TAB, true, "Cover Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_J, -1, COMPUTER_TAB, true, "Return to Base", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_R, -1, COMPUTER_TAB, true, "Rearm Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_A, -1, COMPUTER_TAB, true, "Attack My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_Z, -1, COMPUTER_TAB, true, "Disarm My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_D, -1, COMPUTER_TAB, true, "Disable My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_V, -1, COMPUTER_TAB, true, "Attack My Subsystem", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_X, -1, COMPUTER_TAB, true, "Capture My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Engage Enemy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_W, -1, COMPUTER_TAB, true, "Form on My Wing", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_I, -1, COMPUTER_TAB, true, "Ignore My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_P, -1, COMPUTER_TAB, true, "Protect My Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_C, -1, COMPUTER_TAB, true, "Cover Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_J, -1, COMPUTER_TAB, true, "Return to Base", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_R, -1, COMPUTER_TAB, true, "Rearm Me", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_R, 6, TARGET_TAB, true, "Target Closest Attacking Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_R, 6, TARGET_TAB, true, "Target Closest Attacking Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
// Views
{ KEY_PADMULTIPLY, -1, COMPUTER_TAB, true, "Chase View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PADPERIOD, -1, COMPUTER_TAB, true, "External View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PADENTER, -1, COMPUTER_TAB, true, "Toggle External Camera Lock", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PAD0, -1, COMPUTER_TAB, true, "Free Look View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false }, // Not in use anymore (Swifty)
{ KEY_PADDIVIDE, -1, COMPUTER_TAB, true, "Current Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PADPLUS, -1, COMPUTER_TAB, true, "Increase View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PADMINUS, -1, COMPUTER_TAB, true, "Decrease View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PAD5, -1, COMPUTER_TAB, true, "Center View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 33, COMPUTER_TAB, true, "View Up", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 32, COMPUTER_TAB, true, "View Rear", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 34, COMPUTER_TAB, true, "View Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, 35, COMPUTER_TAB, true, "View Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_PADMULTIPLY, -1, COMPUTER_TAB, true, "Chase View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_PADPERIOD, -1, COMPUTER_TAB, true, "External View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_PADENTER, -1, COMPUTER_TAB, true, "Toggle External Camera Lock", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_PAD0, -1, COMPUTER_TAB, true, "Free Look View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL }, // Not in use anymore (Swifty)
{ KEY_PADDIVIDE, -1, COMPUTER_TAB, true, "Current Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_PADPLUS, -1, COMPUTER_TAB, true, "Increase View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_PADMINUS, -1, COMPUTER_TAB, true, "Decrease View Distance", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_PAD5, -1, COMPUTER_TAB, true, "Center View", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ -1, 33, COMPUTER_TAB, true, "View Up", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ -1, 32, COMPUTER_TAB, true, "View Rear", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ -1, 34, COMPUTER_TAB, true, "View Left", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ -1, 35, COMPUTER_TAB, true, "View Right", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_RAPOSTRO, -1, COMPUTER_TAB, true, "Cycle Radar Range", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_C, -1, COMPUTER_TAB, true, "Communications Menu", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, -1, true, "Show Objectives", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_J, -1, COMPUTER_TAB, true, "Enter Subspace (End Mission)", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_J, -1, TARGET_TAB, true, "Target Target's Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_TAB, 5, SHIP_TAB, true, "Afterburner", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_RAPOSTRO, -1, COMPUTER_TAB, true, "Cycle Radar Range", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_C, -1, COMPUTER_TAB, true, "Communications Menu", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ -1, -1, -1, true, "Show Objectives", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_J, -1, COMPUTER_TAB, true, "Enter Subspace (End Mission)", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_J, -1, TARGET_TAB, true, "Target Target's Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_TAB, 5, SHIP_TAB, true, "Afterburner", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_INSERT, -1, COMPUTER_TAB, true, "Increase Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_DELETE, -1, COMPUTER_TAB, true, "Decrease Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_HOME, -1, COMPUTER_TAB, true, "Increase Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_END, -1, COMPUTER_TAB, true, "Decrease Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PAGEUP, -1, COMPUTER_TAB, true, "Increase Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_PAGEDOWN, -1, COMPUTER_TAB, true, "Decrease Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_D, -1, COMPUTER_TAB, true, "Equalize Energy Settings", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_INSERT, -1, COMPUTER_TAB, true, "Increase Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_DELETE, -1, COMPUTER_TAB, true, "Decrease Weapon Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_HOME, -1, COMPUTER_TAB, true, "Increase Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_END, -1, COMPUTER_TAB, true, "Decrease Shield Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_PAGEUP, -1, COMPUTER_TAB, true, "Increase Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_PAGEDOWN, -1, COMPUTER_TAB, true, "Decrease Engine Energy", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_D, -1, COMPUTER_TAB, true, "Equalize Energy Settings", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_Q, 7, COMPUTER_TAB, true, "Equalize Shields", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_UP, -1, COMPUTER_TAB, true, "Augment Forward Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_DOWN, -1, COMPUTER_TAB, true, "Augment Rear Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_LEFT, -1, COMPUTER_TAB, true, "Augment Left Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_RIGHT, -1, COMPUTER_TAB, true, "Augment Right Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Laser->Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Shield->Laser", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_Q, 7, COMPUTER_TAB, true, "Equalize Shields", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_UP, -1, COMPUTER_TAB, true, "Augment Forward Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_DOWN, -1, COMPUTER_TAB, true, "Augment Rear Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_LEFT, -1, COMPUTER_TAB, true, "Augment Left Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_RIGHT, -1, COMPUTER_TAB, true, "Augment Right Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Laser->Shield", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_SCROLLOCK, -1, COMPUTER_TAB, true, "Transfer Energy Shield->Laser", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
// { -1, -1, -1, true, "Show Damage Popup Window" },
{ -1, -1, SHIP_TAB, false, "Glide When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, -1, SHIP_TAB, false, "Glide When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
//Backslash -- this was a convenient place for Glide When Pressed, as Show Damage Popup isn't used
{ -1, -1, SHIP_TAB, true, "Bank When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ -1, -1, -1, true, "Show Nav Map", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_E, -1, COMPUTER_TAB, true, "Add or Remove Escort", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Clear Escort List", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_E, -1, TARGET_TAB, true, "Target Next Escort Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_R, -1, TARGET_TAB, true, "Target Closest Repair Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, SHIP_TAB, true, "Bank When Pressed", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ -1, -1, -1, true, "Show Nav Map", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_E, -1, COMPUTER_TAB, true, "Add or Remove Escort", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_SHIFTED | KEY_E, -1, COMPUTER_TAB, true, "Clear Escort List", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_E, -1, TARGET_TAB, true, "Target Next Escort Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_R, -1, TARGET_TAB, true, "Target Closest Repair Ship", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_U, -1, TARGET_TAB, true, "Target Next Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_U, -1, TARGET_TAB, true, "Target Previous Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_N, -1, TARGET_TAB, true, "Target Newest Ship in Area", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_K, -1, TARGET_TAB, true, "Target Next Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_K, -1, TARGET_TAB, true, "Target Previous Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_U, -1, TARGET_TAB, true, "Target Next Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_U, -1, TARGET_TAB, true, "Target Previous Uninspected Cargo", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_N, -1, TARGET_TAB, true, "Target Newest Ship in Area", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_K, -1, TARGET_TAB, true, "Target Next Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_K, -1, TARGET_TAB, true, "Target Previous Live Turret", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_B, -1, TARGET_TAB, true, "Target Next Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_B, -1, TARGET_TAB, true, "Target Previous Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_B, -1, TARGET_TAB, true, "Target Next Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_B, -1, TARGET_TAB, true, "Target Previous Hostile Bomb or Bomber", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
// multiplayer messaging keys
{ KEY_1, -1, COMPUTER_TAB, true, "(Multiplayer) Message All", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_2, -1, COMPUTER_TAB, true, "(Multiplayer) Message Friendly", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_3, -1, COMPUTER_TAB, true, "(Multiplayer) Message Hostile", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_4, -1, COMPUTER_TAB, true, "(Multiplayer) Message Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_X, -1, COMPUTER_TAB, true, "(Multiplayer) Observer Zoom to Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_PERIOD, -1, COMPUTER_TAB, true, "Increase Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_COMMA, -1, COMPUTER_TAB, true, "Decrease Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_L, -1, COMPUTER_TAB, true, "Toggle High HUD Contrast", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_N, -1, COMPUTER_TAB, true, "(Multiplayer) Toggle Network Info", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_END, -1, COMPUTER_TAB, true, "(Multiplayer) Self Destruct", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_1, -1, COMPUTER_TAB, true, "(Multiplayer) Message All", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_2, -1, COMPUTER_TAB, true, "(Multiplayer) Message Friendly", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_3, -1, COMPUTER_TAB, true, "(Multiplayer) Message Hostile", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_4, -1, COMPUTER_TAB, true, "(Multiplayer) Message Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_X, -1, COMPUTER_TAB, true, "(Multiplayer) Observer Zoom to Target", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_PERIOD, -1, COMPUTER_TAB, true, "Increase Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_COMMA, -1, COMPUTER_TAB, true, "Decrease Time Compression", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_L, -1, COMPUTER_TAB, true, "Toggle High HUD Contrast", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_N, -1, COMPUTER_TAB, true, "(Multiplayer) Toggle Network Info", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_END, -1, COMPUTER_TAB, true, "(Multiplayer) Self Destruct", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
// Misc
{ KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, true, "Toggle HUD", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_3, -1, SHIP_TAB, true, "Right Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_1, -1, SHIP_TAB, true, "Left Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_PADPLUS, -1, SHIP_TAB, true, "Up Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_SHIFTED | KEY_PADENTER, -1, SHIP_TAB, true, "Down Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, true, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, COMPUTER_TAB, false, "Top-Down View", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ -1, -1, COMPUTER_TAB, false, "Target Padlock View", CC_TYPE_TRIGGER, -1, -1, 0, false, false }, // (Swifty) Toggle for VM_TRACK
{ KEY_SHIFTED | KEY_O, -1, COMPUTER_TAB, true, "Toggle HUD", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_3, -1, SHIP_TAB, true, "Right Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_1, -1, SHIP_TAB, true, "Left Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_PADPLUS, -1, SHIP_TAB, true, "Up Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_SHIFTED | KEY_PADENTER, -1, SHIP_TAB, true, "Down Thrust", CC_TYPE_CONTINUOUS, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, true, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ -1, -1, COMPUTER_TAB, false, "Top-Down View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ -1, -1, COMPUTER_TAB, false, "Target Padlock View", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL }, // (Swifty) Toggle for VM_TRACK
// Auto Navigation Systen
{ KEY_ALTED | KEY_A, -1, COMPUTER_TAB, false, "Toggle Auto Pilot", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_N, -1, COMPUTER_TAB, false, "Cycle Nav Points", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_G, -1, SHIP_TAB, false, "Toggle Gliding", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_O, -1, WEAPON_TAB, false, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false },
{ KEY_ALTED | KEY_A, -1, COMPUTER_TAB, false, "Toggle Auto Pilot", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_N, -1, COMPUTER_TAB, false, "Cycle Nav Points", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_ALTED | KEY_G, -1, SHIP_TAB, false, "Toggle Gliding", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ KEY_O, -1, WEAPON_TAB, false, "Cycle Primary Weapon Firing Rate", CC_TYPE_TRIGGER, -1, -1, 0, false, false, NULL },
{ -1, -1, -1, false, "", CC_TYPE_TRIGGER, -1, -1, 0, false, false }
};
@@ -404,6 +404,7 @@ char **Scan_code_text = Scan_code_text_english;
char **Joy_button_text = Joy_button_text_english;
SCP_vector<config_item*> Control_config_presets;
SCP_vector<SCP_string> Control_config_preset_names;
void set_modifier_status()
{
@@ -591,6 +592,9 @@ void control_config_common_init()
for (int i=0; i<CCFG_MAX; i++) {
Control_config[i].disabled = false;
Control_config[i].continuous_ongoing = false;
// init the overridable description with a copy of the default
Control_config[i].text = strdup(Control_config[i].default_text);
}
control_config_common_load_overrides();
@@ -811,6 +815,14 @@ void control_config_common_load_overrides()
std::copy(Control_config, Control_config + CCFG_MAX + 1, cfg_preset);
Control_config_presets.push_back(cfg_preset);
SCP_string preset_name;
if (optional_string("$Name:")) {
stuff_string_line(preset_name);
} else {
preset_name = "<unnamed preset>";
}
Control_config_preset_names.push_back(preset_name);
while (required_string_either("#End","$Bind Name:")) {
const int iBufferLength = 64;
char szTempBuffer[iBufferLength];
@@ -822,7 +834,7 @@ void control_config_common_load_overrides()
for (size_t i = 0; i < cCntrlAryLength; ++i) {
config_item& r_ccConfig = cfg_preset[i];
if (!strcmp(szTempBuffer, r_ccConfig.text)) {
if (!strcmp(szTempBuffer, r_ccConfig.default_text)) {
/**
* short key_default;
* short joy_default;
@@ -833,6 +845,11 @@ void control_config_common_load_overrides()
int iTemp;
if (optional_string("$New Name:")) {
stuff_string(szTempBuffer, F_NAME, iBufferLength);
r_ccConfig.text = strdup(szTempBuffer);
}
if (optional_string("$Key Default:")) {
if (optional_string("NONE")) {
r_ccConfig.key_default = (short)-1;
+4
View File
@@ -926,6 +926,10 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
if (Ship_info[Ships[ship_obj->instance].ship_info_index].collision_lod > -1) {
mc.lod = Ship_info[Ships[ship_obj->instance].ship_info_index].collision_lod;
}
// check each submodel in turn
for (smv = submodel_vector.begin(); smv != submodel_vector.end(); ++smv) {
// turn on submodel for collision test
+4 -4
View File
@@ -1259,7 +1259,7 @@ void game_loading_callback_close()
// Make sure bar shows all the way over.
game_loading_callback(COUNT_ESTIMATE);
int real_count = game_busy_callback( NULL );
int real_count __attribute__((__unused__)) = game_busy_callback( NULL );
Mouse_hidden = 0;
Game_loading_callback_inited = 0;
@@ -1423,7 +1423,7 @@ int game_start_mission()
{
mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
int s1 = timer_get_milliseconds();
int s1 __attribute__((__unused__)) = timer_get_milliseconds();
// clear post processing settings
gr_post_process_set_defaults();
@@ -1480,7 +1480,7 @@ int game_start_mission()
bm_print_bitmaps();
int e1 = timer_get_milliseconds();
int e1 __attribute__((__unused__)) = timer_get_milliseconds();
mprintf(("Level load took %f seconds.\n", (e1 - s1) / 1000.0f ));
@@ -1739,7 +1739,7 @@ char full_path[1024];
*/
void game_init()
{
int s1, e1;
int s1 __attribute__((__unused__)), e1 __attribute__((__unused__));
const char *ptr;
char whee[MAX_PATH_LEN];
+2 -3
View File
@@ -28,15 +28,14 @@
#pragma optimize("", off)
#define DEFAULT_MASTER_EVENT_MUSIC_VOLUME 0.5f
#define HULL_VALUE_TO_PLAY_INTENSE_BATTLE_MUSIC 0.75f
////////////////////////////
// Globals
////////////////////////////
int Event_Music_battle_started = 0;
float Master_event_music_volume = DEFAULT_MASTER_EVENT_MUSIC_VOLUME; // range is 0->1
float Default_music_volume = 0.5f; // range is 0->1
float Master_event_music_volume = Default_music_volume;
typedef struct tagSNDPATTERN {
int default_next_pattern; // Needed so the next_pattern member can be reset
+2 -1
View File
@@ -41,7 +41,8 @@
extern int Event_Music_battle_started; // flag that will tell us if we've started a battle in the current mission
extern int Event_music_enabled;
extern float Master_event_music_volume; // range is 0->1
extern float Default_music_volume; // range is 0->1
extern float Master_event_music_volume; // range is 0->1
/////////////////////////////////////////////////////////////////////////////
+8
View File
@@ -3,7 +3,11 @@
// throw
#ifdef HAVE_CXX11
void * operator new (size_t size)
#else
void * operator new (size_t size) throw (std::bad_alloc)
#endif // CPP11_STD
{
void *p = vm_malloc_q(size);
@@ -19,7 +23,11 @@ void operator delete (void *p) throw()
vm_free(p);
}
#ifdef HAVE_CXX11
void * operator new [] (size_t size)
#else
void * operator new [] (size_t size) throw (std::bad_alloc)
#endif // CPP11_STD
{
void *p = vm_malloc_q(size);
+20
View File
@@ -4,6 +4,25 @@
#include <new>
#ifdef HAVE_CXX11
// throw
extern void * operator new (size_t size);
extern void operator delete (void *p) throw();
extern void * operator new [] (size_t size);
extern void operator delete [] (void *p) throw();
// no-throw
extern void * operator new (size_t size, const std::nothrow_t&) throw();
extern void operator delete (void *p, const std::nothrow_t&) throw();
extern void * operator new [] (size_t size, const std::nothrow_t&) throw();
extern void operator delete [] (void *p, const std::nothrow_t&) throw();
#else
// throw
extern void * operator new (size_t size) throw (std::bad_alloc);
@@ -21,5 +40,6 @@ extern void operator delete (void *p, const std::nothrow_t&) throw();
extern void * operator new [] (size_t size, const std::nothrow_t&) throw();
extern void operator delete [] (void *p, const std::nothrow_t&) throw();
#endif
#endif // _FSMEMORY_H
+109
View File
@@ -22,6 +22,7 @@
#define IAM_64BIT 1
#endif
#include "windows_stub/config.h"
// value to represent an uninitialized state in any int or uint
@@ -680,5 +681,113 @@ public:
#include "globalincs/vmallocator.h"
#include "globalincs/safe_strings.h"
// c++11 standard detection
// for GCC with autotools, see AX_CXX_COMPILE_STDCXX_11 macro in configure.ac
// this sets HAVE_CXX11 & -std=c++0x or -std=c++11 appropriately
// Use the visual studio version to detect C++11 support
#if _MSC_VER >= 1600
# define HAVE_CXX11
#endif
// clang doesn't seem to have a feature check for is_trivial
// oh well, assume it'll be covered by one of the other two checks...
// http://clang.llvm.org/docs/LanguageExtensions.html#feature_check
#if defined(__clang__)
#if __has_feature(cxx_static_assert)
#if __has_feature(cxx_auto_type)
#define HAVE_CXX11
#endif // __has_feature(cxx_auto_type)
#endif // __has_feature(cxx_static_assert)
#endif // defined(__clang__)
// TODO: sort out cmake/gcc
// DEBUG compile time catch for dangerous uses of memset/memcpy/memmove
// would prefer std::is_trivially_copyable but it's not supported by gcc yet
// ref: http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html
#ifndef NDEBUG
#if defined(HAVE_CXX11)
// feature support seems to be: gcc clang msvc
// auto 4.4 2.9 2010
// std::is_trivial 4.5 ? 2012 (2010 only duplicates std::is_pod)
// static_assert 4.3 2.9 2010
#include <type_traits>
#include <cstring>
// MEMSET!
const auto ptr_memset = std::memset;
#define memset memset_if_trivial_else_error
template<typename T>
void *memset_if_trivial_else_error(T *memset_data, int ch, size_t count)
{
static_assert(std::is_trivial<T>::value, "memset on non-trivial object");
return ptr_memset(memset_data, ch, count);
}
// assume memset on a void* is "safe"
// only used in cutscene/mveplayer.cpp:mve_video_createbuf()
inline void *memset_if_trivial_else_error(void *memset_data, int ch, size_t count)
{
return ptr_memset(memset_data, ch, count);
}
// MEMCPY!
const auto ptr_memcpy = std::memcpy;
#define memcpy memcpy_if_trivial_else_error
template<typename T, typename U>
void *memcpy_if_trivial_else_error(T *memcpy_dest, U *src, size_t count)
{
static_assert(std::is_trivial<T>::value, "memcpy on non-trivial object T");
static_assert(std::is_trivial<U>::value, "memcpy on non-trivial object U");
return ptr_memcpy(memcpy_dest, src, count);
}
// assume memcpy with void* is "safe"
// used in:
// globalincs/systemvars.cpp:insertion_sort()
// network/chat_api.cpp:AddChatCommandToQueue()
// network/multi_obj.cpp:multi_oo_sort_func()
// parse/lua.cpp:ade_get_args() && ade_set_args()
//
// probably should setup a static_assert on insertion_sort as well
template<typename U>
void *memcpy_if_trivial_else_error(void *memcpy_dest, U *memcpy_src, size_t count)
{
static_assert(std::is_trivial<U>::value, "memcpy on non-trivial object U");
return ptr_memcpy(memcpy_dest, memcpy_src, count);
}
template<typename T>
void *memcpy_if_trivial_else_error(T *memcpy_dest, void *memcpy_src, size_t count)
{
static_assert(std::is_trivial<T>::value, "memcpy on non-trivial object T");
return ptr_memcpy(memcpy_dest, memcpy_src, count);
}
template<typename T>
void *memcpy_if_trivial_else_error(T *memcpy_dest, const void *memcpy_src, size_t count)
{
static_assert(std::is_trivial<T>::value, "memcpy on non-trivial object T");
return ptr_memcpy(memcpy_dest, memcpy_src, count);
}
inline void *memcpy_if_trivial_else_error(void *memcpy_dest, void *memcpy_src, size_t count)
{
return ptr_memcpy(memcpy_dest, memcpy_src, count);
}
// MEMMOVE!
const auto ptr_memmove = std::memmove;
#define memmove memmove_if_trivial_else_error
template<typename T, typename U>
void *memmove_if_trivial_else_error(T *memmove_dest, U *memmove_src, size_t count)
{
static_assert(std::is_trivial<T>::value, "memmove on non-trivial object T");
static_assert(std::is_trivial<U>::value, "memmove on non-trivial object U");
return ptr_memmove(memmove_dest, memmove_src, count);
}
#endif // HAVE_CXX11
#endif // NDEBUG
#endif // PS_TYPES_H
+3 -2
View File
@@ -33,6 +33,7 @@
#include "io/keycontrol.h" // m!m
#include "debugconsole/console.h"
#include "debugconsole/console.h"
#include "popup/popup.h"
#if defined(SCP_UNIX) && !defined(__APPLE__)
@@ -83,7 +84,7 @@ int gr_alpha_test = 0;
// Default clipping distances
const float Default_min_draw_distance = 1.0f;
const float Default_max_draw_distance = 1e10;
const float Default_max_draw_distance = 10000000.0f;
float Min_draw_distance = Default_min_draw_distance;
float Max_draw_distance = Default_max_draw_distance;
@@ -1771,7 +1772,7 @@ void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float a
void gr_flip()
{
// m!m avoid running CHA_ONFRAME when the "Quit mission" popup is shown. See mantis 2446 for reference
if (!quit_mission_popup_shown)
if (!quit_mission_popup_shown && !popup_active())
{
//WMC - Evaluate global hook if not override.
Script_system.RunBytecode(Script_globalhook);
+7 -1
View File
@@ -220,13 +220,19 @@ int generic_anim_stream(generic_anim *ga)
ga->previous_frame = -1;
}
else {
bool in_subdir;
bpp = 32;
if(ga->use_hud_color)
bpp = 8;
bm_load_and_parse_eff(ga->filename, CF_TYPE_ANY, &ga->num_frames, &anim_fps, &ga->keyframe, 0);
bm_load_and_parse_eff(ga->filename, CF_TYPE_ANY, &ga->num_frames, &anim_fps, &ga->keyframe, 0, &in_subdir);
char *p = strrchr( ga->filename, '.' );
if ( p )
*p = 0;
if (in_subdir) {
set_temp_subdir_pathtype(ga->filename);
}
char frame_name[32];
snprintf(frame_name, 32, "%s_0000", ga->filename);
ga->bitmap_id = bm_load(frame_name);
+1 -1
View File
@@ -1090,7 +1090,7 @@ bool HudGauge::canRender()
}
if (gauge_config == HUD_ETS_GAUGE) {
if (Ships[Player_obj->instance].flags2 & SF2_NO_ETS) {
if (Ships[Player_obj->instance].flags2 & SF2_NO_ETS && !Show_disabled_ets_gauges) {
return false;
}
}
+4
View File
@@ -420,6 +420,10 @@ int hud_abort_lock()
return 1;
}
if ( Player_ship->flags2 & SF2_NO_SECONDARY_LOCKON ) {
return 1;
}
// if we're on the same team and the team doesn't attack itself, then don't lock!
if ((Player_ship->team == target_team) && (!iff_x_attacks_y(Player_ship->team, target_team)))
{
+10
View File
@@ -46,6 +46,7 @@ int Hud_reticle_style = HUD_RETICLE_STYLE_FS2;
bool Hud_retail = true;
bool Scale_retail_gauges = true;
bool Show_disabled_ets_gauges = false;
int Hud_font = -1;
@@ -259,6 +260,10 @@ void parse_hud_gauges_tbl(const char *filename)
Hud_reticle_style = temp;
}
if (optional_string("$Show disabled ETS gauges:")) {
stuff_boolean(&Show_disabled_ets_gauges);
}
int base_res[2];
int ship_idx = -1;
int ship_font = -1;
@@ -2017,6 +2022,7 @@ void load_gauge_center_reticle(int base_w, int base_h, int hud_font, bool scale_
int scaleX = 15;
int scaleY = 10;
int size = 5;
int autoaim_frame = -1;
if(Hud_reticle_style == HUD_RETICLE_STYLE_FS1) {
if(gr_screen.res == GR_640) {
@@ -2066,8 +2072,12 @@ void load_gauge_center_reticle(int base_w, int base_h, int hud_font, bool scale_
if (optional_string("Firepoint Y coordinate multiplier:"))
stuff_int(&scaleY);
if(optional_string("Autoaim Frame:"))
stuff_int(&autoaim_frame);
hud_gauge->initBitmaps(fname);
hud_gauge->initFirepointDisplay(firepoints, scaleX, scaleY, size);
hud_gauge->setAutoaimFrame(autoaim_frame);
if(ship_idx->at(0) >= 0) {
for (SCP_vector<int>::iterator ship_index = ship_idx->begin(); ship_index != ship_idx->end(); ++ship_index) {
+1
View File
@@ -20,6 +20,7 @@ extern float Hud_speed_multiplier;
#define HUD_RETICLE_STYLE_FS2 1
extern int Hud_reticle_style;
extern bool Show_disabled_ets_gauges;
//Functions
int hud_get_gauge_index(char* name);
+66 -12
View File
@@ -20,6 +20,7 @@
#include "weapon/emp.h"
#include "localization/localize.h"
#include "network/multi.h"
#include "weapon/weapon.h"
#define NUM_RETICLE_ANIS 11 // keep up to date when modifying the number of reticle ani files
@@ -228,6 +229,7 @@ static int Threat_lock_frame; // frame offset of current lock flashing warnin
HudGaugeReticle::HudGaugeReticle():
HudGauge(HUD_OBJECT_CENTER_RETICLE, HUD_CENTER_RETICLE, true, false, (VM_EXTERNAL | VM_DEAD_VIEW | VM_WARP_CHASE | VM_PADLOCK_ANY | VM_TOPDOWN | VM_OTHER_SHIP), 255, 255, 255)
{
has_autoaim_lock = false;
}
void HudGaugeReticle::initBitmaps(char *fname)
@@ -247,9 +249,39 @@ void HudGaugeReticle::initFirepointDisplay(bool firepoint, int scaleX, int scale
void HudGaugeReticle::render(float frametime)
{
ship_info *sip = &Ship_info[Player_ship->ship_info_index];
if (autoaim_frame_offset > 0 || sip->autoaim_lock_snd > -1 || sip->autoaim_lost_snd > -1) {
ship *shipp = &Ships[Objects[Player->objnum].instance];
ship_weapon *swp = &shipp->weapons;
ai_info *aip = &Ai_info[shipp->ai_index];
if (aip->target_objnum != -1) {
bool autoaiming = false;
autoaiming = in_autoaim_fov(shipp, swp->current_primary_bank, &Objects[aip->target_objnum]);
if (autoaiming) {
if (!has_autoaim_lock && sip->autoaim_lock_snd > -1) {
snd_play( &Snds[sip->autoaim_lock_snd]);
}
has_autoaim_lock = true;
}
else {
if (has_autoaim_lock && sip->autoaim_lost_snd > -1) {
snd_play( &Snds[sip->autoaim_lost_snd]);
}
has_autoaim_lock = false;
}
}
}
setGaugeColor(HUD_C_BRIGHT);
renderBitmap(crosshair.first_frame, position[0], position[1]);
if (has_autoaim_lock)
renderBitmap(crosshair.first_frame + autoaim_frame_offset, position[0], position[1]);
else
renderBitmap(crosshair.first_frame, position[0], position[1]);
if (firepoint_display) {
fp.clear();
@@ -277,7 +309,7 @@ void HudGaugeReticle::render(float frametime)
void HudGaugeReticle::getFirepointStatus() {
//First, get the player ship
ship_info* pship;
ship_info* sip;
ship* shipp;
polymodel* pm;
@@ -285,30 +317,45 @@ void HudGaugeReticle::getFirepointStatus() {
if (Objects[Player->objnum].type == OBJ_SHIP) {
shipp = &Ships[Objects[Player->objnum].instance];
pship = &Ship_info[shipp->ship_info_index];
sip = &Ship_info[shipp->ship_info_index];
//Get the player eyepoint
pm = model_get(pship->model_num);
pm = model_get(sip->model_num);
if (pm->n_view_positions == 0) {
mprintf(("Model %s does not have a defined eyepoint. Firepoint display could not be generated\n", pm->filename));
} else {
if (pm->n_guns > 0) {
if (pm->n_guns > 0) {
eye eyepoint = pm->view_positions[shipp->current_viewpoint];
vec2d ep = { eyepoint.pnt.xyz.x, eyepoint.pnt.xyz.y };
for (int i = 0; i < pm->n_guns; i++) {
int isactive = 0;
int bankactive = 0;
ship_weapon *swp = &shipp->weapons;
if (!timestamp_elapsed(shipp->weapons.next_primary_fire_stamp[i]))
isactive = 1;
bankactive = 1;
else if (timestamp_elapsed(shipp->weapons.primary_animation_done_time[i]))
isactive = 1;
bankactive = 1;
else if (i == shipp->weapons.current_primary_bank || shipp->flags & SF_PRIMARY_LINKED)
isactive = 2;
bankactive = 2;
int num_slots = pm->gun_banks[i].num_slots;
for (int j = 0; j < num_slots; j++) {
int fpactive = bankactive;
if (sip->flags2 & SIF2_DYN_PRIMARY_LINKING) {
// If this firepoint is not among the next shot(s) to be fired, dim it one step
if ( !( (j >= (shipp->last_fired_point[i]+1) % num_slots) && (j <= (shipp->last_fired_point[i]+swp->primary_bank_slot_count[i]) % num_slots) ) ) {
fpactive--;
}
} else if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CYCLE) {
// If this firepoint is not the next one to be fired, dim it one step
if (j != (shipp->last_fired_point[i]+1) % num_slots) {
fpactive--;
}
}
for (int j = 0; j < pm->gun_banks[i].num_slots; j++) {
vec3d fpfromeye;
matrix eye_orient, player_transpose;
@@ -317,7 +364,7 @@ void HudGaugeReticle::getFirepointStatus() {
vm_matrix_x_matrix(&eye_orient, &player_transpose, &Eye_matrix);
vm_vec_rotate(&fpfromeye, &pm->gun_banks[i].pnt[j], &eye_orient);
firepoint tmp = { { fpfromeye.xyz.x - ep.x, ep.y - fpfromeye.xyz.y }, isactive };
firepoint tmp = { { fpfromeye.xyz.x - ep.x, ep.y - fpfromeye.xyz.y }, fpactive };
fp.push_back(tmp);
}
}
@@ -326,6 +373,13 @@ void HudGaugeReticle::getFirepointStatus() {
}
}
void HudGaugeReticle::setAutoaimFrame(int framenum) {
if (framenum < 0 || framenum > crosshair.num_frames - 1)
autoaim_frame_offset = 0;
else
autoaim_frame_offset = framenum;
}
void HudGaugeReticle::pageIn()
{
bm_page_in_aabitmap( crosshair.first_frame, crosshair.num_frames);
+3
View File
@@ -43,6 +43,8 @@ protected:
int firepoint_size;
int firepoint_scale_x;
int firepoint_scale_y;
int autoaim_frame_offset;
bool has_autoaim_lock;
public:
HudGaugeReticle();
void render(float frametime);
@@ -50,6 +52,7 @@ public:
void pageIn();
void initFirepointDisplay(bool firepoint, int scaleX, int scaleY, int size);
void getFirepointStatus();
void setAutoaimFrame(int framenum);
};
class HudGaugeThrottle: public HudGauge
+9
View File
@@ -545,6 +545,11 @@ void hud_shield_quadrant_hit(object *objp, int quadrant)
shield_hit_info *shi;
int num;
if (Game_mode & GM_STANDALONE_SERVER)
return;
Assertion(objp != NULL, "hud_shield_quadrant_hit() called with a NULL objp; get a coder!\n");
if ( objp->type != OBJ_SHIP )
return;
@@ -559,12 +564,16 @@ void hud_shield_quadrant_hit(object *objp, int quadrant)
return;
}
Assertion(shi->shield_hit_timers.size() > 0, "Shield hit info object for object '%s' has a size %d shield_hit_timers; get a coder!\n", Ships[objp->instance].ship_name, shi->shield_hit_timers.size());
Assertion(shi->hull_hit_index < shi->shield_hit_timers.size(), "Shield hit info object for object '%s' has a hull_hit_index of %d (should be between 0 and %d); get a coder!\n", Ships[objp->instance].ship_name, shi->hull_hit_index, shi->shield_hit_timers.size() - 1);
if ( quadrant >= 0 ) {
if ( !(Ship_info[Ships[objp->instance].ship_info_index].flags2 & SIF2_MODEL_POINT_SHIELDS) )
num = Quadrant_xlate[quadrant];
else
num = quadrant;
Assertion(num < shi->hull_hit_index, "Shield hit info object for object '%s' hit on quadrant #%d, despite having a hull_hit_index of %d; get a coder!\n", Ships[objp->instance].ship_name, num, shi->hull_hit_index);
shi->shield_hit_timers[num] = timestamp(SHIELD_HIT_DURATION_SHORT);
} else {
shi->shield_hit_timers[shi->hull_hit_index] = timestamp(SHIELD_HIT_DURATION_SHORT);
+4 -5
View File
@@ -1373,11 +1373,10 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message,
target_shipname = NULL;
target_team = -1;
if ( ainfo->target_objnum != -1) {
if ( Objects[ainfo->target_objnum].type == OBJ_SHIP ) {
target_shipname = Ships[Objects[ainfo->target_objnum].instance].ship_name; // I think this is right
target_team = Ships[Objects[ainfo->target_objnum].instance].team;
}
if ( Objects[ainfo->target_objnum].type == OBJ_SHIP ) {
target_shipname = Ships[Objects[ainfo->target_objnum].instance].ship_name; // I think this is right
target_team = Ships[Objects[ainfo->target_objnum].instance].team;
}
Assert ( ainfo->shipnum != -1 );
+1 -1
View File
@@ -1095,7 +1095,7 @@ void hud_target_subobject_common(int next_flag)
target_shipp = &Ships[Objects[Player_ai->target_objnum].instance];
if (!Player_ai->targeted_subsys) {
start = GET_FIRST(&target_shipp->subsys_list);
start = END_OF_LIST(&target_shipp->subsys_list);
} else {
start = Player_ai->targeted_subsys;
}
+11 -1
View File
@@ -41,6 +41,7 @@
#define LAB_FLAG_FULLY_LOAD (1<<5) // use create_ship() to test the ships
#define LAB_FLAG_SHOW_WEAPONS (1<<6) // determines if external weapons models are displayed
#define LAB_FLAG_INITIAL_ROTATION (1<<7) // initial rotation setting
#define LAB_FLAG_DESTROYED_SUBSYSTEMS (1<<8) // render model as if all subsystems are destroyed
// modes
#define LAB_MODE_NONE 0 // not showing anything
@@ -684,7 +685,7 @@ void labviewer_add_model_thrusters(ship_info *sip)
mst.distortion_bitmap = thruster_distortion_bitmap;
mst.use_ab = Lab_thrust_afterburn;
mst.glow_noise = thruster_glow_noise;
mst.glow_noise = thruster_glow_noise * sip->thruster_glow_noise_mult;
mst.rotvel = &vmd_zero_vector;
if (Lab_mode == LAB_MODE_SHIP) {
@@ -904,6 +905,13 @@ void labviewer_render_model(float frametime)
}
}
}
if (sip != NULL) {
if (Lab_viewer_flags & LAB_FLAG_DESTROYED_SUBSYSTEMS) {
model_show_damaged(Lab_model_num, 1);
}
}
opengl_shader_set_animated_effect(ANIMATED_SHADER_LOADOUTSELECT_FS1);
opengl_shader_set_animated_timer(MIN((timer_get_milliseconds()-anim_timer_start)/1500.0f,2.0f));
@@ -1855,6 +1863,7 @@ void labviewer_make_render_options_window(Button *caller)
ADD_RENDER_FLAG("Animated Shader", Lab_model_flags, MR_ANIMATED_SHADER);
ADD_RENDER_FLAG("Show Ship Weapons", Lab_viewer_flags, LAB_FLAG_SHOW_WEAPONS);
ADD_RENDER_FLAG("Initial Rotation", Lab_viewer_flags, LAB_FLAG_INITIAL_ROTATION);
ADD_RENDER_FLAG("Show Destroyed Subsystems", Lab_viewer_flags, LAB_FLAG_DESTROYED_SUBSYSTEMS);
// start tree
@@ -2234,6 +2243,7 @@ void labviewer_make_weap_window(Button* caller)
delete type_nodes[i];
}
}
delete[] type_nodes;
Lab_mode = LAB_MODE_WEAPON;
+2
View File
@@ -159,6 +159,8 @@ void GUISystem::ParseClassInfo(char* filename)
flag = sciep->Parse();
if (flag) {
list_append(&ScreenClassInfo, sciep);
} else {
delete sciep;
}
} while (flag);
+17 -14
View File
@@ -1534,6 +1534,9 @@ void message_queue_process()
// Don't play death scream unless a small ship.
if ( q->builtin_type == MESSAGE_WINGMAN_SCREAM ) {
if (Message_shipnum < 0) {
goto all_done;
}
if (!((Ship_info[Ships[Message_shipnum].ship_info_index].flags & SIF_SMALL_SHIP) || (Ships[Message_shipnum].flags2 & SF2_ALWAYS_DEATH_SCREAM)) ) {
goto all_done;
}
@@ -1917,7 +1920,7 @@ void message_send_builtin_to_player( int type, ship *shipp, int priority, int ti
char *who_from;
int best_match = -1;
matching_builtin *current_builtin = new matching_builtin();
matching_builtin current_builtin;
SCP_vector <matching_builtin> matching_builtins;
@@ -1979,52 +1982,52 @@ void message_send_builtin_to_player( int type, ship *shipp, int priority, int ti
// check the type of message
if ( !stricmp(Messages[i].name, name) ) {
// condition 1: we have a type match
current_builtin->message_index = i;
current_builtin->type_of_match = BUILTIN_MATCHES_TYPE;
current_builtin.message_index = i;
current_builtin.type_of_match = BUILTIN_MATCHES_TYPE;
// check the species of this persona (if required)
if ( (persona_species >= 0) && (Personas[Messages[i].persona_index].species == persona_species) ) {
// condition 2: we have a type + species match
current_builtin->type_of_match = BUILTIN_MATCHES_SPECIES;
current_builtin.type_of_match = BUILTIN_MATCHES_SPECIES;
}
// check the exact persona (if required)
// NOTE: doesn't need to be nested under the species condition above
if ( (persona_index >= 0) && (Messages[i].persona_index == persona_index) ) {
// condition 3: type + species + persona index match
current_builtin->type_of_match = BUILTIN_MATCHES_PERSONA_CHECK_MOOD;
current_builtin.type_of_match = BUILTIN_MATCHES_PERSONA_CHECK_MOOD;
}
// check if the personas mood suits this particular message, first check if it is excluded
if (!Messages[i].excluded_moods.empty() && (current_builtin->type_of_match == BUILTIN_MATCHES_PERSONA_CHECK_MOOD)) {
if (!Messages[i].excluded_moods.empty() && (current_builtin.type_of_match == BUILTIN_MATCHES_PERSONA_CHECK_MOOD)) {
for (SCP_vector<int>::iterator iter = Messages[i].excluded_moods.begin(); iter != Messages[i].excluded_moods.end(); ++iter) {
if (*iter == Current_mission_mood) {
current_builtin->type_of_match = BUILTIN_MATCHES_PERSONA_EXCLUDED;
current_builtin.type_of_match = BUILTIN_MATCHES_PERSONA_EXCLUDED;
break;
}
}
}
if (current_builtin->type_of_match == BUILTIN_MATCHES_PERSONA_CHECK_MOOD) {
if (current_builtin.type_of_match == BUILTIN_MATCHES_PERSONA_CHECK_MOOD) {
if (Current_mission_mood == Messages[i].mood) {
current_builtin->type_of_match = BUILTIN_MATCHES_PERSONA_MOOD;
current_builtin.type_of_match = BUILTIN_MATCHES_PERSONA_MOOD;
}
else {
current_builtin->type_of_match = BUILTIN_MATCHES_PERSONA;
current_builtin.type_of_match = BUILTIN_MATCHES_PERSONA;
}
}
if (current_builtin->type_of_match == best_match) {
if (current_builtin.type_of_match == best_match) {
num_matching_builtins++;
}
// otherwise check to see if the this is the best kind of match we've found so far
else if (current_builtin->type_of_match > best_match) {
best_match = current_builtin->type_of_match;
else if (current_builtin.type_of_match > best_match) {
best_match = current_builtin.type_of_match;
num_matching_builtins = 1;
}
// add the match to our list
matching_builtins.push_back(*current_builtin);
matching_builtins.push_back(current_builtin);
}
}
+31 -34
View File
@@ -1838,6 +1838,7 @@ int parse_create_object_sub(p_object *p_objp)
shipp->ship_max_shield_strength = p_objp->ship_max_shield_strength;
shipp->ship_max_hull_strength = p_objp->ship_max_hull_strength;
shipp->max_shield_recharge = p_objp->max_shield_recharge;
// Goober5000 - ugh, this is really stupid having to do this here; if the
// ship creation code was better organized this wouldn't be necessary
@@ -2250,7 +2251,7 @@ int parse_create_object_sub(p_object *p_objp)
Objects[objnum].hull_strength = p_objp->initial_hull * shipp->ship_max_hull_strength / 100.0f;
for (iLoop = 0; iLoop<Objects[objnum].n_quadrants; iLoop++)
{
Objects[objnum].shield_quadrant[iLoop] = (float) (p_objp->initial_shields * get_max_shield_quad(&Objects[objnum]) / 100.0f);
Objects[objnum].shield_quadrant[iLoop] = (float) (shipp->max_shield_recharge * p_objp->initial_shields * get_max_shield_quad(&Objects[objnum]) / 100.0f);
}
// initial velocities now do not apply to ships which warp in after mission starts
@@ -3110,6 +3111,7 @@ int parse_object(mission *pm, int flag, p_object *p_objp)
}
Assert(p_objp->ship_max_hull_strength > 0.0f); // Goober5000: div-0 check (not shield because we might not have one)
p_objp->max_shield_recharge = Ship_info[p_objp->ship_class].max_shield_recharge;
// if the kamikaze flag is set, we should have the next flag
@@ -4603,8 +4605,9 @@ void resolve_path_masks(int anchor, int *path_mask)
Assert(!(anchor & SPECIAL_ARRIVAL_ANCHOR_FLAG));
parent_pobjp = mission_parse_get_parse_object(Parse_names[anchor]);
// load model for checking paths
modelnum = model_load(Ship_info[parent_pobjp->ship_class].pof_file, 0, NULL);
// Load the anchor ship model with subsystems and all; it'll need to be done for this mission anyway
ship_info *sip = &Ship_info[parent_pobjp->ship_class];
modelnum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
// resolve names to indexes
*path_mask = 0;
@@ -4617,9 +4620,6 @@ void resolve_path_masks(int anchor, int *path_mask)
*path_mask |= (1 << bay_path);
}
// unload model
model_unload(modelnum);
// cache the result
prp->cached_mask = *path_mask;
}
@@ -5832,42 +5832,38 @@ int get_mission_info(const char *filename, mission *mission_p, bool basic)
if (p) *p = 0; // remove any extension
strcat_s(real_fname, FS_MISSION_FILE_EXT); // append mission extension
int rval, filelength;
int filelength;
// if mission_p is NULL, make it point to The_mission
if ( mission_p == NULL )
mission_p = &The_mission;
do {
CFILE *ftemp = cfopen(real_fname, "rt");
if (!ftemp) {
rval = -1;
break;
}
CFILE *ftemp = cfopen(real_fname, "rt");
if (!ftemp) {
return -1;
}
// 7/9/98 -- MWA -- check for 0 length file.
filelength = cfilelength(ftemp);
cfclose(ftemp);
if (filelength == 0) {
rval = -1;
break;
}
// 7/9/98 -- MWA -- check for 0 length file.
filelength = cfilelength(ftemp);
cfclose(ftemp);
if (filelength == 0) {
return -1;
}
try
{
read_file_text(real_fname, CF_TYPE_MISSIONS);
mission_p->Reset();
parse_init(basic);
parse_mission_info(mission_p, basic);
}
catch (const parse::ParseException& e)
{
mprintf(("MISSIONS: Unable to parse '%s'! Error message = %s.\n", real_fname, e.what()));
break;
}
} while (0);
try
{
read_file_text(real_fname, CF_TYPE_MISSIONS);
mission_p->Reset();
parse_init(basic);
parse_mission_info(mission_p, basic);
}
catch (const parse::ParseException& e)
{
mprintf(("MISSIONS: Unable to parse '%s'! Error message = %s.\n", real_fname, e.what()));
return -1;
}
return rval;
return 0;
}
/**
@@ -7566,6 +7562,7 @@ void mission_bring_in_support_ship( object *requester_objp )
// set support ship hitpoints
pobj->ship_max_hull_strength = Ship_info[i].max_hull_strength;
pobj->ship_max_shield_strength = Ship_info[i].max_shield_strength;
pobj->max_shield_recharge = Ship_info[i].max_shield_recharge;
pobj->team = requester_shipp->team;
+2
View File
@@ -424,6 +424,8 @@ public:
float ship_max_hull_strength; // Needed to deal with special hitpoints
float ship_max_shield_strength;
float max_shield_recharge;
// Goober5000
SCP_vector<texture_replace> replacement_textures;
+5
View File
@@ -1513,6 +1513,11 @@ void draw_model_icon(int model_id, int flags, float closeup_zoom, int x, int y,
//Assume it's a weapon
rot_angles.h = -(PI_2);
}
else if(sip->model_icon_angles.p != 0.0f || sip->model_icon_angles.b != 0.0f || sip->model_icon_angles.h != 0.0f)
{
// If non-zero model_icon_angles exists, always use that
rot_angles = sip->model_icon_angles;
}
else if(sip->flags & SIF_SMALL_SHIP)
{
rot_angles.p = -(PI_2);
+2 -1
View File
@@ -1022,7 +1022,8 @@ typedef struct mc_info {
vec3d *p0; // The starting point of the ray (sphere) to check
vec3d *p1; // The ending point of the ray (sphere) to check
int flags; // Flags that the model_collide code looks at. See MC_??? defines
float radius; // If MC_CHECK_THICK is set, checks a sphere moving with the radius.
float radius; // If MC_CHECK_THICK is set, checks a sphere moving with the radius.
int lod; // Which detail level of the submodel to check instead
// Return values
int num_hits; // How many collisions were found
+16 -1
View File
@@ -1130,7 +1130,22 @@ void mc_check_subobj( int mn )
if ( Cmdline_old_collision_sys ) {
model_collide_sub(sm->bsp_data);
} else {
model_collide_bsp(model_get_bsp_collision_tree(sm->collision_tree_index), 0);
if (Mc->lod > 0 && sm->num_details > 0) {
bsp_info *lod_sm = sm;
for (int i = Mc->lod - 1; i >= 0; i--) {
if (sm->details[i] != -1) {
lod_sm = &Mc_pm->submodel[sm->details[i]];
//mprintf(("Checking %s collision for %s using %s instead\n", Mc_pm->filename, sm->name, lod_sm->name));
break;
}
}
model_collide_bsp(model_get_bsp_collision_tree(lod_sm->collision_tree_index), 0);
} else {
model_collide_bsp(model_get_bsp_collision_tree(sm->collision_tree_index), 0);
}
}
}
}
+51 -31
View File
@@ -83,7 +83,6 @@ static float Interp_box_scale = 1.0f; // this is used to scale both detail boxes
static vec3d Interp_render_box_min = ZERO_VECTOR;
static vec3d Interp_render_box_max = ZERO_VECTOR;
static float Interp_render_sphere_radius = 0.0f;
static vec3d Interp_render_sphere_offset = ZERO_VECTOR;
// -------------------------------------------------------------------
// lighting save stuff
@@ -369,7 +368,6 @@ void interp_clear_instance()
Interp_render_box_min = vmd_zero_vector;
Interp_render_box_max = vmd_zero_vector;
Interp_render_sphere_radius = 0.0f;
Interp_render_sphere_offset = vmd_zero_vector;
}
/**
@@ -2728,6 +2726,7 @@ void model_really_render(int model_num, matrix *orient, vec3d * pos, uint flags,
uint save_gr_zbuffering_mode;
int zbuf_mode;
ship *shipp = NULL;
ship_info *sip = NULL;
object *objp = NULL;
bool set_autocen = false;
bool draw_thrusters = false;
@@ -2742,6 +2741,7 @@ void model_really_render(int model_num, matrix *orient, vec3d * pos, uint flags,
if (objp->type == OBJ_SHIP) {
shipp = &Ships[objp->instance];
sip = &Ship_info[shipp->ship_info_index];
if (shipp->flags2 & SF2_GLOWMAPS_DISABLED)
flags |= MR_NO_GLOWMAPS;
@@ -2905,33 +2905,37 @@ void model_really_render(int model_num, matrix *orient, vec3d * pos, uint flags,
}
#endif
// scale the render box settings based on the "Model Detail" slider
switch (Detail.detail_distance)
{
// 1st dot is 20%
case 0:
Interp_box_scale = 0.2f;
break;
if (shipp != NULL && (sip->flags2 & SIF2_LOCK_DETAIL_BOXES)) {
Interp_box_scale = 1.0f;
} else {
// scale the render box settings based on the "Model Detail" slider
switch (Detail.detail_distance)
{
// 1st dot is 20%
case 0:
Interp_box_scale = 0.2f;
break;
// 2nd dot is 50%
case 1:
Interp_box_scale = 0.5f;
break;
// 2nd dot is 50%
case 1:
Interp_box_scale = 0.5f;
break;
// 3rd dot is 80%
case 2:
Interp_box_scale = 0.8f;
break;
// 3rd dot is 80%
case 2:
Interp_box_scale = 0.8f;
break;
// 4th dot is 100% (this is the default setting for "High" and "Very High" settings)
case 3:
Interp_box_scale = 1.0f;
break;
// 4th dot is 100% (this is the default setting for "High" and "Very High" settings)
case 3:
Interp_box_scale = 1.0f;
break;
// 5th dot (max) is 120%
case 4:
Interp_box_scale = 1.2f;
break;
// 5th dot (max) is 120%
case 4:
Interp_box_scale = 1.2f;
break;
}
}
vec3d auto_back = ZERO_VECTOR;
@@ -4468,7 +4472,13 @@ void model_render_children_buffers(polymodel *pm, int mn, int detail_level)
vm_vec_copy_scale(&Interp_render_box_min, &model->render_box_min, Interp_box_scale);
vm_vec_copy_scale(&Interp_render_box_max, &model->render_box_max, Interp_box_scale);
if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &model->offset)) )
vec3d offset;
if (model->use_render_box_offset)
offset = model->render_box_offset;
else
model_find_submodel_offset(&offset, pm->id, mn);
if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &offset)) )
return;
}
if ( !(Interp_flags & MR_FULL_DETAIL) && model->use_render_sphere ) {
@@ -4476,8 +4486,10 @@ void model_render_children_buffers(polymodel *pm, int mn, int detail_level)
// TODO: doesn't consider submodel rotations yet -zookeeper
vec3d offset;
model_find_submodel_offset(&offset, pm->id, mn);
vm_vec_add2(&offset, &model->render_sphere_offset);
if (model->use_render_sphere_offset)
offset = model->render_sphere_offset;
else
model_find_submodel_offset(&offset, pm->id, mn);
if ( (-model->use_render_sphere + in_sphere(&offset, Interp_render_sphere_radius)) )
return;
@@ -4591,7 +4603,13 @@ void model_render_buffers(polymodel *pm, int mn, bool is_child)
vm_vec_copy_scale(&Interp_render_box_min, &model->render_box_min, Interp_box_scale);
vm_vec_copy_scale(&Interp_render_box_max, &model->render_box_max, Interp_box_scale);
if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &model->offset)) )
vec3d offset;
if (model->use_render_box_offset)
offset = model->render_box_offset;
else
model_find_submodel_offset(&offset, pm->id, mn);
if ( (-model->use_render_box + in_box(&Interp_render_box_min, &Interp_render_box_max, &offset)) )
return;
}
if ( !is_child && !(Interp_flags & MR_FULL_DETAIL) && model->use_render_sphere ) {
@@ -4599,8 +4617,10 @@ void model_render_buffers(polymodel *pm, int mn, bool is_child)
// TODO: doesn't consider submodel rotations yet -zookeeper
vec3d offset;
model_find_submodel_offset(&offset, pm->id, mn);
vm_vec_add2(&offset, &model->render_sphere_offset);
if (model->use_render_sphere_offset)
offset = model->render_sphere_offset;
else
model_find_submodel_offset(&offset, pm->id, mn);
if ( (-model->use_render_sphere + in_sphere(&offset, Interp_render_sphere_radius)) )
return;
+25 -4
View File
@@ -1354,6 +1354,18 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
while (*p == ' ') p++;
pm->submodel[n].use_render_box = atoi(p);
if ( (p = strstr(props, "$box_offset:")) != NULL ) {
p += 12;
while (*p == ' ') p++;
pm->submodel[n].render_box_offset.xyz.x = (float)strtod(p, (char **)NULL);
while (*p != ',') p++;
pm->submodel[n].render_box_offset.xyz.y = (float)strtod(++p, (char **)NULL);
while (*p != ',') p++;
pm->submodel[n].render_box_offset.xyz.z = (float)strtod(++p, (char **)NULL);
pm->submodel[n].use_render_box_offset = true;
}
if ( (p = strstr(props, "$box_min:")) != NULL ) {
p += 9;
while (*p == ' ') p++;
@@ -1400,6 +1412,8 @@ int read_model_file(polymodel * pm, char *filename, int n_subsystems, model_subs
pm->submodel[n].render_sphere_offset.xyz.y = (float)strtod(++p, (char **)NULL);
while (*p != ',') p++;
pm->submodel[n].render_sphere_offset.xyz.z = (float)strtod(++p, (char **)NULL);
pm->submodel[n].use_render_sphere_offset = true;
} else {
pm->submodel[n].render_sphere_offset = vmd_zero_vector;
}
@@ -2639,6 +2653,12 @@ int model_load(char *filename, int n_subsystems, model_subsystem *subsystems, in
}
dl2 = tolower(sm2->name[first_diff]) - 'a';
// Handle LODs named "detail0/1/2/etc" too (as opposed to "detaila/b/c/etc")
if (sm1->parent == -1 && sm2->parent == -1 && !sm1->is_damaged && !sm2->is_damaged && !sm1->is_live_debris && !sm2->is_live_debris) {
dl2 = dl2 - dl1;
dl1 = 0;
}
if ( (dl1<0) || (dl2<0) || (dl1>=MAX_MODEL_DETAIL_LEVELS) || (dl2>=MAX_MODEL_DETAIL_LEVELS) ) continue; // invalid detail levels
if ( dl1 == 0 ) {
@@ -2663,10 +2683,11 @@ int model_load(char *filename, int n_subsystems, model_subsystem *subsystems, in
if ( !Cmdline_old_collision_sys ) {
for ( i = 0; i < pm->n_models; ++i ) {
pm->submodel[i].collision_tree_index = model_create_bsp_collision_tree();
bsp_collision_tree *tree = model_get_bsp_collision_tree(pm->submodel[i].collision_tree_index);
model_collide_parse_bsp(tree, pm->submodel[i].bsp_data, pm->version);
if ( !(pm->submodel[i].nocollide_this_only || pm->submodel[i].no_collisions) ) {
pm->submodel[i].collision_tree_index = model_create_bsp_collision_tree();
bsp_collision_tree *tree = model_get_bsp_collision_tree(pm->submodel[i].collision_tree_index);
model_collide_parse_bsp(tree, pm->submodel[i].bsp_data, pm->version);
}
}
}
+5
View File
@@ -585,6 +585,11 @@ void multi_options_process_packet(unsigned char *data, header *hinfo)
// find out who is sending this data
player_index = find_player_id(hinfo->id);
if (player_index < 0) {
nprintf(("Network", "Received packet from unknown player!\n"));
return;
}
// get the packet code
GET_DATA(code);
switch(code){
+2 -1
View File
@@ -4511,7 +4511,8 @@ void multi_pxo_pinfo_build_vals()
if (fs->stats.last_flown == 0) {
strcpy_s(Multi_pxo_pinfo_vals[7], XSTR("No missions flown", 970) );
} else {
tm *tmr = gmtime( (time_t*)&fs->stats.last_flown );
time_t tmp_lf = fs->stats.last_flown; // don't cast a pointer to a type that can be either 32 or 64bit
tm *tmr = gmtime( &tmp_lf );
if (tmr != NULL)
strftime(Multi_pxo_pinfo_vals[7], 30, "%m/%d/%y %H:%M", tmr);
+6
View File
@@ -1599,6 +1599,12 @@ void multi_create_standalone_object()
vm_vec_zero(&v);
objnum = observer_create(&m,&v);
if (objnum < 0) {
Error(LOCATION, "Failed to create standalone observer object! Please investigate!");
return;
}
Player_obj = &Objects[objnum];
obj_set_flags(Player_obj, Player_obj->flags & (~OF_COLLIDES) );
//obj_set_flags(Player_obj, Player_obj->flags | OF_SHOULD_BE_DEAD);
+4
View File
@@ -269,6 +269,10 @@ int ship_ship_check_collision(collision_info_struct *ship_ship_hit_info, vec3d *
// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
if (heavy_sip->collision_lod > -1) {
mc.lod = heavy_sip->collision_lod;
}
// check each submodel in turn
for (smv = submodel_vector.begin(); smv != submodel_vector.end(); ++smv) {
// turn on submodel for collision test
+15 -9
View File
@@ -168,6 +168,7 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti
mc.pos = &ship_objp->pos;
mc.p0 = &weapon_objp->last_pos;
mc.p1 = &weapon_end_pos;
mc.lod = sip->collision_lod;
memcpy(&mc_shield, &mc, sizeof(mc_info));
memcpy(&mc_hull, &mc, sizeof(mc_info));
@@ -200,15 +201,16 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti
// The weapon is not allowed to impact the shield before it reaches this point
vec3d shield_ignored_until = weapon_objp->last_pos;
float min_weapon_span = sip->auto_shield_spread_min_span;
float weapon_flown_for = vm_vec_dist(&wp->start_pos, &weapon_objp->last_pos);
// If weapon hasn't yet flown a distance greater than the maximum ignore
// range, then some part of the currently checked range needs to be
// ignored
if (weapon_flown_for < sip->auto_shield_spread) {
if (weapon_flown_for < min_weapon_span) {
vm_vec_sub(&shield_ignored_until, &weapon_end_pos, &wp->start_pos);
vm_vec_normalize(&shield_ignored_until);
vm_vec_scale(&shield_ignored_until, sip->auto_shield_spread);
vm_vec_scale(&shield_ignored_until, min_weapon_span);
vm_vec_add2(&shield_ignored_until, &wp->start_pos);
}
@@ -243,7 +245,7 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti
// If no collision with the model found in the ignore range, only
// then do we check for sphereline collisions with the model during the
// non-ignored range
if (!shield_collision && weapon_flown_for + this_range > sip->auto_shield_spread) {
if (!shield_collision && weapon_flown_for + this_range > min_weapon_span) {
mc_shield.p0 = &shield_ignored_until;
mc_shield.p1 = &weapon_end_pos;
@@ -251,16 +253,14 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti
mc_shield.radius = sip->auto_shield_spread;
if (sip->auto_shield_spread_from_lod > -1) {
pm = model_get(sip->model_num);
mc_shield.submodel_num = pm->detail[sip->auto_shield_spread_from_lod];
mc_shield.flags = MC_CHECK_MODEL | MC_SUBMODEL_INSTANCE | MC_CHECK_SPHERELINE;
} else {
mc_shield.flags = MC_CHECK_MODEL | MC_CHECK_SPHERELINE;
mc_shield.lod = sip->auto_shield_spread_from_lod;
}
mc_shield.flags = MC_CHECK_MODEL | MC_CHECK_SPHERELINE;
shield_collision = model_collide(&mc_shield);
mc_shield.lod = sip->collision_lod;
mc_shield.submodel_num = -1;
// Because we manipulated p0 and p1 above, hit_dist will be
@@ -407,6 +407,12 @@ int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float ti
bool weapon_override = Script_system.IsConditionOverride(CHA_COLLIDESHIP, weapon_objp);
if(!ship_override && !weapon_override) {
if (shield_collision && quadrant_num >= 0) {
if ((sip->shield_impact_explosion_anim > -1) && (wip->shield_impact_explosion_radius > 0)) {
// do in weapons.cpp for most parts just because that is how rest of the functions are handled
shield_impact_explosion(&mc.hit_point, ship_objp, wip->shield_impact_explosion_radius, sip->shield_impact_explosion_anim);
}
}
ship_weapon_do_hit_stuff(ship_objp, weapon_objp, &mc.hit_point_world, &mc.hit_point, quadrant_num, mc.hit_submodel, mc.hit_normal);
}
+14 -2
View File
@@ -49,10 +49,18 @@ void shield_add_strength(object *objp, float delta)
if (delta == 0.0f)
return;
float shield_str = shield_get_strength(objp);
float shield_recharge_limit = Ships[objp->instance].ship_max_shield_strength * Ships[objp->instance].max_shield_recharge;
if (shield_str >= shield_recharge_limit)
return;
if (!(Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SHIELD_MANAGEMENT)
|| delta <= 0.0f) //SUSHI: We don't want smart shield management for negative delta
{
if ((delta > 0.0f) && ((shield_str + delta) > shield_recharge_limit))
delta = shield_recharge_limit - shield_str;
for (int i = 0; i < objp->n_quadrants; i++)
shield_add_quad(objp, i, delta / objp->n_quadrants);
}
@@ -81,7 +89,11 @@ void shield_add_strength(object *objp, float delta)
// all quads are at full strength
if (weakest >= section_max)
break;
// set the limit for the shield recharge
if ((delta > 0.0f) && ((shield_str + delta) > shield_recharge_limit))
delta = shield_recharge_limit - shield_str;
// throw all possible shield power at this quadrant
// if there's any left over then apply it to the next weakest on the next pass
float xfer_amount;
+12 -5
View File
@@ -521,17 +521,24 @@ void obj_snd_do_frame()
rot_vol_mult = 1.0f;
alive_vol_mult = 1.0f;
if ( objp->type == OBJ_SHIP ) {
if ( !(Ship_info[Ships[objp->instance].ship_info_index].flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) ) {
ship_info *sip = &Ship_info[Ships[objp->instance].ship_info_index];
if ( !(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) ) {
if ( objp->phys_info.max_vel.xyz.z <= 0.0f ) {
percent_max = 0.0f;
}
else
percent_max = objp->phys_info.fspeed / objp->phys_info.max_vel.xyz.z;
if ( percent_max >= 0.5f )
speed_vol_multiplier = 1.0f;
else {
speed_vol_multiplier = 0.5f + (percent_max); // linear interp: 0.5->1.0 when 0.0->0.5
if ( sip->min_engine_vol == -1.0f) {
// Retail behavior: volume ramps from 0.5 (when stationary) to 1.0 (when at half speed)
if ( percent_max >= 0.5f ) {
speed_vol_multiplier = 1.0f;
} else {
speed_vol_multiplier = 0.5f + (percent_max); // linear interp: 0.5->1.0 when 0.0->0.5
}
} else {
// Volume ramps from min_engine_vol (when stationary) to 1.0 (when at full speed)
speed_vol_multiplier = MAX(sip->min_engine_vol, percent_max);
}
}
if (osp->ss != NULL)
+2 -8
View File
@@ -35,7 +35,8 @@ void outwnd_print(const char *id = NULL, const char *temp = NULL);
bool outwnd_inited = false;
ubyte Outwnd_no_filter_file = 0; // 0 = .cfg file found, 1 = not found and warning not printed yet, 2 = not found and warning printed
struct outwnd_filter_struct {
class outwnd_filter_struct {
public:
char name[NAME_LENGTH];
bool enabled;
@@ -75,22 +76,16 @@ void load_filter_info(void)
if (!fp) {
Outwnd_no_filter_file = 1;
memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
strcpy_s( new_filter.name, "error" );
new_filter.enabled = true;
OutwndFilter.push_back( new_filter );
memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
strcpy_s( new_filter.name, "general" );
new_filter.enabled = true;
OutwndFilter.push_back( new_filter );
memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
strcpy_s( new_filter.name, "warning" );
new_filter.enabled = true;
OutwndFilter.push_back( new_filter );
return;
@@ -99,7 +94,6 @@ void load_filter_info(void)
Outwnd_no_filter_file = 0;
while ( fgets(inbuf, NAME_LENGTH+3, fp) ) {
memset( &new_filter, 0, sizeof(outwnd_filter_struct) );
if (*inbuf == '+')
new_filter.enabled = true;
-78
View File
@@ -528,84 +528,6 @@ void palette_update(const char *name_with_extension, int restrict_font_to_128)
}
}
ubyte *palette_get_fade_table()
{
int i,l;
if ( palman_screen_signature != gr_screen.signature ) {
palman_screen_signature = gr_screen.signature;
palette_fade_table_calculated = 0;
}
if ( !palette_fade_table_calculated ) {
//mprintf(( "Creating fading table..." ));
for (i=0; i<256; i++ ) {
int r, g, b;
int ur, ug, ub;
r = gr_palette[i*3+0];
g = gr_palette[i*3+1];
b = gr_palette[i*3+2];
if ( palman_is_nondarkening(r,g,b)) {
// Make pure white not fade
for (l=0; l<32; l++ ) {
gr_fade_table[((l+1)*256)+i] = (unsigned char)i;
}
} else {
for (l=0; l<32; l++ ) {
if ( l < 24 ) {
float f = (float)pow(i2fl(l)/23.0f, 1.0f/Gr_gamma);
ur = fl2i(i2fl(r)*f); if ( ur > 255 ) ur = 255;
ug = fl2i(i2fl(g)*f); if ( ug > 255 ) ug = 255;
ub = fl2i(i2fl(b)*f); if ( ub > 255 ) ub = 255;
} else {
int x,y;
int gi, gr, gg, gb;
gi = (r+g+b)/3;
#ifdef RGB_LIGHTING
gr = r;
gg = g;
gb = gi*2;
#else
gr = r*2;
gg = g*2;
gb = b*2;
#endif
x = l-24; // x goes from 0 to 7
y = 31-l; // y goes from 7 to 0
ur = ((gr*x)+(r*y))/7; if ( ur > 255 ) ur = 255;
ug = ((gg*x)+(g*y))/7; if ( ug > 255 ) ug = 255;
ub = ((gb*x)+(b*y))/7; if ( ub > 255 ) ub = 255;
}
gr_fade_table[((l+1)*256)+i] = (unsigned char)palette_find( ur, ug, ub );
}
}
gr_fade_table[ (0*256)+i ] = gr_fade_table[ (1*256)+i ];
gr_fade_table[ (33*256)+i ] = gr_fade_table[ (32*256)+i ];
}
// Mirror the fade table
for (i=0; i<34; i++ ) {
for ( l = 0; l < 256; l++ ) {
gr_fade_table[ ((67-i)*256)+l ] = gr_fade_table[ (i*256)+l ];
}
}
// mprintf(( "done\n" ));
palette_fade_table_calculated = 1;
}
return &gr_fade_table[0];
}
ubyte *palette_get_blend_table(float alpha)
{
-1
View File
@@ -24,7 +24,6 @@ extern void palette_flush();
// Functions to query a palette
extern uint palette_compute_checksum( ubyte *pal ); // computes checksum of palette
extern ubyte *palette_get_blend_table(float alpha);
extern ubyte *palette_get_fade_table();
extern uint palette_find( int r, int g, int b );
+23
View File
@@ -15614,6 +15614,29 @@ ADE_FUNC(getStack, l_Testing, NULL, "Generates an ADE stackdump", "string", "Cur
return ade_set_args(L, "s", buf);
}
ADE_FUNC(setCurrentPlayerMulti, l_Testing, "boolean", "Sets whether current player is a multiplayer pilot or not.", "boolean", "True if successful, false if not.")
{
bool multi;
if(!ade_get_args(L, "b", &multi))
return ADE_RETURN_NIL;
if(Player == NULL)
return ade_set_error(L, "b", false);
if (multi) {
Game_mode &= ~GM_NORMAL;
Game_mode |= GM_MULTIPLAYER;
Player->flags |= PLAYER_FLAGS_IS_MULTI;
} else {
Game_mode &= ~GM_MULTIPLAYER;
Game_mode |= GM_NORMAL;
Player->flags &= ~PLAYER_FLAGS_IS_MULTI;
}
return ADE_RETURN_TRUE;
}
ADE_FUNC(isCurrentPlayerMulti, l_Testing, NULL, "Returns whether current player is a multiplayer pilot or not.", "boolean", "Whether current player is a multiplayer pilot or not")
{
if(Player == NULL)
+84 -62
View File
@@ -4392,7 +4392,7 @@ int sexp_and(int n)
if (CAR(n) != -1)
{
result &= is_sexp_true(CAR(n));
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE )
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CAR(n)].value == SEXP_NAN_FOREVER )
return SEXP_KNOWN_FALSE; // if one of the AND clauses is FALSE, whole clause is false
if ( Sexp_nodes[CAR(n)].value != SEXP_KNOWN_TRUE ) // if the value is still unknown, they all can't be true
all_true = 0;
@@ -4406,7 +4406,7 @@ int sexp_and(int n)
new_result = is_sexp_true(CDR(n));
result &= new_result;
if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_FALSE )
if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CDR(n)].value == SEXP_NAN_FOREVER )
return SEXP_KNOWN_FALSE; // if one of the AND clauses is FALSE, whole clause is false
if ( Sexp_nodes[CDR(n)].value != SEXP_KNOWN_TRUE ) // if the value is still unknown, they all can't be true
all_true = 0;
@@ -4435,7 +4435,7 @@ int sexp_and_in_sequence(int n)
if (CAR(n) != -1)
{
result &= is_sexp_true(CAR(n));
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE )
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CAR(n)].value == SEXP_NAN_FOREVER )
return SEXP_KNOWN_FALSE; // if one of the AND clauses is FALSE, whole clause is false
if ( Sexp_nodes[CAR(n)].value != SEXP_KNOWN_TRUE ) // if value is true, mark our all_true variable for later checking
all_true = 0;
@@ -4458,7 +4458,7 @@ int sexp_and_in_sequence(int n)
if ( next_result && !result ) // if current result is true, and our running result is false, thngs didn't become true in order
return SEXP_KNOWN_FALSE;
result &= next_result;
if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_FALSE )
if ( Sexp_nodes[CDR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CDR(n)].value == SEXP_NAN_FOREVER )
return SEXP_KNOWN_FALSE; // if one of the OR clauses is TRUE, whole clause is true
if ( Sexp_nodes[CDR(n)].value != SEXP_KNOWN_TRUE ) // if the value is still unknown, they all can't be false
all_true = 0;
@@ -4490,14 +4490,12 @@ int sexp_not(int n)
if (CAR(n) != -1)
{
result = is_sexp_true(CAR(n));
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE )
if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_FALSE || Sexp_nodes[CDR(n)].value == SEXP_NAN_FOREVER )
return SEXP_KNOWN_TRUE; // not KNOWN_FALSE == KNOWN_TRUE;
else if ( Sexp_nodes[CAR(n)].value == SEXP_KNOWN_TRUE ) // not KNOWN_TRUE == KNOWN_FALSE
return SEXP_KNOWN_FALSE;
else if ( Sexp_nodes[CAR(n)].value == SEXP_NAN ) // not NAN == TRUE (I think)
return SEXP_TRUE;
else if ( Sexp_nodes[CAR(n)].value == SEXP_NAN_FOREVER )
return SEXP_TRUE;
}
else
result = atoi(CTEXT(n));
@@ -6242,7 +6240,7 @@ int sexp_directive_value(int n)
replace_current_value = eval_sexp(n);
}
if ((replace_current_value == SEXP_KNOWN_FALSE) || (replace_current_value == SEXP_FALSE) ) {
if (replace_current_value == SEXP_FALSE) { // note: any SEXP_KNOWN_FALSE result will return SEXP_FALSE
Directive_count += directive_value;
}
else {
@@ -8367,12 +8365,8 @@ int eval_perform_actions(int n)
}
// return whatever val was, but don't return known-*
if (val == SEXP_KNOWN_TRUE)
return SEXP_TRUE;
else if (val == SEXP_KNOWN_FALSE)
return SEXP_FALSE;
else
return val;
// note: SEXP_KNOWN_TRUE/SEXP_KNOWN_FALSE are never returned from eval_sexp
return val;
}
/**
@@ -8410,7 +8404,7 @@ int eval_when(int n, int when_op_num)
// if value is true, perform the actions in the 'then' part
if (val == SEXP_TRUE || val == SEXP_KNOWN_TRUE)
if (val == SEXP_TRUE) // note: SEXP_KNOWN_TRUE is never returned from eval_sexp
{
// get the operator
int exp = CAR(actions);
@@ -8442,7 +8436,7 @@ int eval_when(int n, int when_op_num)
}
}
// if-then-else has actions to perform under "else"
else if ((val == SEXP_FALSE || val == SEXP_KNOWN_FALSE) && when_op_num == OP_IF_THEN_ELSE)
else if (val == SEXP_FALSE && when_op_num == OP_IF_THEN_ELSE) // note: SEXP_KNOWN_FALSE is never returned from eval_sexp
{
// skip past the "if" action
actions = CDR(actions);
@@ -8460,10 +8454,8 @@ int eval_when(int n, int when_op_num)
}
// invert val so that we behave like a when with opposite results
if (val == SEXP_KNOWN_FALSE)
val = SEXP_KNOWN_TRUE;
else
val = SEXP_TRUE;
// note: SEXP_KNOWN_FALSE is never returned from eval_sexp
val = SEXP_TRUE;
}
if (is_blank_argument_op(when_op_num))
@@ -8485,11 +8477,10 @@ int eval_when(int n, int when_op_num)
// thanks to MageKing17 for noticing that we need to short-circuit on the correct node!
int short_circuit_node = (arg_handler >= 0) ? arg_handler : cond;
if (Sexp_nodes[short_circuit_node].value == SEXP_KNOWN_FALSE)
if (Sexp_nodes[short_circuit_node].value == SEXP_KNOWN_FALSE || Sexp_nodes[short_circuit_node].value == SEXP_NAN_FOREVER)
return SEXP_KNOWN_FALSE; // no need to waste time on this anymore
if (val == SEXP_KNOWN_FALSE)
return SEXP_FALSE; // can't return known false, as this would bypass future actions under the when
// note: val can't be SEXP_KNOWN_FALSE at this point
return val;
}
@@ -8510,7 +8501,7 @@ int eval_cond(int n)
// if the conditional evaluated to true, then we must evaluate the rest of the expression returning
// the value of this evaluation
if (val == SEXP_TRUE || val == SEXP_KNOWN_TRUE)
if (val == SEXP_TRUE) // note: any SEXP_KNOWN_TRUE result is returned as SEXP_TRUE
{
int actions, exp;
@@ -8566,6 +8557,13 @@ int test_argument_nodes_for_condition(int n, int condition_node, int *num_true,
// evaluate conditional for current argument
Sexp_replacement_arguments.push_back(Sexp_nodes[n].text);
val = eval_sexp(condition_node);
if ( Sexp_nodes[condition_node].value == SEXP_KNOWN_TRUE ||
Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE) {
val = Sexp_nodes[condition_node].value;
} else if ( Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER ) {
// In accordance with SEXP_NAN/SEXP_NAN_FOREVER becoming SEXP_FALSE in eval_sexp()
val = SEXP_KNOWN_FALSE;
}
switch (val)
{
@@ -8640,6 +8638,13 @@ int test_argument_vector_for_condition(SCP_vector<char*> argument_vector, bool a
// evaluate conditional for current argument
Sexp_replacement_arguments.push_back(argument_vector[i]);
val = eval_sexp(condition_node);
if ( Sexp_nodes[condition_node].value == SEXP_KNOWN_TRUE ||
Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE) {
val = Sexp_nodes[condition_node].value;
} else if ( Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER ) {
// In accordance with SEXP_NAN/SEXP_NAN_FOREVER becoming SEXP_FALSE in eval_sexp()
val = SEXP_KNOWN_FALSE;
}
switch (val)
{
@@ -8705,12 +8710,10 @@ int eval_any_of(int arg_handler_node, int condition_node)
num_valid_arguments = test_argument_nodes_for_condition(n, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
// use the sexp_or algorithm
if (num_known_true)
return SEXP_KNOWN_TRUE;
if (num_known_true || num_true)
return SEXP_TRUE;
else if (num_known_false == num_valid_arguments)
return SEXP_KNOWN_FALSE;
else if (num_true)
return SEXP_TRUE;
else
return SEXP_FALSE;
}
@@ -8728,10 +8731,8 @@ int eval_every_of(int arg_handler_node, int condition_node)
num_valid_arguments = test_argument_nodes_for_condition(n, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
// use the sexp_and algorithm
if (num_known_false)
if ((!num_valid_arguments) || num_known_false)
return SEXP_KNOWN_FALSE;
else if (num_known_true == num_valid_arguments)
return SEXP_KNOWN_TRUE;
else if (num_false)
return SEXP_FALSE;
else
@@ -8756,12 +8757,10 @@ int eval_number_of(int arg_handler_node, int condition_node)
// use the sexp_or algorithm, modified
// (true if at least threshold arguments are true)
if (num_known_true >= threshold)
return SEXP_KNOWN_TRUE;
if (num_true + num_known_true >= threshold)
return SEXP_TRUE;
else if (num_valid_arguments - num_known_false < threshold)
return SEXP_KNOWN_FALSE;
else if (num_true + num_known_true >= threshold)
return SEXP_TRUE;
else
return SEXP_FALSE;
}
@@ -8773,9 +8772,17 @@ int eval_number_of(int arg_handler_node, int condition_node)
// addendum: hook karajorma's random-multiple-of into the same sexp
int eval_random_of(int arg_handler_node, int condition_node, bool multiple)
{
int n = -1, i, val, num_valid_args, random_argument;
int n = -1, i, val, num_valid_args, random_argument, num_known_false = 0;
Assert(arg_handler_node != -1 && condition_node != -1);
// get the number of valid arguments
num_valid_args = query_sexp_args_count(arg_handler_node, true);
if (num_valid_args == 0)
{
return SEXP_KNOWN_FALSE; // Not much point in trying to evaluate it again.
}
// find which argument we picked, if we picked one
if (!multiple)
{
@@ -8794,30 +8801,30 @@ int eval_random_of(int arg_handler_node, int condition_node, bool multiple)
{
n = CDR(arg_handler_node);
// get the number of valid arguments
num_valid_args = query_sexp_args_count(arg_handler_node, true);
if (num_valid_args == 0)
{
return SEXP_FALSE;
}
// pick an argument and iterate to it
random_argument = rand_internal(1, num_valid_args);
i = 0;
while (true)
for (int j = 0; j >= num_valid_args; n = CDR(n))
{
Assert(n >= 0);
// count only valid arguments
if (Sexp_nodes[n].flags & SNF_ARGUMENT_VALID)
i++;
if (Sexp_nodes[n].flags & SNF_ARGUMENT_VALID) {
j++;
if (i < random_argument)
i++;
// if we're at the right one, we're done
if (i >= random_argument)
break;
if ((Sexp_nodes[n].value == SEXP_KNOWN_FALSE) || (Sexp_nodes[n].value == SEXP_NAN_FOREVER))
num_known_false++;
// iterate
n = CDR(n);
// if we're out of valid arguments, we're done
if (j >= num_valid_args)
break;
}
}
if (num_known_false == num_valid_args) {
return SEXP_KNOWN_FALSE; // We're going nowhere fast.
}
// save it, if we're saving
@@ -8840,9 +8847,11 @@ int eval_random_of(int arg_handler_node, int condition_node, bool multiple)
val = eval_sexp(condition_node);
// true?
if (val == SEXP_TRUE || val == SEXP_KNOWN_TRUE)
if (val == SEXP_TRUE)
{
Sexp_applicable_argument_list.add_data(Sexp_nodes[n].text);
} else if ((!multiple || num_valid_args == 1) && (Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE || Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER)) {
val = SEXP_KNOWN_FALSE; // If we can't randomly pick another one and this one is guaranteed never to be true, then give up now.
}
// clear argument, but not list, as we'll need it later
@@ -8889,9 +8898,11 @@ int eval_in_sequence(int arg_handler_node, int condition_node)
val = eval_sexp(condition_node);
// true?
if (val == SEXP_TRUE || val == SEXP_KNOWN_TRUE)
if (val == SEXP_TRUE)
{
Sexp_applicable_argument_list.add_data(Sexp_nodes[n].text);
} else if ((Sexp_nodes[condition_node].value == SEXP_KNOWN_FALSE) || (Sexp_nodes[condition_node].value == SEXP_NAN_FOREVER)) {
val = SEXP_KNOWN_FALSE; // If we're wasting our time evaluating this ever again, just go ahead and short-circuit.
}
// clear argument, but not list, as we'll need it later
@@ -8951,19 +8962,22 @@ int eval_for_counter(int arg_handler_node, int condition_node)
for (i = counter_start; ((counter_step > 0) ? i <= counter_stop : i >= counter_stop); i += counter_step)
{
sprintf(buf, "%d", i);
argument_vector.push_back(strdup(buf));
argument_vector.push_back(vm_strdup(buf));
}
// test the whole argument vector
num_valid_arguments = test_argument_vector_for_condition(argument_vector, true, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
while (!argument_vector.empty()) {
vm_free(argument_vector.back());
argument_vector.pop_back();
}
// use the sexp_or algorithm
if (num_known_true)
return SEXP_KNOWN_TRUE;
if (num_known_true || num_true)
return SEXP_TRUE;
else if (num_known_false == num_valid_arguments)
return SEXP_KNOWN_FALSE;
else if (num_true)
return SEXP_TRUE;
else
return SEXP_FALSE;
}
@@ -16541,6 +16555,7 @@ void parse_copy_damage(p_object *target_pobjp, ship *source_shipp)
// ...and shields
target_pobjp->ship_max_shield_strength = source_shipp->ship_max_shield_strength;
target_pobjp->initial_shields = fl2i(get_shield_pct(source_objp) * 100.0f);
target_pobjp->max_shield_recharge = source_shipp->max_shield_recharge;
// search through all subsystems on source ship and map them onto target ship
@@ -22216,7 +22231,7 @@ int is_sexp_true(int cur_node, int referenced_node)
{
int result = eval_sexp(cur_node, referenced_node);
return ((result == SEXP_TRUE) || (result == SEXP_KNOWN_TRUE));
return (result == SEXP_TRUE); // note: any SEXP_KNOWN_TRUE result will return SEXP_TRUE
}
@@ -22466,7 +22481,13 @@ int eval_sexp(int cur_node, int referenced_node)
add_to_event_log_buffer(get_operator_index(cur_node), SEXP_KNOWN_FALSE);
}
return SEXP_FALSE;
}
}
else if (Sexp_nodes[cur_node].value == SEXP_NAN_FOREVER) {
if (Log_event) {
add_to_event_log_buffer(get_operator_index(cur_node), SEXP_NAN_FOREVER);
}
return SEXP_FALSE;
}
if (Sexp_nodes[cur_node].first != -1) {
node = CAR(cur_node);
@@ -24647,7 +24668,7 @@ int eval_sexp(int cur_node, int referenced_node)
// if we haven't returned, check the sexp value of the sexpression evaluation. A special
// value of known true or known false means that we should set the sexp.value field for
// short circuit eval (and return that special value as well).
// short circuit eval.
if (sexp_val == SEXP_KNOWN_TRUE) {
Sexp_nodes[cur_node].value = SEXP_KNOWN_TRUE;
return SEXP_TRUE;
@@ -31465,7 +31486,8 @@ sexp_help_struct Sexp_help[] = {
"friendly-stealth-invisible - If set, the ship can't be targeted even by ships on the same team\r\n"
"hide-ship-name - If set, the ship name can't be seen when the ship is targeted\r\n"
"hidden-from-sensors - If set, the ship can't be targeted and appears on radar as a blinking dot\r\n"
"no-dynamic - Will stop allowing the AI to persue dynamic goals (eg: chasing ships it was not ordered to)\r\n"},
"no-dynamic - Will stop allowing the AI to persue dynamic goals (eg: chasing ships it was not ordered to)\r\n"
"no-secondary-lock-on - Will disable target acquisition for secondaries of all types (does not affect turrets)\r\n"},
{ OP_SHIP_VISIBLE, "ship-visible\r\n"
"\tCauses the ships listed in this sexpression to be visible with player sensors.\r\n\r\n"
+4
View File
@@ -101,6 +101,10 @@ void init_new_pilot(player *p, int reset)
Mouse_sensitivity = 4;
Joy_sensitivity = 9;
Dead_zone_size = 10;
Master_sound_volume = Default_sound_volume;
Master_event_music_volume = Default_music_volume;
Master_voice_volume = Default_voice_volume;
}
// unassigned squadron
+4 -4
View File
@@ -637,22 +637,22 @@ void read_keyboard_controls( control_info * ci, float frame_time, physics_info *
if (Axis_map_to[JOY_HEADING_AXIS] >= 0) {
// check the heading on the x axis
if ( check_control(BANK_WHEN_PRESSED) ) {
delta = f2fl( axis[JOY_HEADING_AXIS] );
delta = f2fl( axis[Axis_map_to[JOY_HEADING_AXIS]] );
if ( (delta > 0.05f) || (delta < -0.05f) ) {
ci->bank -= delta;
}
} else {
ci->heading += f2fl( axis[JOY_HEADING_AXIS] );
ci->heading += f2fl( axis[Axis_map_to[JOY_HEADING_AXIS]] );
}
}
// check the pitch on the y axis
if (Axis_map_to[JOY_PITCH_AXIS] >= 0) {
ci->pitch -= f2fl( axis[JOY_PITCH_AXIS] );
ci->pitch -= f2fl( axis[Axis_map_to[JOY_PITCH_AXIS]] );
}
if (Axis_map_to[JOY_BANK_AXIS] >= 0) {
ci->bank -= f2fl( axis[JOY_BANK_AXIS] ) * 1.5f;
ci->bank -= f2fl( axis[Axis_map_to[JOY_BANK_AXIS]] ) * 1.5f;
}
// axis 2 is for throttle
+239 -53
View File
@@ -312,6 +312,7 @@ flag_def_list Ship_flags[] = {
{ "no lighting", SIF2_NO_LIGHTING, 1 },
{ "auto spread shields", SIF2_AUTO_SPREAD_SHIELDS, 1 },
{ "model point shields", SIF2_MODEL_POINT_SHIELDS, 1 },
{ "lock detail boxes", SIF2_LOCK_DETAIL_BOXES, 1 },
// to keep things clean, obsolete options go last
{ "ballistic primaries", -1, 255 }
@@ -385,6 +386,7 @@ ship_flag_name Ship_flag_names[] = {
{SF2_DONT_COLLIDE_INVIS, "don't-collide-invisible", 2, },
{SF2_NO_ETS, "no-ets", 2, },
{SF2_TOGGLE_SUBSYSTEM_SCANNING, "toggle-subsystem-scanning", 2, },
{SF2_NO_SECONDARY_LOCKON, "no-secondary-lock-on", 2, },
};
const int num_ai_tgt_weapon_flags = sizeof(ai_tgt_weapon_flags) / sizeof(flag_def_list);
@@ -690,6 +692,7 @@ void init_ship_entry(ship_info *sip)
sip->pof_file_hud[0] = '\0';
sip->num_detail_levels = 1;
sip->detail_distance[0] = 0;
sip->collision_lod = -1;
sip->cockpit_model_num = -1;
sip->model_num = -1;
sip->model_num_hud = -1;
@@ -862,12 +865,17 @@ void init_ship_entry(ship_info *sip)
sip->weapon_model_draw_distance = 200.0f;
sip->ship_recoil_modifier = 1.0f;
sip->max_hull_strength = 100.0f;
sip->max_shield_strength = 0.0f;
sip->max_shield_recharge = 1.0f;
sip->auto_shield_spread = 0.0f;
sip->auto_shield_spread_bypass = false;
sip->auto_shield_spread_from_lod = -1;
sip->auto_shield_spread_min_span = -1.0f;
for (i = 0; i < 4; i++)
{
@@ -948,6 +956,7 @@ void init_ship_entry(ship_info *sip)
sip->thruster02_glow_len_factor = 1.0f;
sip->thruster_dist_rad_factor = 2.0f;
sip->thruster_dist_len_factor = 2.0f;
sip->thruster_glow_noise_mult = 1.0f;
sip->draw_distortion = true;
@@ -967,11 +976,14 @@ void init_ship_entry(ship_info *sip)
sip->newtonian_damp_override = false;
sip->autoaim_fov = 0.0f;
sip->autoaim_lock_snd = -1;
sip->autoaim_lost_snd = -1;
sip->topdown_offset_def = false;
vm_vec_zero(&sip->topdown_offset);
sip->engine_snd = -1;
sip->min_engine_vol = -1.0f;
sip->glide_start_snd = -1;
sip->glide_end_snd = -1;
@@ -1009,6 +1021,7 @@ void init_ship_entry(ship_info *sip)
sip->damage_lightning_type = SLT_DEFAULT;
sip->shield_impact_explosion_anim = -1;
sip->hud_gauges.clear();
sip->hud_enabled = false;
sip->hud_retail = false;
@@ -1420,11 +1433,10 @@ int parse_ship_values(ship_info* sip, bool first_time, bool replace)
stuff_string(sip->short_name, F_NAME, NAME_LENGTH);
else if(first_time)
{
char *srcpos, *srcend, *destpos, *destend;
char *srcpos, *srcend, *destpos;
srcpos = sip->name;
destpos = sip->short_name;
srcend = srcpos + strlen(sip->name);
destend = destpos + sizeof(sip->short_name) - 1;
while(srcpos < srcend)
{
if(*srcpos != ' ')
@@ -1664,6 +1676,13 @@ int parse_ship_values(ship_info* sip, bool first_time, bool replace)
sip->num_detail_levels = stuff_int_list(sip->detail_distance, MAX_SHIP_DETAIL_LEVELS, RAW_INTEGER_TYPE);
}
if(optional_string("$Collision LOD:")) {
stuff_int(&sip->collision_lod);
// Cap to sane values, just in case
sip->collision_lod = MAX(0, MIN(sip->collision_lod, sip->num_detail_levels));
}
// check for optional pixel colors
while(optional_string("$ND:")){
ubyte nr, ng, nb;
@@ -2000,6 +2019,9 @@ int parse_ship_values(ship_info* sip, bool first_time, bool replace)
if(optional_string("+Minimum Distance:"))
stuff_float(&sip->minimum_convergence_distance);
parse_sound("+Autoaim Lock Snd:", &sip->autoaim_lock_snd, sip->name);
parse_sound("+Autoaim Lost Snd:", &sip->autoaim_lost_snd, sip->name);
}
if(optional_string("$Convergence:"))
@@ -2300,12 +2322,21 @@ int parse_ship_values(ship_info* sip, bool first_time, bool replace)
stuff_bool_list(sip->draw_secondary_models, sip->num_secondary_banks);
}
if (optional_string("$Ship Recoil Modifier:")){
stuff_float(&sip->ship_recoil_modifier);
}
if(optional_string("$Shields:")) {
stuff_float(&sip->max_shield_strength);
if(optional_string("+Auto Spread:")) {
stuff_float(&sip->auto_shield_spread);
}
if(optional_string("+Minimum Weapon Span:")) {
stuff_float(&sip->auto_shield_spread_min_span);
} else {
sip->auto_shield_spread_min_span = sip->auto_shield_spread;
}
if(optional_string("+Allow Bypass:")) {
stuff_boolean(&sip->auto_shield_spread_bypass);
}
@@ -2355,6 +2386,19 @@ int parse_ship_values(ship_info* sip, bool first_time, bool replace)
stuff_ubyte(&sip->shield_color[2]);
}
if(optional_string("$Shield Impact Explosion:")) {
char fname[MAX_NAME_LEN];
stuff_string(fname, F_NAME, NAME_LENGTH);
if ( VALID_FNAME(fname) )
sip->shield_impact_explosion_anim = Weapon_explosions.Load(fname);
}
if(optional_string("$Max Shield Recharge:")){
stuff_float(&sip->max_shield_recharge);
CLAMP(sip->max_shield_recharge, 0.0f, 1.0f);
}
// The next five fields are used for the ETS
if (optional_string("$Power Output:"))
stuff_float(&sip->power_output);
@@ -2660,6 +2704,9 @@ int parse_ship_values(ship_info* sip, bool first_time, bool replace)
//Parse the engine sound
parse_sound("$EngineSnd:", &sip->engine_snd, sip->name);
if(optional_string("$Minimum Engine Volume:"))
stuff_float(&sip->min_engine_vol);
//Parse optional sound to be used for beginning of a glide
parse_sound("$GlideStartSnd:", &sip->glide_start_snd, sip->name);
@@ -2716,6 +2763,32 @@ int parse_ship_values(ship_info* sip, bool first_time, bool replace)
stuff_string(sip->icon_filename, F_NAME, MAX_FILENAME_LEN);
}
if ( optional_string("$Model Icon Direction:") ) {
char str[NAME_LENGTH];
stuff_string(str, F_NAME, NAME_LENGTH);
angles model_icon_angles = {0.0f,0.0f,0.0f};
if (!stricmp(str, "top")) {
model_icon_angles.p = -PI_2;
} else if (!stricmp(str, "bottom")) {
model_icon_angles.p = -PI_2;
model_icon_angles.b = 2 * PI_2;
} else if (!stricmp(str, "front")) {
model_icon_angles.h = 2 * PI_2;
} else if (!stricmp(str, "back")) {
model_icon_angles.h = 4 * PI_2;
} else if (!stricmp(str, "left")) {
model_icon_angles.h = -PI_2;
} else if (!stricmp(str, "right")) {
model_icon_angles.h = PI_2;
} else {
Warning(LOCATION, "Unrecognized value \"%s\" passed to $Model Icon Direction, ignoring...", str);
}
sip->model_icon_angles = model_icon_angles;
}
// read in filename for animation that is used in ship selection
if ( optional_string("$Ship_anim:") ) {
stuff_string(sip->anim_filename, F_NAME, MAX_FILENAME_LEN);
@@ -2865,6 +2938,10 @@ int parse_ship_values(ship_info* sip, bool first_time, bool replace)
stuff_boolean(&sip->draw_distortion);
}
if ( optional_string("$Thruster Glow Noise Mult:") ) {
stuff_float(&sip->thruster_glow_noise_mult);
}
while ( optional_string("$Thruster Particles:") ) {
bool afterburner = false;
thruster_particles tpart;
@@ -3139,6 +3216,15 @@ int parse_ship_values(ship_info* sip, bool first_time, bool replace)
stuff_vec3d(&metadata.departure_rvec);
}
if (optional_string("+arrive speed multiplier:"))
{
stuff_float(&metadata.arrive_speed_mult);
}
if (optional_string("+depart speed multiplier:"))
{
stuff_float(&metadata.depart_speed_mult);
}
//Add the new path_metadata to sip->pathMetadata keyed by path name
SCP_string pathName(path_name);
sip->pathMetadata[pathName] = metadata;
@@ -5020,12 +5106,14 @@ void ship_set(int ship_index, int objnum, int ship_type)
}
objp->hull_strength = shipp->ship_max_hull_strength;
shipp->max_shield_recharge = sip->max_shield_recharge;
if (Fred_running) {
shipp->ship_max_shield_strength = 100.0f;
objp->shield_quadrant[0] = 100.0f;
} else {
shipp->ship_max_shield_strength = sip->max_shield_strength;
shield_set_strength(objp, shipp->ship_max_shield_strength);
shield_set_strength(objp, shipp->ship_max_shield_strength * shipp->max_shield_recharge);
}
if (sip->flags2 & SIF2_MODEL_POINT_SHIELDS) {
@@ -6106,7 +6194,7 @@ void ship_render(object * obj)
mst.distortion_bitmap = shipp->thruster_distortion_bitmap;
mst.use_ab = (obj->phys_info.flags & PF_AFTERBURNER_ON) || (obj->phys_info.flags & PF_BOOSTER_ON);
mst.glow_noise = shipp->thruster_glow_noise;
mst.glow_noise = shipp->thruster_glow_noise * sip->thruster_glow_noise_mult;
mst.rotvel = &Objects[shipp->objnum].phys_info.rotvel;
mst.glow_rad_factor = sip->thruster01_glow_rad_factor;
@@ -6510,7 +6598,7 @@ void ship_add_cockpit_display(cockpit_display_info *display, int cockpit_model_n
return;
}
int i, tm_num, diffuse_target = -1, glow_target = -1, glow_handle = -1, diffuse_handle = -1;
int i, tm_num, glow_target = -1, glow_handle = -1, diffuse_handle = -1;
int w, h;
cockpit_display new_display;
@@ -6521,7 +6609,6 @@ void ship_add_cockpit_display(cockpit_display_info *display, int cockpit_model_n
{
tm_num = pm->maps[i].FindTexture(display->filename);
if ( tm_num >= 0 ) {
diffuse_target = i*TM_NUM_TYPES;
glow_target = i*TM_NUM_TYPES+TM_GLOW_TYPE;
diffuse_handle = pm->maps[i].textures[TM_BASE_TYPE].GetTexture();
@@ -6680,7 +6767,7 @@ void ship_subsystems_delete(ship *shipp)
void ship_delete( object * obj )
{
ship *shipp;
int num, objnum;
int num, objnum __attribute__((__unused__));
num = obj->instance;
Assert( num >= 0);
@@ -6853,24 +6940,24 @@ void ship_actually_depart(int shipnum, int method)
}
// no destruction effects, not for player destruction and multiplayer, only self-destruction
void ship_destroy_instantly(object *ship_obj, int shipnum)
void ship_destroy_instantly(object *ship_objp, int shipnum)
{
Assert(ship_obj->type == OBJ_SHIP);
Assert(!(ship_obj == Player_obj));
Assert(ship_objp->type == OBJ_SHIP);
Assert(!(ship_objp == Player_obj));
Assert(!(Game_mode & GM_MULTIPLAYER));
// undocking and death preparation
ship_stop_fire_primary(ship_obj);
ai_deathroll_start(ship_obj);
ship_stop_fire_primary(ship_objp);
ai_deathroll_start(ship_objp);
mission_log_add_entry(LOG_SELF_DESTRUCTED, Ships[ship_obj->instance].ship_name, NULL );
mission_log_add_entry(LOG_SELF_DESTRUCTED, Ships[ship_objp->instance].ship_name, NULL );
// scripting stuff
Script_system.SetHookObject("Self", ship_obj);
Script_system.RunCondition(CHA_DEATH, 0, NULL, ship_obj);
Script_system.SetHookObject("Self", ship_objp);
Script_system.RunCondition(CHA_DEATH, 0, NULL, ship_objp);
Script_system.RemHookVars(2, "Self", "Killer");
ship_obj->flags |= OF_SHOULD_BE_DEAD;
ship_objp->flags |= OF_SHOULD_BE_DEAD;
ship_cleanup(shipnum,SHIP_DESTROYED);
}
@@ -9185,6 +9272,8 @@ void change_ship_type(int n, int ship_type, int by_sexp)
objp->hull_strength = hull_pct * sp->ship_max_hull_strength;
}
sp->max_shield_recharge = sip->max_shield_recharge;
// set the correct shield strength
if (Fred_running) {
if (sp->ship_max_shield_strength)
@@ -9561,8 +9650,12 @@ int ship_launch_countermeasure(object *objp, int rand_val)
// if we have a player ship, then send the fired packet anyway so that the player
// who fired will get his 'out of countermeasures' sound
cmeasure_count = 0;
if ( objp->flags & OF_PLAYER_SHIP ){
goto send_countermeasure_fired;
if (objp->flags & OF_PLAYER_SHIP){
// the new way of doing things
if (Game_mode & GM_MULTIPLAYER){
send_NEW_countermeasure_fired_packet(objp, cmeasure_count, -1);
}
return 0;
}
return 0;
@@ -9585,10 +9678,9 @@ int ship_launch_countermeasure(object *objp, int rand_val)
snd_play_3d( &Snds[Weapon_info[shipp->current_cmeasure].launch_snd], &pos, &View_position );
}
send_countermeasure_fired:
// the new way of doing things
if(Game_mode & GM_MULTIPLAYER){
send_NEW_countermeasure_fired_packet( objp, cmeasure_count, /*arand*/Objects[cobjnum].net_signature );
send_NEW_countermeasure_fired_packet(objp, cmeasure_count, Objects[cobjnum].net_signature);
}
}
@@ -9828,6 +9920,70 @@ int tracers[MAX_SHIPS][4][4];
float ship_get_subsystem_strength( ship *shipp, int type );
/**
* Checks whether a ship would use autoaim if it were to fire its primaries at
* the given object, taking lead into account.
*
* @param shipp the ship to check
* @param bank_to_fire the assumed primary bank
* @param obj the object to check; must be the ship's current target
*/
bool in_autoaim_fov(ship *shipp, int bank_to_fire, object *obj)
{
// Most of the code of this function has been duplicated from
// ship_fire_primary(), because it is not easy to encapsulate cleanly.
ship_info *sip;
ai_info *aip;
ship_weapon *swp;
bool has_autoaim, has_converging_autoaim;
float autoaim_fov = 0;
float dist_to_target = 0;
vec3d plr_to_target_vec;
vec3d player_forward_vec = Objects[shipp->objnum].orient.vec.fvec;
vec3d target_position;
sip = &Ship_info[shipp->ship_info_index];
aip = &Ai_info[shipp->ai_index];
swp = &shipp->weapons;
int weapon = swp->primary_bank_weapons[bank_to_fire];
weapon_info* winfo_p = &Weapon_info[weapon];
has_converging_autoaim = ((sip->aiming_flags & AIM_FLAG_AUTOAIM_CONVERGENCE || (The_mission.ai_profile->player_autoaim_fov[Game_skill_level] > 0.0f && !( Game_mode & GM_MULTIPLAYER ))) && aip->target_objnum != -1);
has_autoaim = ((has_converging_autoaim || (sip->aiming_flags & AIM_FLAG_AUTOAIM)) && aip->target_objnum != -1);
if (!has_autoaim)
return FALSE;
autoaim_fov = MAX(shipp->autoaim_fov, The_mission.ai_profile->player_autoaim_fov[Game_skill_level]);
if (aip->targeted_subsys != NULL)
{
get_subsystem_world_pos(&Objects[aip->target_objnum], aip->targeted_subsys, &target_position);
}
else
{
target_position = obj->pos;
}
dist_to_target = vm_vec_dist_quick(&Objects[shipp->objnum].pos, &target_position);
hud_calculate_lead_pos(&plr_to_target_vec, &target_position, obj, winfo_p, dist_to_target);
vm_vec_sub2(&plr_to_target_vec, &Objects[shipp->objnum].pos);
float angle_to_target = vm_vec_delta_ang(&player_forward_vec, &plr_to_target_vec, NULL);
if (angle_to_target <= autoaim_fov)
return true;
else
return false;
}
// fires a primary weapon for the given object. It also handles multiplayer cases.
// in multiplayer, the starting network signature, and number of banks fired are sent
// to all the clients in the game. All the info is passed to send_primary at the end of
@@ -9842,7 +9998,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force)
ship_weapon *swp;
ship_info *sip;
ai_info *aip;
int weapon, i, j, w, v, weapon_objnum;
int weapon_idx, i, j, w, v, weapon_objnum;
int bank_to_fire, num_fired = 0;
int banks_fired; // used for multiplayer to help determine whether or not to send packet
banks_fired = 0; // used in multiplayer -- bitfield of banks that were fired
@@ -9953,9 +10109,9 @@ int ship_fire_primary(object * obj, int stream_weapons, int force)
bank_to_fire = (swp->current_primary_bank+i) % swp->num_primary_banks;
weapon = swp->primary_bank_weapons[bank_to_fire];
Assert( weapon >= 0 && weapon < MAX_WEAPON_TYPES );
if ( (weapon < 0) || (weapon >= MAX_WEAPON_TYPES) ) {
weapon_idx = swp->primary_bank_weapons[bank_to_fire];
Assert( weapon_idx >= 0 && weapon_idx < MAX_WEAPON_TYPES );
if ( (weapon_idx < 0) || (weapon_idx >= MAX_WEAPON_TYPES) ) {
Int3(); // why would a ship try to fire a weapon that doesn't exist?
continue;
}
@@ -9967,7 +10123,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force)
continue;
}
weapon_info* winfo_p = &Weapon_info[weapon];
weapon_info* winfo_p = &Weapon_info[weapon_idx];
if (needs_target_pos) {
target_velocity_vec = Objects[aip->target_objnum].phys_info.vel;
@@ -10323,6 +10479,15 @@ int ship_fire_primary(object * obj, int stream_weapons, int force)
// Mark all these weapons as in the same group
int new_group_id = weapon_create_group_id();
vec3d total_impulse;
vec3d *firepoint_list;
size_t current_firepoint = 0;
if (winfo_p->wi_flags3 & WIF3_APPLY_RECOIL){
firepoint_list = new vec3d[numtimes * points];
vm_vec_zero(&total_impulse);
}
for ( w = 0; w < numtimes; w++ ) {
polymodel *weapon_model = NULL;
if(winfo_p->external_model_num >= 0)
@@ -10435,9 +10600,20 @@ int ship_fire_primary(object * obj, int stream_weapons, int force)
firing_orient = obj->orient;
}
if (winfo_p->wi_flags3 & WIF3_APPLY_RECOIL){ // Function to add recoil functionality - DahBlount
vec3d local_impulse = firing_orient.vec.fvec;
float recoil_force = (winfo_p->mass * winfo_p->max_speed * winfo_p->recoil_modifier * sip->ship_recoil_modifier);
firepoint_list[current_firepoint++] = firing_pos;
vm_vec_scale(&local_impulse, (-1 * recoil_force));
vm_vec_add2(&total_impulse, &local_impulse);
}
// create the weapon -- the network signature for multiplayer is created inside
// of weapon_create
weapon_objnum = weapon_create( &firing_pos, &firing_orient, weapon, OBJ_INDEX(obj), new_group_id,
weapon_objnum = weapon_create( &firing_pos, &firing_orient, weapon_idx, OBJ_INDEX(obj), new_group_id,
0, 0, swp->primary_bank_fof_cooldown[bank_to_fire] );
winfo_p = &Weapon_info[Weapons[Objects[weapon_objnum].instance].weapon_info_index];
has_fired = true;
@@ -10482,7 +10658,7 @@ int ship_fire_primary(object * obj, int stream_weapons, int force)
// create the muzzle flash effect
if ( (obj != Player_obj) || (sip->flags2 & SIF2_SHOW_SHIP_MODEL) || (Viewer_mode) ) {
// show the flash only if in not cockpit view, or if "show ship" flag is set
shipfx_flash_create( obj, sip->model_num, &pnt, &obj->orient.vec.fvec, 1, weapon );
shipfx_flash_create( obj, sip->model_num, &pnt, &obj->orient.vec.fvec, 1, weapon_idx );
}
// maybe shudder the ship - if its me
@@ -10498,6 +10674,14 @@ int ship_fire_primary(object * obj, int stream_weapons, int force)
}
swp->external_model_fp_counter[bank_to_fire]++;
}
if (winfo_p->wi_flags3 & WIF3_APPLY_RECOIL){
vec3d avg_firepoint;
vm_vec_avg_n(&avg_firepoint, current_firepoint, firepoint_list);
ship_apply_whack(&total_impulse, &avg_firepoint, obj);
delete[] firepoint_list;
}
}
CLAMP(shipp->weapon_energy, 0.0f, sip->max_weapon_reserve);
@@ -10842,7 +11026,7 @@ extern void ai_maybe_announce_shockwave_weapon(object *firing_objp, int weapon_i
// need to avoid firing when normally called
int ship_fire_secondary( object *obj, int allow_swarm )
{
int n, weapon, j, bank, bank_adjusted, starting_bank_count = -1, num_fired;
int n, weapon_idx, j, bank, bank_adjusted, starting_bank_count = -1, num_fired;
ushort starting_sig = 0;
ship *shipp;
ship_weapon *swp;
@@ -10923,12 +11107,12 @@ int ship_fire_secondary( object *obj, int allow_swarm )
return 0;
}
weapon = swp->secondary_bank_weapons[bank];
weapon_idx = swp->secondary_bank_weapons[bank];
Assert( (swp->secondary_bank_weapons[bank] >= 0) && (swp->secondary_bank_weapons[bank] < MAX_WEAPON_TYPES) );
if((swp->secondary_bank_weapons[bank] < 0) || (swp->secondary_bank_weapons[bank] >= MAX_WEAPON_TYPES)){
return 0;
}
wip = &Weapon_info[weapon];
wip = &Weapon_info[weapon_idx];
if ( MULTIPLAYER_MASTER ) {
starting_sig = multi_get_next_network_signature( MULTI_SIG_NON_PERMANENT );
@@ -11049,11 +11233,11 @@ int ship_fire_secondary( object *obj, int allow_swarm )
float t;
if (Weapon_info[weapon].burst_shots > swp->burst_counter[bank_adjusted]) {
t = Weapon_info[weapon].burst_delay;
if (Weapon_info[weapon_idx].burst_shots > swp->burst_counter[bank_adjusted]) {
t = Weapon_info[weapon_idx].burst_delay;
swp->burst_counter[bank_adjusted]++;
} else {
t = Weapon_info[weapon].fire_wait; // They can fire 5 times a second
t = Weapon_info[weapon_idx].fire_wait; // They can fire 5 times a second
swp->burst_counter[bank_adjusted] = 0;
}
swp->next_secondary_fire_stamp[bank] = timestamp((int) (t * 1000.0f));
@@ -11066,7 +11250,7 @@ int ship_fire_secondary( object *obj, int allow_swarm )
if ( obj == Player_obj )
if ( ship_maybe_play_secondary_fail_sound(wip) ) {
char missile_name[NAME_LENGTH];
strcpy_s(missile_name, Weapon_info[weapon].name);
strcpy_s(missile_name, Weapon_info[weapon_idx].name);
end_string_at_first_hash_symbol(missile_name);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Cannot fire %s due to weapons system damage", 489), missile_name);
}
@@ -11162,7 +11346,7 @@ int ship_fire_secondary( object *obj, int allow_swarm )
vm_vec_add(&firing_pos, &missile_point, &obj->pos);
if ( Game_mode & GM_MULTIPLAYER ) {
Assert( Weapon_info[weapon].subtype == WP_MISSILE );
Assert( Weapon_info[weapon_idx].subtype == WP_MISSILE );
}
matrix firing_orient;
@@ -11179,17 +11363,17 @@ int ship_fire_secondary( object *obj, int allow_swarm )
// create the weapon -- for multiplayer, the net_signature is assigned inside
// of weapon_create
weapon_num = weapon_create( &firing_pos, &firing_orient, weapon, OBJ_INDEX(obj), -1, aip->current_target_is_locked);
weapon_num = weapon_create( &firing_pos, &firing_orient, weapon_idx, OBJ_INDEX(obj), -1, aip->current_target_is_locked);
if (weapon_num >= 0) {
weapon = Weapons[Objects[weapon_num].instance].weapon_info_index;
weapon_idx = Weapons[Objects[weapon_num].instance].weapon_info_index;
weapon_set_tracking_info(weapon_num, OBJ_INDEX(obj), aip->target_objnum, aip->current_target_is_locked, aip->targeted_subsys);
has_fired = true;
// create the muzzle flash effect
if ( (obj != Player_obj) || (sip->flags2 & SIF2_SHOW_SHIP_MODEL) || (Viewer_mode) ) {
// show the flash only if in not cockpit view, or if "show ship" flag is set
shipfx_flash_create(obj, sip->model_num, &pnt, &obj->orient.vec.fvec, 0, weapon);
shipfx_flash_create(obj, sip->model_num, &pnt, &obj->orient.vec.fvec, 0, weapon_idx);
}
if((wip->wi_flags & WIF_SHUDDER) && (obj == Player_obj) && !(Game_mode & GM_STANDALONE_SERVER)){
@@ -11212,8 +11396,8 @@ int ship_fire_secondary( object *obj, int allow_swarm )
}
if ( obj == Player_obj ) {
if ( Weapon_info[weapon].launch_snd != -1 ) {
snd_play( &Snds[Weapon_info[weapon].launch_snd], 0.0f, 1.0f, SND_PRIORITY_MUST_PLAY );
if ( Weapon_info[weapon_idx].launch_snd != -1 ) {
snd_play( &Snds[Weapon_info[weapon_idx].launch_snd], 0.0f, 1.0f, SND_PRIORITY_MUST_PLAY );
swp = &Player_ship->weapons;
if (bank >= 0) {
wip = &Weapon_info[swp->secondary_bank_weapons[bank]];
@@ -11226,8 +11410,8 @@ int ship_fire_secondary( object *obj, int allow_swarm )
}
} else {
if ( Weapon_info[weapon].launch_snd != -1 ) {
snd_play_3d( &Snds[Weapon_info[weapon].launch_snd], &obj->pos, &View_position );
if ( Weapon_info[weapon_idx].launch_snd != -1 ) {
snd_play_3d( &Snds[Weapon_info[weapon_idx].launch_snd], &obj->pos, &View_position );
}
}
@@ -11262,7 +11446,7 @@ done_secondary:
}
// maybe announce a shockwave weapon
ai_maybe_announce_shockwave_weapon(obj, weapon);
ai_maybe_announce_shockwave_weapon(obj, weapon_idx);
}
// if we are out of ammo in this bank then don't carry over firing swarm/corkscrew
@@ -12591,7 +12775,7 @@ float ship_calculate_rearm_duration( object *objp )
//find out time to repair shields
if(sip->sup_shield_repair_rate > 0.0f)
shield_rep_time = (sp->ship_max_shield_strength - shield_get_strength(objp)) / (sp->ship_max_shield_strength * sip->sup_shield_repair_rate);
shield_rep_time = ((sp->ship_max_shield_strength * sp->max_shield_recharge) - shield_get_strength(objp)) / (sp->max_shield_recharge * sp->ship_max_shield_strength * sip->sup_shield_repair_rate);
max_hull_repair = sp->ship_max_hull_strength * (The_mission.support_ships.max_hull_repair_val * 0.01f);
if ((The_mission.flags & MISSION_FLAG_SUPPORT_REPAIRS_HULL) && (max_hull_repair > objp->hull_strength) && (sip->sup_hull_repair_rate > 0.0f))
@@ -12727,7 +12911,7 @@ int ship_do_rearm_frame( object *objp, float frametime )
if ( !(objp->flags & OF_NO_SHIELDS) )
{
shield_str = shield_get_strength(objp);
if ( shield_str < shipp->ship_max_shield_strength ) {
if ( shield_str < (shipp->ship_max_shield_strength * shipp->max_shield_recharge) ) {
if ( objp == Player_obj ) {
player_maybe_start_repair_sound();
}
@@ -15550,7 +15734,7 @@ void ship_page_in()
// Page in all the ship classes that are used on this level
int num_ship_types_used = 0;
int test_id = -1;
int test_id __attribute__((__unused__)) = -1;
memset( fireball_used, 0, sizeof(int) * MAX_FIREBALL_TYPES );
@@ -17723,6 +17907,8 @@ int ship_get_subobj_model_num(ship_info* sip, char* subobj_name)
void init_path_metadata(path_metadata& metadata)
{
vm_vec_zero(&metadata.departure_rvec);
metadata.arrive_speed_mult = FLT_MIN;
metadata.depart_speed_mult = FLT_MIN;
}
int ship_get_sound(object *objp, GameSoundsIndex id)
@@ -17768,29 +17954,29 @@ bool ship_has_sound(object *objp, GameSoundsIndex id)
/**
* Given a ship with bounding box and a point, find the closest point on the bbox
*
* @param ship_obj Object that has the bounding box (should be a ship)
* @param ship_objp Object that has the bounding box (should be a ship)
* @param start World position of the point being compared
* @param box_pt OUTPUT PARAMETER: closest point on the bbox to start
*
* @return point is inside bbox, TRUE/1
* @return point is outside bbox, FALSE/0
*/
int get_nearest_bbox_point(object *ship_obj, vec3d *start, vec3d *box_pt)
int get_nearest_bbox_point(object *ship_objp, vec3d *start, vec3d *box_pt)
{
vec3d temp, rf_start;
polymodel *pm;
pm = model_get(Ship_info[Ships[ship_obj->instance].ship_info_index].model_num);
pm = model_get(Ship_info[Ships[ship_objp->instance].ship_info_index].model_num);
// get start in ship rf
vm_vec_sub(&temp, start, &ship_obj->pos);
vm_vec_rotate(&rf_start, &temp, &ship_obj->orient);
vm_vec_sub(&temp, start, &ship_objp->pos);
vm_vec_rotate(&rf_start, &temp, &ship_objp->orient);
// find box_pt
int inside = project_point_onto_bbox(&pm->mins, &pm->maxs, &rf_start, &temp);
// get box_pt in world rf
vm_vec_unrotate(box_pt, &temp, &ship_obj->orient);
vm_vec_add2(box_pt, &ship_obj->pos);
vm_vec_unrotate(box_pt, &temp, &ship_objp->orient);
vm_vec_add2(box_pt, &ship_objp->pos);
return inside;
}
+23 -4
View File
@@ -424,7 +424,7 @@ typedef struct ship_flag_name {
int flag_list; // is this flag in the 1st or 2nd ship flags list?
} ship_flag_name;
#define MAX_SHIP_FLAG_NAMES 17
#define MAX_SHIP_FLAG_NAMES 18
extern ship_flag_name Ship_flag_names[];
// states for the flags variable within the ship structure
@@ -505,6 +505,7 @@ extern ship_flag_name Ship_flag_names[];
#define SF2_WEAPONS_LOCKED (1<<25) // Karajorma - Prevents the player from changing the weapons on the ship on the loadout screen
#define SF2_SHIP_SELECTIVE_LINKING (1<<26) // RSAXVC - Allow pilot to pick firing configuration
#define SF2_SCRAMBLE_MESSAGES (1<<27) // Goober5000 - all messages sent from this ship appear scrambled
#define SF2_NO_SECONDARY_LOCKON (1<<28) // zookeeper - secondary lock-on disabled
// If any of these bits in the ship->flags are set, ignore this ship when targeting
extern int TARGET_SHIP_IGNORE_FLAGS;
@@ -592,6 +593,8 @@ public:
float ship_max_shield_strength;
float ship_max_hull_strength;
float max_shield_recharge;
int ship_guardian_threshold; // Goober5000 - now also determines whether ship is guardian'd
@@ -928,6 +931,7 @@ extern int ship_find_exited_ship_by_signature( int signature);
#define SIF2_AUTO_SPREAD_SHIELDS (1 << 16) // zookeeper - auto spread shields
#define SIF2_DRAW_WEAPON_MODELS (1 << 17) // the ship draws weapon models of any sort (used to be a boolean)
#define SIF2_MODEL_POINT_SHIELDS (1 << 18) // zookeeper - uses model-defined shield points instead of quadrants
#define SIF2_LOCK_DETAIL_BOXES (1 << 19) // zookeeper - don't scale detail boxes or spheres based on detail settings
#define SIF_DEFAULT_VALUE 0
#define SIF2_DEFAULT_VALUE 0
@@ -1144,6 +1148,8 @@ typedef struct ship_collision_physics {
typedef struct path_metadata {
vec3d departure_rvec;
float arrive_speed_mult;
float depart_speed_mult;
} path_metadata;
// The real FreeSpace ship_info struct.
@@ -1175,6 +1181,7 @@ public:
char pof_file_hud[MAX_FILENAME_LEN]; // POF file to load for the HUD target box
int num_detail_levels; // number of detail levels for this ship
int detail_distance[MAX_SHIP_DETAIL_LEVELS]; // distance to change detail levels at
int collision_lod; // check for collisions using a LOD
int cockpit_model_num; // cockpit model
int model_num; // ship model
int model_num_hud; // model to use when rendering to the HUD (eg, mini supercap)
@@ -1293,14 +1300,20 @@ public:
bool draw_secondary_models[MAX_SHIP_SECONDARY_BANKS];
float weapon_model_draw_distance;
// Recoil modifier for the ship
float ship_recoil_modifier;
float max_hull_strength; // Max hull strength of this class of ship.
float max_shield_strength;
float auto_shield_spread;
bool auto_shield_spread_bypass;
int auto_shield_spread_from_lod;
float auto_shield_spread; // Thickness of the shield
bool auto_shield_spread_bypass; // Whether weapons fired up close can bypass shields
int auto_shield_spread_from_lod; // Which LOD to project the shield from
float auto_shield_spread_min_span; // Minimum distance weapons must travel until allowed to collide with the shield
int shield_point_augment_ctrls[4]; // Re-mapping of shield augmentation controls for model point shields
float max_shield_recharge;
float hull_repair_rate; //How much of the hull is repaired every second
float subsys_repair_rate; //How fast
@@ -1320,6 +1333,7 @@ public:
ubyte shield_icon_index; // index to locate ship-specific animation frames for the shield on HUD
char icon_filename[MAX_FILENAME_LEN]; // filename for icon that is displayed in ship selection
angles model_icon_angles; // angle from which the model icon should be rendered (if not 0,0,0)
char anim_filename[MAX_FILENAME_LEN]; // filename for animation that plays in ship selection
char overhead_filename[MAX_FILENAME_LEN]; // filename for animation that plays weapons loadout
int selection_effect;
@@ -1372,6 +1386,7 @@ public:
float thruster02_glow_len_factor;
float thruster_dist_rad_factor;
float thruster_dist_len_factor;
float thruster_glow_noise_mult;
bool draw_distortion;
@@ -1398,6 +1413,7 @@ public:
vec3d topdown_offset;
int engine_snd; // handle to engine sound for ship (-1 if no engine sound)
float min_engine_vol; // minimum volume modifier for engine sound when ship is stationary
int glide_start_snd; // handle to sound to play at the beginning of a glide maneuver (default is 0 for regular throttle down sound)
int glide_end_snd; // handle to sound to play at the end of a glide maneuver (default is 0 for regular throttle up sound)
@@ -1417,10 +1433,12 @@ public:
float minimum_convergence_distance;
float convergence_distance;
vec3d convergence_offset;
int autoaim_lock_snd, autoaim_lost_snd;
float emp_resistance_mod;
float piercing_damage_draw_limit;
int shield_impact_explosion_anim;
int damage_lightning_type;
@@ -1591,6 +1609,7 @@ extern void ship_cleanup(int shipnum, int cleanup_mode);
extern void ship_destroy_instantly(object *ship_obj, int shipnum);
extern void ship_actually_depart(int shipnum, int method = SHIP_DEPARTED_WARP);
extern bool in_autoaim_fov(ship *shipp, int bank_to_fire, object *obj);
extern int ship_fire_primary_debug(object *objp); // Fire the debug laser.
extern int ship_stop_fire_primary(object * obj);
extern int ship_fire_primary(object * objp, int stream_weapons, int force = 0);
+84 -84
View File
@@ -78,7 +78,7 @@ void shipfx_remove_submodel_ship_sparks(ship *shipp, int submodel_num)
*
* DKA: 5/26/99 make velocity of debris scale according to size of debris subobject (at least for large subobjects)
*/
void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, ship_subsys *subsys, vec3d *exp_center, float exp_mag)
void shipfx_subsystem_maybe_create_live_debris(object *ship_objp, ship *ship_p, ship_subsys *subsys, vec3d *exp_center, float exp_mag)
{
// initializations
polymodel *pm = model_get(Ship_info[ship_p->ship_info_index].model_num);
@@ -94,7 +94,7 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
return;
}
ship_model_start(ship_obj);
ship_model_start(ship_objp);
// copy angles
angles copy_angs = pm->submodel[submodel_num].angs;
@@ -111,10 +111,10 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
// get the rotvel
void model_get_rotating_submodel_axis(vec3d *model_axis, vec3d *world_axis, int modelnum, int submodel_num, object *obj);
model_get_rotating_submodel_axis(&model_axis, &world_axis, pm->id, submodel_num, ship_obj);
model_get_rotating_submodel_axis(&model_axis, &world_axis, pm->id, submodel_num, ship_objp);
vm_vec_copy_scale(&rotvel, &world_axis, sii->cur_turn_rate);
model_find_world_point(&world_axis_pt, &sii->pt_on_axis, pm->id, submodel_num, &ship_obj->orient, &ship_obj->pos);
model_find_world_point(&world_axis_pt, &sii->pt_on_axis, pm->id, submodel_num, &ship_objp->orient, &ship_objp->pos);
vm_quaternion_rotate(&m_rot, vm_vec_mag((vec3d*)&sii->angs), &model_axis);
} else {
@@ -131,27 +131,27 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
// get start world pos
vm_vec_zero(&start_world_pos);
model_find_world_point(&start_world_pos, &pm->submodel[live_debris_submodel].offset, pm->id, live_debris_submodel, &ship_obj->orient, &ship_obj->pos );
model_find_world_point(&start_world_pos, &pm->submodel[live_debris_submodel].offset, pm->id, live_debris_submodel, &ship_objp->orient, &ship_objp->pos );
// convert to model coord of underlying submodel
// set angle to zero
pm->submodel[submodel_num].angs = zero_angs;
world_find_model_point(&start_model_pos, &start_world_pos, pm, submodel_num, &ship_obj->orient, &ship_obj->pos);
world_find_model_point(&start_model_pos, &start_world_pos, pm, submodel_num, &ship_objp->orient, &ship_objp->pos);
// rotate from submodel coord to world coords
// reset angle to current angle
pm->submodel[submodel_num].angs = copy_angs;
model_find_world_point(&end_world_pos, &start_model_pos, pm->id, submodel_num, &ship_obj->orient, &ship_obj->pos);
model_find_world_point(&end_world_pos, &start_model_pos, pm->id, submodel_num, &ship_objp->orient, &ship_objp->pos);
int fireball_type = fireball_ship_explosion_type(&Ship_info[ship_p->ship_info_index]);
if(fireball_type < 0) {
fireball_type = FIREBALL_EXPLOSION_MEDIUM;
}
// create fireball here.
fireball_create(&end_world_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_obj), pm->submodel[live_debris_submodel].rad);
fireball_create(&end_world_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_objp), pm->submodel[live_debris_submodel].rad);
// create debris
live_debris_obj = debris_create(ship_obj, pm->id, live_debris_submodel, &end_world_pos, exp_center, 1, exp_mag);
live_debris_obj = debris_create(ship_objp, pm->id, live_debris_submodel, &end_world_pos, exp_center, 1, exp_mag);
// only do if debris is created
if (live_debris_obj) {
@@ -177,7 +177,7 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
// Add radial velocity (at least as large as exp velocity)
vec3d temp_vel; // explosion velocity with ship_obj velocity removed
vm_vec_sub(&temp_vel, &live_debris_obj->phys_info.vel, &ship_obj->phys_info.vel);
vm_vec_sub(&temp_vel, &live_debris_obj->phys_info.vel, &ship_objp->phys_info.vel);
// find magnitudes of radial and temp velocity
float vel_mag = vm_vec_mag(&temp_vel);
@@ -202,8 +202,8 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
}
// scale up speed of debris if ship_obj > 125, but not for knossos
if (ship_obj->radius > 250 && !(Ship_info[ship_p->ship_info_index].flags & SIF_KNOSSOS_DEVICE)) {
vm_vec_scale(&live_debris_obj->phys_info.vel, ship_obj->radius/250.0f);
if (ship_objp->radius > 250 && !(Ship_info[ship_p->ship_info_index].flags & SIF_KNOSSOS_DEVICE)) {
vm_vec_scale(&live_debris_obj->phys_info.vel, ship_objp->radius/250.0f);
}
}
@@ -211,7 +211,7 @@ void shipfx_subsystem_maybe_create_live_debris(object *ship_obj, ship *ship_p, s
}
}
ship_model_stop(ship_obj);
ship_model_stop(ship_objp);
}
void set_ship_submodel_as_blown_off(ship *shipp, char *name)
@@ -239,12 +239,12 @@ void set_ship_submodel_as_blown_off(ship *shipp, char *name)
* Create debris for ship submodel which has live debris (at ship death)
* when ship submodel has not already been blown off (and hence liberated live debris)
*/
void shipfx_maybe_create_live_debris_at_ship_death( object *ship_obj )
void shipfx_maybe_create_live_debris_at_ship_death( object *ship_objp )
{
// if ship has live debris, detonate that subsystem now
// search for any live debris
ship *shipp = &Ships[ship_obj->instance];
ship *shipp = &Ships[ship_objp->instance];
polymodel *pm = model_get(Ship_info[shipp->ship_info_index].model_num);
// no subsystems -> no live debris.
@@ -263,7 +263,7 @@ void shipfx_maybe_create_live_debris_at_ship_death( object *ship_obj )
Assert(parent != -1);
// set model values only once (esp blown off)
ship_model_start(ship_obj);
ship_model_start(ship_objp);
// check if already blown off (ship model set)
if ( !pm->submodel[parent].blown_off ) {
@@ -281,14 +281,14 @@ void shipfx_maybe_create_live_debris_at_ship_death( object *ship_obj )
if (pss != NULL) {
if (pss->system_info != NULL) {
vec3d exp_center, tmp = ZERO_VECTOR;
model_find_world_point(&exp_center, &tmp, pm->id, parent, &ship_obj->orient, &ship_obj->pos );
model_find_world_point(&exp_center, &tmp, pm->id, parent, &ship_objp->orient, &ship_objp->pos );
// if not blown off, blow it off
shipfx_subsystem_maybe_create_live_debris(ship_obj, shipp, pss, &exp_center, 3.0f);
shipfx_subsystem_maybe_create_live_debris(ship_objp, shipp, pss, &exp_center, 3.0f);
// now set subsystem as blown off, so we only get one copy
pm->submodel[parent].blown_off = 1;
set_ship_submodel_as_blown_off(&Ships[ship_obj->instance], pss->system_info->subobj_name);
set_ship_submodel_as_blown_off(&Ships[ship_objp->instance], pss->system_info->subobj_name);
}
}
}
@@ -296,36 +296,36 @@ void shipfx_maybe_create_live_debris_at_ship_death( object *ship_obj )
}
// clean up
ship_model_stop(ship_obj);
ship_model_stop(ship_objp);
}
void shipfx_blow_off_subsystem(object *ship_obj,ship *ship_p,ship_subsys *subsys, vec3d *exp_center, bool no_explosion)
void shipfx_blow_off_subsystem(object *ship_objp, ship *ship_p,ship_subsys *subsys, vec3d *exp_center, bool no_explosion)
{
vec3d subobj_pos;
int model_num = Ship_info[ship_p->ship_info_index].model_num;
model_subsystem *psub = subsys->system_info;
get_subsystem_world_pos(ship_obj, subsys, &subobj_pos);
get_subsystem_world_pos(ship_objp, subsys, &subobj_pos);
// get rid of sparks on submodel that is destroyed
shipfx_remove_submodel_ship_sparks(ship_p, psub->subobj_num);
// create debris shards
if (!(subsys->flags & SSF_VANISHED) && !no_explosion) {
shipfx_blow_up_model(ship_obj, model_num, psub->subobj_num, 50, &subobj_pos );
shipfx_blow_up_model(ship_objp, model_num, psub->subobj_num, 50, &subobj_pos );
// create live debris objects, if any
// TODO: some MULITPLAYER implcations here!!
shipfx_subsystem_maybe_create_live_debris(ship_obj, ship_p, subsys, exp_center, 1.0f);
shipfx_subsystem_maybe_create_live_debris(ship_objp, ship_p, subsys, exp_center, 1.0f);
int fireball_type = fireball_ship_explosion_type(&Ship_info[ship_p->ship_info_index]);
if(fireball_type < 0) {
fireball_type = FIREBALL_EXPLOSION_MEDIUM;
}
// create first fireball
fireball_create( &subobj_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_obj), psub->radius );
fireball_create( &subobj_pos, fireball_type, FIREBALL_MEDIUM_EXPLOSION, OBJ_INDEX(ship_objp), psub->radius );
}
}
@@ -1687,29 +1687,29 @@ static int get_split_ship()
}
static void maybe_fireball_wipe(clip_ship* half_ship, int* sound_handle);
static void split_ship_init( ship* shipp, split_ship* split_ship )
static void split_ship_init( ship* shipp, split_ship* split_shipp )
{
object* parent_ship_obj = &Objects[shipp->objnum];
matrix* orient = &parent_ship_obj->orient;
for (int ii=0; ii<NUM_SUB_EXPL_HANDLES; ++ii) {
split_ship->sound_handle[ii] = shipp->sub_expl_sound_handle[ii];
split_shipp->sound_handle[ii] = shipp->sub_expl_sound_handle[ii];
}
// play 3d sound for shockwave explosion
snd_play_3d( &Snds[SND_SHOCKWAVE_EXPLODE], &parent_ship_obj->pos, &View_position, 0.0f, NULL, 0, 1.0f, SND_PRIORITY_SINGLE_INSTANCE, NULL, 3.0f );
// initialize both ships
split_ship->front_ship.parent_obj = parent_ship_obj;
split_ship->back_ship.parent_obj = parent_ship_obj;
split_ship->explosion_flash_timestamp = timestamp((int)(0.00075f*parent_ship_obj->radius));
split_ship->explosion_flash_started = 0;
split_ship->front_ship.orient = *orient;
split_ship->back_ship.orient = *orient;
split_ship->front_ship.next_fireball = timestamp_rand(0, 100);
split_ship->back_ship.next_fireball = timestamp_rand(0, 100);
split_shipp->front_ship.parent_obj = parent_ship_obj;
split_shipp->back_ship.parent_obj = parent_ship_obj;
split_shipp->explosion_flash_timestamp = timestamp((int)(0.00075f*parent_ship_obj->radius));
split_shipp->explosion_flash_started = 0;
split_shipp->front_ship.orient = *orient;
split_shipp->back_ship.orient = *orient;
split_shipp->front_ship.next_fireball = timestamp_rand(0, 100);
split_shipp->back_ship.next_fireball = timestamp_rand(0, 100);
split_ship->front_ship.clip_plane_norm = vmd_z_vector;
vm_vec_copy_scale(&split_ship->back_ship.clip_plane_norm, &vmd_z_vector, -1.0f);
split_shipp->front_ship.clip_plane_norm = vmd_z_vector;
vm_vec_copy_scale(&split_shipp->back_ship.clip_plane_norm, &vmd_z_vector, -1.0f);
// find the point at which the ship splits (relative to its pivot)
polymodel* pm = model_get(Ship_info[shipp->ship_info_index].model_num);
@@ -1721,18 +1721,18 @@ static void split_ship_init( ship* shipp, split_ship* split_ship )
init_clip_plane_dist = 0.5f * (0.5f - frand())*pm->core_radius;
}
split_ship->back_ship.cur_clip_plane_pt = init_clip_plane_dist;
split_ship->front_ship.cur_clip_plane_pt = init_clip_plane_dist;
split_shipp->back_ship.cur_clip_plane_pt = init_clip_plane_dist;
split_shipp->front_ship.cur_clip_plane_pt = init_clip_plane_dist;
float dist;
dist = (split_ship->front_ship.cur_clip_plane_pt+pm->maxs.xyz.z)/2.0f;
vm_vec_copy_scale(&split_ship->front_ship.local_pivot, &orient->vec.fvec, dist);
vm_vec_make(&split_ship->front_ship.model_center_disp_to_orig_center, 0.0f, 0.0f, -dist);
dist = (split_ship->back_ship.cur_clip_plane_pt +pm->mins.xyz.z)/2.0f;
vm_vec_copy_scale(&split_ship->back_ship.local_pivot, &orient->vec.fvec, dist);
vm_vec_make(&split_ship->back_ship.model_center_disp_to_orig_center, 0.0f, 0.0f, -dist);
vm_vec_add2(&split_ship->front_ship.local_pivot, &parent_ship_obj->pos );
vm_vec_add2(&split_ship->back_ship.local_pivot, &parent_ship_obj->pos );
dist = (split_shipp->front_ship.cur_clip_plane_pt+pm->maxs.xyz.z)/2.0f;
vm_vec_copy_scale(&split_shipp->front_ship.local_pivot, &orient->vec.fvec, dist);
vm_vec_make(&split_shipp->front_ship.model_center_disp_to_orig_center, 0.0f, 0.0f, -dist);
dist = (split_shipp->back_ship.cur_clip_plane_pt +pm->mins.xyz.z)/2.0f;
vm_vec_copy_scale(&split_shipp->back_ship.local_pivot, &orient->vec.fvec, dist);
vm_vec_make(&split_shipp->back_ship.model_center_disp_to_orig_center, 0.0f, 0.0f, -dist);
vm_vec_add2(&split_shipp->front_ship.local_pivot, &parent_ship_obj->pos );
vm_vec_add2(&split_shipp->back_ship.local_pivot, &parent_ship_obj->pos );
// find which debris pieces are in the front and back split ships
for (int i=0; i<pm->num_debris_objects; i++ ) {
@@ -1742,30 +1742,30 @@ static void split_ship_init( ship* shipp, split_ship* split_ship )
// tmp is world position, temp_pos is world_pivot, tmp1 is offset from world_pivot (in ship local coord)
model_find_world_point(&tmp, &tmp1, pm->id, -1, &vmd_identity_matrix, &temp_pos );
if (tmp.xyz.z > init_clip_plane_dist) {
split_ship->front_ship.draw_debris[i] = DEBRIS_DRAW;
split_ship->back_ship.draw_debris[i] = DEBRIS_NONE;
split_shipp->front_ship.draw_debris[i] = DEBRIS_DRAW;
split_shipp->back_ship.draw_debris[i] = DEBRIS_NONE;
} else {
split_ship->front_ship.draw_debris[i] = DEBRIS_NONE;
split_ship->back_ship.draw_debris[i] = DEBRIS_DRAW;
split_shipp->front_ship.draw_debris[i] = DEBRIS_NONE;
split_shipp->back_ship.draw_debris[i] = DEBRIS_DRAW;
}
}
// set up physics
physics_init( &split_ship->front_ship.phys_info );
physics_init( &split_ship->back_ship.phys_info );
split_ship->front_ship.phys_info.flags |= (PF_ACCELERATES | PF_DEAD_DAMP);
split_ship->back_ship.phys_info.flags |= (PF_ACCELERATES | PF_DEAD_DAMP);
split_ship->front_ship.phys_info.side_slip_time_const = 10000.0f;
split_ship->back_ship.phys_info.side_slip_time_const = 10000.0f;
split_ship->front_ship.phys_info.rotdamp = 10000.0f;
split_ship->back_ship.phys_info.rotdamp = 10000.0f;
physics_init( &split_shipp->front_ship.phys_info );
physics_init( &split_shipp->back_ship.phys_info );
split_shipp->front_ship.phys_info.flags |= (PF_ACCELERATES | PF_DEAD_DAMP);
split_shipp->back_ship.phys_info.flags |= (PF_ACCELERATES | PF_DEAD_DAMP);
split_shipp->front_ship.phys_info.side_slip_time_const = 10000.0f;
split_shipp->back_ship.phys_info.side_slip_time_const = 10000.0f;
split_shipp->front_ship.phys_info.rotdamp = 10000.0f;
split_shipp->back_ship.phys_info.rotdamp = 10000.0f;
// set up explosion vel and relative velocities (assuming mass depends on length)
float front_length = pm->maxs.xyz.z - split_ship->front_ship.cur_clip_plane_pt;
float back_length = split_ship->back_ship.cur_clip_plane_pt - pm->mins.xyz.z;
float front_length = pm->maxs.xyz.z - split_shipp->front_ship.cur_clip_plane_pt;
float back_length = split_shipp->back_ship.cur_clip_plane_pt - pm->mins.xyz.z;
float ship_length = front_length + back_length;
split_ship->front_ship.length_left = front_length;
split_ship->back_ship.length_left = back_length;
split_shipp->front_ship.length_left = front_length;
split_shipp->back_ship.length_left = back_length;
float expl_length_scale = (ship_length - 200.0f) / 2000.0f;
// s_r_f effects speed of "wipe" and rotvel
@@ -1773,8 +1773,8 @@ static void split_ship_init( ship* shipp, split_ship* split_ship )
float explosion_time = (3.0f + expl_length_scale + (frand()-0.5f)) * speed_reduction_factor;
float long_length = MAX(front_length, back_length);
float expl_vel = long_length / explosion_time;
split_ship->front_ship.explosion_vel = expl_vel;
split_ship->back_ship.explosion_vel = -expl_vel;
split_shipp->front_ship.explosion_vel = expl_vel;
split_shipp->back_ship.explosion_vel = -expl_vel;
float rel_vel = (0.6f + 0.2f*frand()) * expl_vel * speed_reduction_factor;
float front_vel = rel_vel * back_length / ship_length;
@@ -1786,26 +1786,26 @@ static void split_ship_init( ship* shipp, split_ship* split_ship )
rotvel.xyz.z = 0.0f;
vm_vec_normalize(&rotvel);
vm_vec_scale(&rotvel, 0.15f / speed_reduction_factor);
split_ship->front_ship.phys_info.rotvel = rotvel;
vm_vec_copy_scale(&split_ship->back_ship.phys_info.rotvel, &rotvel, -(front_length*front_length)/(back_length*back_length));
split_ship->front_ship.phys_info.rotvel.xyz.z = parent_ship_obj->phys_info.rotvel.xyz.z;
split_ship->back_ship.phys_info.rotvel.xyz.z = parent_ship_obj->phys_info.rotvel.xyz.z;
split_shipp->front_ship.phys_info.rotvel = rotvel;
vm_vec_copy_scale(&split_shipp->back_ship.phys_info.rotvel, &rotvel, -(front_length*front_length)/(back_length*back_length));
split_shipp->front_ship.phys_info.rotvel.xyz.z = parent_ship_obj->phys_info.rotvel.xyz.z;
split_shipp->back_ship.phys_info.rotvel.xyz.z = parent_ship_obj->phys_info.rotvel.xyz.z;
// modify vel of each split ship based on rotvel of parent ship obj
vec3d temp_rotvel = parent_ship_obj->phys_info.rotvel;
temp_rotvel.xyz.z = 0.0f;
vec3d vel_from_rotvel;
vm_vec_crossprod(&vel_from_rotvel, &temp_rotvel, &split_ship->front_ship.local_pivot);
vm_vec_crossprod(&vel_from_rotvel, &temp_rotvel, &split_ship->back_ship.local_pivot);
vm_vec_crossprod(&vel_from_rotvel, &temp_rotvel, &split_shipp->front_ship.local_pivot);
vm_vec_crossprod(&vel_from_rotvel, &temp_rotvel, &split_shipp->back_ship.local_pivot);
// set up velocity and make initial fireballs and particles
split_ship->front_ship.phys_info.vel = parent_ship_obj->phys_info.vel;
split_ship->back_ship.phys_info.vel = parent_ship_obj->phys_info.vel;
maybe_fireball_wipe(&split_ship->front_ship, (int*)&split_ship->sound_handle);
maybe_fireball_wipe(&split_ship->back_ship, (int*)&split_ship->sound_handle);
vm_vec_scale_add2(&split_ship->front_ship.phys_info.vel, &orient->vec.fvec, front_vel);
vm_vec_scale_add2(&split_ship->back_ship.phys_info.vel, &orient->vec.fvec, back_vel);
split_shipp->front_ship.phys_info.vel = parent_ship_obj->phys_info.vel;
split_shipp->back_ship.phys_info.vel = parent_ship_obj->phys_info.vel;
maybe_fireball_wipe(&split_shipp->front_ship, (int*)&split_shipp->sound_handle);
maybe_fireball_wipe(&split_shipp->back_ship, (int*)&split_shipp->sound_handle);
vm_vec_scale_add2(&split_shipp->front_ship.phys_info.vel, &orient->vec.fvec, front_vel);
vm_vec_scale_add2(&split_shipp->back_ship.phys_info.vel, &orient->vec.fvec, back_vel);
// HANDLE LIVE DEBRIS - blow off if not already gone
shipfx_maybe_create_live_debris_at_ship_death( parent_ship_obj );
@@ -1930,7 +1930,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
if(db == NULL || shipp == NULL)
return;
object *ship_obj = &Objects[shipp->objnum];
object *ship_objp = &Objects[shipp->objnum];
physics_info *pi = &Objects[db->objnum].phys_info;
ship_info *sip = &Ship_info[shipp->ship_info_index];
@@ -1945,7 +1945,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
}
else
{
vm_vec_copy_scale(&pi->vel, &ship_obj->orient.vec.fvec, debris_speed);
vm_vec_copy_scale(&pi->vel, &ship_objp->orient.vec.fvec, debris_speed);
}
}
else if(sip->debris_min_speed >= 0.0f)
@@ -1959,7 +1959,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
}
else
{
vm_vec_copy_scale(&pi->vel, &ship_obj->orient.vec.fvec, sip->debris_min_speed);
vm_vec_copy_scale(&pi->vel, &ship_objp->orient.vec.fvec, sip->debris_min_speed);
}
}
}
@@ -1974,7 +1974,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
}
else
{
vm_vec_copy_scale(&pi->vel, &ship_obj->orient.vec.fvec, sip->debris_max_speed);
vm_vec_copy_scale(&pi->vel, &ship_objp->orient.vec.fvec, sip->debris_max_speed);
}
}
}
@@ -1991,7 +1991,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
}
else
{
vm_vec_copy_scale(&pi->rotvel, &ship_obj->orient.vec.uvec, debris_rotspeed);
vm_vec_copy_scale(&pi->rotvel, &ship_objp->orient.vec.uvec, debris_rotspeed);
}
}
else if(sip->debris_min_rotspeed >= 0.0f)
@@ -2005,7 +2005,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
}
else
{
vm_vec_copy_scale(&pi->rotvel, &ship_obj->orient.vec.uvec, sip->debris_min_rotspeed);
vm_vec_copy_scale(&pi->rotvel, &ship_objp->orient.vec.uvec, sip->debris_min_rotspeed);
}
}
}
@@ -2021,7 +2021,7 @@ void shipfx_debris_limit_speed(debris *db, ship *shipp)
}
else
{
vm_vec_copy_scale(&pi->rotvel, &ship_obj->orient.vec.uvec, sip->debris_max_rotspeed);
vm_vec_copy_scale(&pi->rotvel, &ship_objp->orient.vec.uvec, sip->debris_max_rotspeed);
}
}
}
+64 -64
View File
@@ -1660,12 +1660,12 @@ int ds_get_channel(int sig)
/**
* @todo Documentation
*/
int ds_is_channel_playing(int channel)
int ds_is_channel_playing(int channel_id)
{
if ( Channels[channel].source_id != 0 ) {
if ( Channels[channel_id].source_id != 0 ) {
ALint status;
OpenAL_ErrorPrint( alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status) );
OpenAL_ErrorPrint( alGetSourcei(Channels[channel_id].source_id, AL_SOURCE_STATE, &status) );
return (status == AL_PLAYING);
}
@@ -1676,10 +1676,10 @@ int ds_is_channel_playing(int channel)
/**
* @todo Documentation
*/
void ds_stop_channel(int channel)
void ds_stop_channel(int channel_id)
{
if ( Channels[channel].source_id != 0 ) {
OpenAL_ErrorPrint( alSourceStop(Channels[channel].source_id) );
if ( Channels[channel_id].source_id != 0 ) {
OpenAL_ErrorPrint( alSourceStop(Channels[channel_id].source_id) );
}
}
@@ -1701,13 +1701,13 @@ void ds_stop_channel_all()
* @brief Set the volume for a channel. The volume is expected to be in linear scale
* @details If the sound is a 3D sound buffer, this is like re-establishing the maximum volume.
*/
void ds_set_volume( int channel, float vol )
void ds_set_volume( int channel_id, float vol )
{
if ( (channel < 0) || (channel >= MAX_CHANNELS) ) {
if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
return;
}
ALuint source_id = Channels[channel].source_id;
ALuint source_id = Channels[channel_id].source_id;
if (source_id != 0) {
CAP(vol, 0.0f, 1.0f);
@@ -1718,39 +1718,39 @@ void ds_set_volume( int channel, float vol )
/**
* Set the pan for a channel. The pan is expected to be in DirectSound units
*/
void ds_set_pan( int channel, float pan )
void ds_set_pan( int channel_id, float pan )
{
if ( (channel < 0) || (channel >= MAX_CHANNELS) ) {
if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
return;
}
ALint state;
OpenAL_ErrorCheck( alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &state), return );
OpenAL_ErrorCheck( alGetSourcei(Channels[channel_id].source_id, AL_SOURCE_STATE, &state), return );
if (state == AL_PLAYING) {
//OpenAL_ErrorPrint( alSourcei(Channels[channel].source_id, AL_SOURCE_RELATIVE, AL_TRUE) );
OpenAL_ErrorPrint( alSource3f(Channels[channel].source_id, AL_POSITION, pan, 0.0f, 1.0f) );
//OpenAL_ErrorPrint( alSourcei(Channels[channel_id].source_id, AL_SOURCE_RELATIVE, AL_TRUE) );
OpenAL_ErrorPrint( alSource3f(Channels[channel_id].source_id, AL_POSITION, pan, 0.0f, 1.0f) );
}
}
/**
* Get the pitch of a channel
*/
int ds_get_pitch(int channel)
int ds_get_pitch(int channel_id)
{
ALint status;
ALfloat alpitch = 0;
int pitch;
if ( (channel < 0) || (channel >= MAX_CHANNELS) ) {
if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
return -1;
}
OpenAL_ErrorCheck( alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status), return -1 );
OpenAL_ErrorCheck( alGetSourcei(Channels[channel_id].source_id, AL_SOURCE_STATE, &status), return -1 );
if (status == AL_PLAYING) {
OpenAL_ErrorPrint( alGetSourcef(Channels[channel].source_id, AL_PITCH, &alpitch) );
OpenAL_ErrorPrint( alGetSourcef(Channels[channel_id].source_id, AL_PITCH, &alpitch) );
}
// convert OpenAL values to DirectSound values and return
@@ -1762,11 +1762,11 @@ int ds_get_pitch(int channel)
/**
* Set the pitch of a channel
*/
void ds_set_pitch(int channel, int pitch)
void ds_set_pitch(int channel_id, int pitch)
{
ALint status;
if ( (channel < 0) || (channel >= MAX_CHANNELS) ) {
if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
return;
}
@@ -1778,24 +1778,24 @@ void ds_set_pitch(int channel, int pitch)
pitch = MAX_PITCH;
}
OpenAL_ErrorCheck( alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status), return );
OpenAL_ErrorCheck( alGetSourcei(Channels[channel_id].source_id, AL_SOURCE_STATE, &status), return );
if (status == AL_PLAYING) {
ALfloat alpitch = log10f((float)pitch) - 2.0f;
OpenAL_ErrorPrint( alSourcef(Channels[channel].source_id, AL_PITCH, alpitch) );
OpenAL_ErrorPrint( alSourcef(Channels[channel_id].source_id, AL_PITCH, alpitch) );
}
}
/**
* @todo Documentation
*/
void ds_chg_loop_status(int channel, int loop)
void ds_chg_loop_status(int channel_id, int loop)
{
if ( (channel < 0) || (channel >= MAX_CHANNELS) ) {
if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
return;
}
ALuint source_id = Channels[channel].source_id;
ALuint source_id = Channels[channel_id].source_id;
OpenAL_ErrorPrint( alSourcei(source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE) );
}
@@ -1818,99 +1818,99 @@ void ds_chg_loop_status(int channel, int loop)
*/
int ds3d_play(int sid, int snd_id, vec3d *pos, vec3d *vel, float min, float max, int looping, float max_volume, float estimated_vol, int priority )
{
int channel;
int channel_id;
if (!ds_initialized) {
return -1;
}
channel = ds_get_free_channel(estimated_vol, snd_id, priority);
channel_id = ds_get_free_channel(estimated_vol, snd_id, priority);
if (channel < 0) {
if (channel_id < 0) {
return -1;
}
if ( Channels[channel].source_id == 0 ) {
if ( Channels[channel_id].source_id == 0 ) {
return -1;
}
// set up 3D sound data here
ds3d_update_buffer(channel, min, max, pos, vel);
ds3d_update_buffer(channel_id, min, max, pos, vel);
OpenAL_ErrorPrint( alSourcef(Channels[channel].source_id, AL_PITCH, 1.0f) );
OpenAL_ErrorPrint( alSourcef(Channels[channel_id].source_id, AL_PITCH, 1.0f) );
OpenAL_ErrorPrint( alSourcef(Channels[channel].source_id, AL_GAIN, max_volume) );
OpenAL_ErrorPrint( alSourcef(Channels[channel_id].source_id, AL_GAIN, max_volume) );
ALint status;
OpenAL_ErrorCheck( alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status), return -1 );
OpenAL_ErrorCheck( alGetSourcei(Channels[channel_id].source_id, AL_SOURCE_STATE, &status), return -1 );
if (status == AL_PLAYING) {
OpenAL_ErrorPrint( alSourceStop(Channels[channel].source_id) );
OpenAL_ErrorPrint( alSourceStop(Channels[channel_id].source_id) );
}
OpenAL_ErrorCheck( alSourcei(Channels[channel].source_id, AL_BUFFER, sound_buffers[sid].buf_id), return -1 );
OpenAL_ErrorCheck( alSourcei(Channels[channel_id].source_id, AL_BUFFER, sound_buffers[sid].buf_id), return -1 );
if (Ds_eax_inited) {
OpenAL_ErrorPrint( alSource3i(Channels[channel].source_id, AL_AUXILIARY_SEND_FILTER, AL_EFX_aux_id, 0, AL_FILTER_NULL) );
OpenAL_ErrorPrint( alSource3i(Channels[channel_id].source_id, AL_AUXILIARY_SEND_FILTER, AL_EFX_aux_id, 0, AL_FILTER_NULL) );
}
OpenAL_ErrorPrint( alSourcei(Channels[channel].source_id, AL_SOURCE_RELATIVE, AL_FALSE) );
OpenAL_ErrorPrint( alSourcei(Channels[channel_id].source_id, AL_SOURCE_RELATIVE, AL_FALSE) );
OpenAL_ErrorPrint( alSourcei(Channels[channel].source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE) );
OpenAL_ErrorPrint( alSourcei(Channels[channel_id].source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE) );
OpenAL_ErrorPrint( alSourcePlay(Channels[channel].source_id) );
OpenAL_ErrorPrint( alSourcePlay(Channels[channel_id].source_id) );
sound_buffers[sid].channel_id = channel;
sound_buffers[sid].channel_id = channel_id;
Channels[channel].sid = sid;
Channels[channel].snd_id = snd_id;
Channels[channel].sig = channel_next_sig++;
Channels[channel].last_position = 0;
Channels[channel].is_voice_msg = false;
Channels[channel].vol = max_volume;
Channels[channel].looping = looping;
Channels[channel].priority = priority;
Channels[channel_id].sid = sid;
Channels[channel_id].snd_id = snd_id;
Channels[channel_id].sig = channel_next_sig++;
Channels[channel_id].last_position = 0;
Channels[channel_id].is_voice_msg = false;
Channels[channel_id].vol = max_volume;
Channels[channel_id].looping = looping;
Channels[channel_id].priority = priority;
if (channel_next_sig < 0 ) {
channel_next_sig = 1;
}
return Channels[channel].sig;
return Channels[channel_id].sig;
}
/**
* @todo Documentation
*/
void ds_set_position(int channel, unsigned int offset)
void ds_set_position(int channel_id, unsigned int offset)
{
if ( (channel < 0) || (channel >= MAX_CHANNELS) ) {
if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
return;
}
OpenAL_ErrorPrint( alSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, offset) );
OpenAL_ErrorPrint( alSourcei(Channels[channel_id].source_id, AL_BYTE_OFFSET, offset) );
}
/**
* @todo Documentation
*/
unsigned int ds_get_play_position(int channel)
unsigned int ds_get_play_position(int channel_id)
{
if ( (channel < 0) || (channel >= MAX_CHANNELS) ) {
if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
return 0;
}
ALint pos = -1;
int sid = Channels[channel].sid;
int sid = Channels[channel_id].sid;
if ( (sid < 0) || ((size_t)sid >= sound_buffers.size()) ) {
return 0;
}
if (AL_play_position) {
OpenAL_ErrorPrint( alGetSourcei(Channels[channel].source_id, AL_BYTE_LOKI, &pos) );
OpenAL_ErrorPrint( alGetSourcei(Channels[channel_id].source_id, AL_BYTE_LOKI, &pos) );
if ( pos < 0 ) {
pos = 0;
@@ -1925,7 +1925,7 @@ unsigned int ds_get_play_position(int channel)
pos = (ALint)(pos * ((float)sound_buffers[sid].nbytes / size));
}
} else {
OpenAL_ErrorPrint( alGetSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, &pos) );
OpenAL_ErrorPrint( alGetSourcei(Channels[channel_id].source_id, AL_BYTE_OFFSET, &pos) );
if (pos < 0) {
pos = 0;
@@ -1938,7 +1938,7 @@ unsigned int ds_get_play_position(int channel)
/**
* @todo Documentation
*/
unsigned int ds_get_write_position(int channel)
unsigned int ds_get_write_position(int channel_id)
{
return 0;
}
@@ -1946,13 +1946,13 @@ unsigned int ds_get_write_position(int channel)
/**
* @todo Documentation
*/
int ds_get_channel_size(int channel)
int ds_get_channel_size(int channel_id)
{
if ( (channel < 0) || (channel >= MAX_CHANNELS) ) {
if ( (channel_id < 0) || (channel_id >= MAX_CHANNELS) ) {
return 0;
}
int sid = Channels[channel].sid;
int sid = Channels[channel_id].sid;
if ( (sid < 0) || ((size_t)sid >= sound_buffers.size()) ) {
return 0;
@@ -2408,10 +2408,10 @@ void ds_do_frame()
/**
* Given a valid channel return the sound id
*/
int ds_get_sound_id(int channel)
int ds_get_sound_id(int channel_id)
{
Assert( channel >= 0 );
Assert( channel_id >= 0 );
return Channels[channel].snd_id;
return Channels[channel_id].snd_id;
}
+3 -3
View File
@@ -32,18 +32,18 @@
// -1 => failure
//
//
int ds3d_update_buffer(int channel, float min, float max, vec3d *pos, vec3d *vel)
int ds3d_update_buffer(int channel_id, float min, float max, vec3d *pos, vec3d *vel)
{
if (Cmdline_no_3d_sound) {
nprintf(("Sound", "Aborting ds3d_update_buffer due to Cmdline_no_3d_sound..."));
return -1;
}
if (channel < 0) {
if (channel_id < 0) {
return 0;
}
ALuint source_id = Channels[channel].source_id;
ALuint source_id = Channels[channel_id].source_id;
ALfloat rolloff = 1.0f;
if (pos) {
+6 -4
View File
@@ -50,10 +50,12 @@ typedef struct sound {
SCP_vector<sound> Sounds;
int Sound_enabled = FALSE; // global flag to turn sound on/off
int Snd_sram; // mem (in bytes) used up by storing sounds in system memory
float Master_sound_volume = 1.0f; // range is 0 -> 1, used for non-music sound fx
float Master_voice_volume = 0.7f; // range is 0 -> 1, used for all voice playback
int Sound_enabled = FALSE; // global flag to turn sound on/off
int Snd_sram; // mem (in bytes) used up by storing sounds in system memory
float Default_sound_volume = 1.0f; // range is 0 -> 1, used for non-music sound fx
float Default_voice_volume = 0.7f; // range is 0 -> 1, used for all voice playback
float Master_sound_volume = Default_sound_volume;
float Master_voice_volume = Default_voice_volume;
unsigned int SND_ENV_DEFAULT = 0;
+2
View File
@@ -62,6 +62,8 @@ typedef struct sound_env
} sound_env;
extern int Sound_enabled;
extern float Default_sound_volume; // 0 -> 1.0
extern float Default_voice_volume; // 0 -> 1.0
extern float Master_sound_volume; // 0 -> 1.0
extern float Master_voice_volume; // 0 -> 1.0
extern int Snd_sram; // System memory consumed by sound data
+1 -1
View File
@@ -729,7 +729,7 @@ void shockwave_page_in()
} else if (Shockwave_info[i].model_id >= 0) {
// for a model we have to run model_load() on it again to make sure
// that it's ref_count is sane for this mission
int idx = model_load( Shockwave_info[i].filename, 0, NULL );
int idx __attribute__((__unused__)) = model_load( Shockwave_info[i].filename, 0, NULL );
Assert( idx == Shockwave_info[i].model_id );
model_page_in_textures( Shockwave_info[i].model_id );
+8 -1
View File
@@ -122,7 +122,7 @@ extern int Num_weapon_subtypes;
#define WIF3_TURRET_INTERCEPTABLE (1 << 5) // These two flags mark a weapon as being interceptable by the AI
#define WIF3_FIGHTER_INTERCEPTABLE (1 << 6) // (like WIF_BOMB), without forcing it to be tagetable -MageKing17
#define WIF3_AOE_ELECTRONICS (1 << 7) // Apply electronics effect across the weapon's entire area of effect instead of just on the impacted ship -MageKing17
#define WIF3_APPLY_RECOIL (1 << 8) // Apply recoil using weapon and ship info
#define WIF_HOMING (WIF_HOMING_HEAT | WIF_HOMING_ASPECT | WIF_HOMING_JAVELIN)
#define WIF_LOCKED_HOMING (WIF_HOMING_ASPECT | WIF_HOMING_JAVELIN)
@@ -141,6 +141,7 @@ extern int Num_weapon_subtypes;
#define WF_DESTROYED_BY_WEAPON (1<<6) // destroyed by damage from other weapon
#define WF_SPAWNED (1<<7) //Spawned from a spawning type weapon
#define WF_HOMING_UPDATE_NEEDED (1<<8) // this is a newly spawned homing weapon which needs to update client machines
#define WF_NO_HOMING (1<<9) // this weapon should ignore any homing behavior it'd usually have
// flags for setting burst fire
#define WBF_FAST_FIRING (1<<0) // burst is to use only the firewait to determine firing delays
@@ -416,6 +417,7 @@ typedef struct weapon_info {
int impact_weapon_expl_index; // Index into Weapon_expl_info of which ANI should play when this thing impacts something
float impact_explosion_radius; // How big the explosion should be
float shield_impact_explosion_radius; // How big the shield hit explosion should be
int dinky_impact_weapon_expl_index;
float dinky_impact_explosion_radius;
@@ -435,6 +437,9 @@ typedef struct weapon_info {
float emp_intensity; // intensity of the EMP effect
float emp_time; // time of the EMP effect
// Recoil effect
float recoil_modifier;
// Energy suck effect
float weapon_reduce; // how much energy removed from weapons systems
float afterburner_reduce; // how much energy removed from weapons systems
@@ -670,4 +675,6 @@ void weapon_pause_sounds();
// Unpauses all running weapon sounds
void weapon_unpause_sounds();
void shield_impact_explosion(vec3d *hitpos, object *objp, float radius, int idx);
#endif
+48 -2
View File
@@ -665,6 +665,8 @@ void parse_wi_flags(weapon_info *weaponp, int wi_flags, int wi_flags2, int wi_fl
weaponp->wi_flags3 |= WIF3_TURRET_INTERCEPTABLE;
else if (!stricmp(NOX("fighter interceptable"), weapon_strings[i]))
weaponp->wi_flags3 |= WIF3_FIGHTER_INTERCEPTABLE;
else if (!stricmp(NOX("apply recoil"), weapon_strings[i]))
weaponp->wi_flags3 |= WIF3_APPLY_RECOIL;
else
Warning(LOCATION, "Bogus string in weapon flags: %s\n", weapon_strings[i]);
}
@@ -940,6 +942,8 @@ void init_weapon_entry(int weap_info_index)
wip->impact_explosion_radius = 1.0f;
wip->impact_weapon_expl_index = -1;
wip->shield_impact_explosion_radius = 1.0f;
wip->dinky_impact_explosion_radius = 1.0f;
wip->dinky_impact_weapon_expl_index = -1;
@@ -958,6 +962,7 @@ void init_weapon_entry(int weap_info_index)
wip->emp_intensity = EMP_DEFAULT_INTENSITY;
wip->emp_time = EMP_DEFAULT_TIME; // Goober5000: <-- Look! I fixed a Volition bug! Gimme $5, Dave!
wip->recoil_modifier = 1.0f;
wip->weapon_reduce = ESUCK_DEFAULT_WEAPON_REDUCE;
wip->afterburner_reduce = ESUCK_DEFAULT_AFTERBURNER_REDUCE;
@@ -1911,6 +1916,12 @@ int parse_weapon(int subtype, bool replace)
if ( optional_string("$Impact Explosion Radius:") )
stuff_float(&wip->impact_explosion_radius);
if ( optional_string("$Shield Impact Explosion Radius:") ) {
stuff_float(&wip->shield_impact_explosion_radius);
} else if (first_time) {
wip->shield_impact_explosion_radius = wip->impact_explosion_radius;
}
if ( optional_string("$Dinky Impact Explosion:") ) {
stuff_string(fname, F_NAME, NAME_LENGTH);
@@ -1967,6 +1978,15 @@ int parse_weapon(int subtype, bool replace)
stuff_float(&wip->emp_time);
}
// This is an optional modifier for a weapon that uses the "apply recoil" flag. recoil_force in ship.cpp line 10445 is multiplied by this if defined.
if (optional_string("$Recoil Modifier:")){
if (!(wip->wi_flags3 & WIF3_APPLY_RECOIL)){
Warning(LOCATION, "$Recoil Modifier specified for weapon %s but this weapon does not have the \"apply recoil\" weapon flag set. Automatically setting the flag", wip->name);
wip->wi_flags3 |= WIF3_APPLY_RECOIL;
}
stuff_float(&wip->recoil_modifier);
}
// Energy suck optional stuff (if WIF_ENERGY_SUCK is not set, none of this matters anyway)
if( optional_string("$Leech Weapon:") ){
stuff_float(&wip->weapon_reduce);
@@ -4772,7 +4792,7 @@ void weapon_process_post(object * obj, float frame_time)
}
// a single player or multiplayer server function -- it affects actual weapon movement.
if (wip->wi_flags & WIF_HOMING) {
if (wip->wi_flags & WIF_HOMING && !(wp->weapon_flags & WF_NO_HOMING)) {
weapon_home(obj, num, frame_time);
// If this is a swarm type missile,
@@ -4825,7 +4845,14 @@ void weapon_process_post(object * obj, float frame_time)
//create the warphole
vm_vec_add2(&warpout,&obj->pos);
wp->lssm_warp_idx=fireball_create(&warpout, FIREBALL_WARP, FIREBALL_WARP_EFFECT, -1,obj->radius*1.5f,1,&vmd_zero_vector,wp->lssm_warp_time,0,&obj->orient);
wp->lssm_stage=2;
if (wp->lssm_warp_idx < 0) {
mprintf(("LSSM: Failed to create warp effect! Please report if this happens frequently.\n"));
// Abort warping
wp->lssm_stage = 0;
} else {
wp->lssm_stage = 2;
}
}
//its just entered subspace subspace. don't collide or render
@@ -4944,6 +4971,10 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o
wp = &Weapons[Objects[weapon_objnum].instance];
wip = &Weapon_info[wp->weapon_info_index];
if (wp->weapon_flags & WF_NO_HOMING) {
return;
}
if (parent_objnum >= 0) {
parent_objp = &Objects[parent_objnum];
Assert(parent_objp->type == OBJ_SHIP);
@@ -4951,6 +4982,16 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o
parent_objp = NULL;
}
if (parent_objp != NULL && (Ships[parent_objp->instance].flags2 & SF2_NO_SECONDARY_LOCKON)) {
wp->weapon_flags |= WF_NO_HOMING;
wp->homing_object = NULL;
wp->homing_subsys = NULL;
wp->target_num = -1;
wp->target_sig = -1;
return;
}
if ( parent_objp == NULL || Ships[parent_objp->instance].ai_index >= 0 ) {
int target_team = -1;
if ( target_objnum >= 0 ) {
@@ -7036,3 +7077,8 @@ void weapon_unpause_sounds()
// Pause all beam sounds
beam_unpause_sounds();
}
void shield_impact_explosion(vec3d *hitpos, object *objp, float radius, int idx) {
int expl_ani_handle = Weapon_explosions.GetAnim(idx, hitpos, radius);
particle_create( hitpos, &vmd_zero_vector, 0.0f, radius, PARTICLE_BITMAP_PERSISTENT, expl_ani_handle, -1.0f, objp );
}
+2 -2
View File
@@ -64,8 +64,8 @@
// don't verbose stub funtions unless we're debugging
#define STUB_FUNCTION nprintf(( "Warning", "STUB: %s in "__FILE__" at line %d, thread %d\n", __FUNCTION__, __LINE__, getpid() ))
#define DEBUGME(d1) nprintf(( "Warning", "DEBUGME: %s in "__FILE__" at line %d, msg \"%s\", thread %d\n", __FUNCTION__, __LINE__, d1, getpid() ))
#define STUB_FUNCTION nprintf(( "Warning", "STUB: %s in " __FILE__ " at line %d, thread %d\n", __FUNCTION__, __LINE__, getpid() ))
#define DEBUGME(d1) nprintf(( "Warning", "DEBUGME: %s in " __FILE__ " at line %d, msg \"%s\", thread %d\n", __FUNCTION__, __LINE__, d1, getpid() ))
#define _cdecl
+2
View File
@@ -39,6 +39,8 @@ AC_SUBST(LDFLAGS)
PKG_PROG_PKG_CONFIG()
dnl lets see if we support c++11
AX_CXX_COMPILE_STDCXX_11([noext], [optional])
dnl The configuration options
dnl -------------------------
+133
View File
@@ -0,0 +1,133 @@
# ============================================================================
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
# ============================================================================
#
# SYNOPSIS
#
# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
#
# DESCRIPTION
#
# Check for baseline language coverage in the compiler for the C++11
# standard; if necessary, add switches to CXXFLAGS to enable support.
#
# The first argument, if specified, indicates whether you insist on an
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
# -std=c++11). If neither is specified, you get whatever works, with
# preference for an extended mode.
#
# The second argument, if specified 'mandatory' or if left unspecified,
# indicates that baseline C++11 support is required and that the macro
# should error out if no mode with that support is found. If specified
# 'optional', then configuration proceeds regardless, after defining
# HAVE_CXX11 if and only if a supporting mode is found.
#
# LICENSE
#
# Copyright (c) 2008 Benjamin Kosnik <[email protected]>
# Copyright (c) 2012 Zack Weinberg <[email protected]>
# Copyright (c) 2013 Roy Stogner <[email protected]>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 3
m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [
template <typename T>
struct check
{
static_assert(sizeof(int) <= sizeof(T), "not big enough");
};
typedef check<check<bool>> right_angle_brackets;
int a;
decltype(a) b;
typedef check<int> check_type;
check_type c;
check_type&& cr = static_cast<check_type&&>(c);
auto d = a;
])
AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
m4_if([$1], [], [],
[$1], [ext], [],
[$1], [noext], [],
[m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
[$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
[$2], [optional], [ax_cxx_compile_cxx11_required=false],
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl
AC_LANG_PUSH([C++])dnl
ac_success=no
AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
ax_cv_cxx_compile_cxx11,
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[ax_cv_cxx_compile_cxx11=yes],
[ax_cv_cxx_compile_cxx11=no])])
if test x$ax_cv_cxx_compile_cxx11 = xyes; then
ac_success=yes
fi
m4_if([$1], [noext], [], [dnl
if test x$ac_success = xno; then
for switch in -std=gnu++11 -std=gnu++0x; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
$cachevar,
[ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXXFLAGS="$ac_save_CXXFLAGS"])
if eval test x\$$cachevar = xyes; then
CXXFLAGS="$CXXFLAGS $switch"
ac_success=yes
break
fi
done
fi])
m4_if([$1], [ext], [], [dnl
if test x$ac_success = xno; then
for switch in -std=c++11 -std=c++0x; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
$cachevar,
[ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXXFLAGS="$ac_save_CXXFLAGS"])
if eval test x\$$cachevar = xyes; then
CXXFLAGS="$CXXFLAGS $switch"
ac_success=yes
break
fi
done
fi])
AC_LANG_POP([C++])
if test x$ax_cxx_compile_cxx11_required = xtrue; then
if test x$ac_success = xno; then
AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
fi
else
if test x$ac_success = xno; then
HAVE_CXX11=0
AC_MSG_NOTICE([No compiler with C++11 support was found])
else
HAVE_CXX11=1
AC_DEFINE(HAVE_CXX11,1,
[define if the compiler supports basic C++11 syntax])
fi
AC_SUBST(HAVE_CXX11)
fi
])