mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
Compare commits
126
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f475ae983e | ||
|
|
3be57f609e | ||
|
|
fc66e2f78b | ||
|
|
1afadaa142 | ||
|
|
1583b74c9d | ||
|
|
e8ba07ee43 | ||
|
|
7f706d398f | ||
|
|
7b50be4afb | ||
|
|
f690e124d0 | ||
|
|
df6e87f552 | ||
|
|
45305bf78f | ||
|
|
e6f640c53d | ||
|
|
4f1d39ed0e | ||
|
|
a7570926c9 | ||
|
|
aa481d7463 | ||
|
|
e79afa5b65 | ||
|
|
b69a80db90 | ||
|
|
5f64b680f5 | ||
|
|
a3508be54a | ||
|
|
0fede5f475 | ||
|
|
a8c36b9654 | ||
|
|
8c98287b39 | ||
|
|
345fa9c3ac | ||
|
|
cf483e0237 | ||
|
|
f40710f500 | ||
|
|
9f162d813f | ||
|
|
3edee14eea | ||
|
|
82757763e6 | ||
|
|
91346a814d | ||
|
|
5f013ad41d | ||
|
|
00cd5490c4 | ||
|
|
a4542cf71b | ||
|
|
f4521da771 | ||
|
|
6ba0f3622a | ||
|
|
e3765e24e1 | ||
|
|
7171bf1005 | ||
|
|
b85ee3217d | ||
|
|
12f137c645 | ||
|
|
f0eb798f7e | ||
|
|
5c60351288 | ||
|
|
5895aca2c5 | ||
|
|
cfd2469f8b | ||
|
|
0094a5dba4 | ||
|
|
94e84fc9b8 | ||
|
|
35ad2c5cdc | ||
|
|
af7e0a700b | ||
|
|
8943449825 | ||
|
|
555488e0bb | ||
|
|
c6cf9da861 | ||
|
|
f11e9253b2 | ||
|
|
fac68e4838 | ||
|
|
17d8105c38 | ||
|
|
a31eed376c | ||
|
|
e8abd881d2 | ||
|
|
136b5c936d | ||
|
|
34855d000e | ||
|
|
b6eed01e41 | ||
|
|
9616fb4cd7 | ||
|
|
344d8ba217 | ||
|
|
7e5239aff0 | ||
|
|
09d5225883 | ||
|
|
7f3ba14cec | ||
|
|
850414b358 | ||
|
|
f18fa672f2 | ||
|
|
fcb62348b9 | ||
|
|
fbbb31bc49 | ||
|
|
4d0e574ba4 | ||
|
|
ce5b56fdf7 | ||
|
|
04de7f7498 | ||
|
|
46b2165312 | ||
|
|
4182951b19 | ||
|
|
cbd6f247d9 | ||
|
|
73facc313e | ||
|
|
d2e3094544 | ||
|
|
61512d5b8f | ||
|
|
2b42038c09 | ||
|
|
ad8f6ccda3 | ||
|
|
a201c9b3f3 | ||
|
|
7edde650a1 | ||
|
|
ae3b88f23b | ||
|
|
c86e58e5e8 | ||
|
|
f441432d57 | ||
|
|
417982862e | ||
|
|
158733df8f | ||
|
|
4b75870857 | ||
|
|
dbfe86f018 | ||
|
|
f7d95acec8 | ||
|
|
506686cfb7 | ||
|
|
8415a591e1 | ||
|
|
1f8644f059 | ||
|
|
f32f947b62 | ||
|
|
99ce717f7e | ||
|
|
28f32a2f6d | ||
|
|
3d5d730306 | ||
|
|
96426de56f | ||
|
|
b14b5e3622 | ||
|
|
35cd6ea336 | ||
|
|
3332870e9e | ||
|
|
944c4bb2f2 | ||
|
|
705faf4a78 | ||
|
|
614eda3b08 | ||
|
|
593cf6a533 | ||
|
|
17ddae5db4 | ||
|
|
d1b1eb65b6 | ||
|
|
43ee74a2e0 | ||
|
|
20d33ac699 | ||
|
|
1609e9211f | ||
|
|
c8c05e9d0b | ||
|
|
35130122e4 | ||
|
|
c1b549867a | ||
|
|
efea823ef1 | ||
|
|
91e375693c | ||
|
|
022aa38ad1 | ||
|
|
40419fb891 | ||
|
|
25d4a3b439 | ||
|
|
968e8d3d66 | ||
|
|
6610938b80 | ||
|
|
4b2691f572 | ||
|
|
0ac2532fe5 | ||
|
|
e42892cb90 | ||
|
|
0d14a559eb | ||
|
|
2a65fcb388 | ||
|
|
a02b9d953a | ||
|
|
53f8c36587 | ||
|
|
8323f5b4ad | ||
|
|
6ef349a6d4 |
No files matched your search
-175
@@ -712,178 +712,3 @@ int main ()
|
||||
AC_SUBST(THEORA_LIBS)
|
||||
rm -f conf.theoratest
|
||||
])
|
||||
|
||||
|
||||
dnl AM_PATH_OPENAL([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||
dnl Test for OpenAL, and define OPENAL_CFLAGS and OPENAL_LIBS
|
||||
dnl
|
||||
AC_DEFUN([AM_PATH_OPENAL],
|
||||
[dnl
|
||||
dnl Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(openal,[ --with-openal=PFX Prefix where OpenAL is installed (optional)], openal_prefix="$withval", openal_prefix="")
|
||||
AC_ARG_WITH(openal-libraries,[ --with-openal-libraries=DIR Directory where OpenAL library is installed (optional)], openal_libraries="$withval", openal_libraries="")
|
||||
AC_ARG_WITH(openal-includes,[ --with-openal-includes=DIR Directory where OpenAL header files are installed (optional)], openal_includes="$withval", openal_includes="")
|
||||
AC_ARG_ENABLE(openaltest, [ --disable-openaltest Do not try to compile and run a test OpenAL program],, enable_openaltest=yes)
|
||||
|
||||
if test "x$openal_libraries" != "x" ; then
|
||||
OPENAL_LIBS="-L$openal_libraries"
|
||||
elif test "x$openal_prefix" != "x" ; then
|
||||
OPENAL_LIBS="-L$openal_prefix/lib"
|
||||
elif test "x$prefix" != "xNONE"; then
|
||||
OPENAL_LIBS="-L$libdir"
|
||||
fi
|
||||
|
||||
OPENAL_LIBS="$OPENAL_LIBS -lopenal"
|
||||
|
||||
if test "x$openal_includes" != "x" ; then
|
||||
OPENAL_CFLAGS="-I$openal_includes"
|
||||
elif test "x$openal_prefix" != "x" ; then
|
||||
OPENAL_CFLAGS="-I$openal_prefix/include"
|
||||
elif test "x$prefix" != "xNONE"; then
|
||||
OPENAL_CFLAGS=""
|
||||
fi
|
||||
|
||||
|
||||
AC_MSG_CHECKING(for OpenAL)
|
||||
no_openal=""
|
||||
|
||||
|
||||
if test "x$enable_openaltest" = "xyes" ; then
|
||||
ac_save_CFLAGS="$CFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $OPENAL_CFLAGS"
|
||||
LIBS="$LIBS $OPENAL_LIBS"
|
||||
dnl
|
||||
dnl Now check if the installed OpenAL is sufficiently new.
|
||||
dnl
|
||||
rm -f conf.openaltest
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
int main ()
|
||||
{
|
||||
#ifdef AL_VERSION_1_1
|
||||
alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT");
|
||||
|
||||
system("touch conf.openaltest");
|
||||
return 0;
|
||||
#else
|
||||
printf("\n*** OpenAL version 1.1 or greater is required.\n");
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
],, no_openal=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
|
||||
if test "x$no_openal" = "x" ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test -f conf.openaltest ; then
|
||||
:
|
||||
else
|
||||
echo "*** Could not run OpenAL test program, checking why..."
|
||||
CFLAGS="$CFLAGS $OPENAL_CFLAGS"
|
||||
LIBS="$LIBS $OPENAL_LIBS"
|
||||
AC_TRY_LINK([
|
||||
#include <stdio.h>
|
||||
#include <AL/al.h>
|
||||
], [ return 0; ],
|
||||
[ echo "*** The test program compiled, but did not run. This usually means"
|
||||
echo "*** that the run-time linker is not finding OpenAL or finding the wrong"
|
||||
echo "*** version of OpenAL. If it is not finding OpenAL, you'll need to set your"
|
||||
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
|
||||
echo "*** to the installed location Also, make sure you have run ldconfig if that"
|
||||
echo "*** is required on your system"
|
||||
echo "***"
|
||||
echo "*** If you have an old version installed, it is best to remove it, although"
|
||||
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
|
||||
[ echo "*** The test program failed to compile or link. See the file config.log for the"
|
||||
echo "*** exact error that occured. This usually means OpenAL was incorrectly installed"
|
||||
echo "*** or that you have moved OpenAL since it was installed." ])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
OPENAL_CFLAGS=""
|
||||
OPENAL_LIBS=""
|
||||
ifelse([$2], , :, [$2])
|
||||
fi
|
||||
AC_SUBST(OPENAL_CFLAGS)
|
||||
AC_SUBST(OPENAL_LIBS)
|
||||
rm -f conf.openaltest
|
||||
])
|
||||
|
||||
dnl AM_PATH_OPENGL([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
|
||||
dnl Test for OpenGL, and define OPENGL_CFLAGS and OPENGL_LIBS
|
||||
dnl
|
||||
AC_DEFUN([AM_PATH_OPENGL],
|
||||
[dnl
|
||||
dnl Get the cflags and libraries
|
||||
dnl
|
||||
AC_ARG_WITH(opengl,[ --with-opengl=PFX Prefix where OpenGL is installed (optional)], opengl_prefix="$withval", opengl_prefix="")
|
||||
AC_ARG_WITH(opengl-libraries,[ --with-opengl-libraries=DIR Directory where OpenGL library is installed (optional)], opengl_libraries="$withval", opengl_libraries="")
|
||||
AC_ARG_WITH(opengl-includes,[ --with-opengl-includes=DIR Directory where OpenGL header files are installed (optional)], opengl_includes="$withval", opengl_includes="")
|
||||
AC_ARG_ENABLE(opengltest, [ --disable-opengltest Do not try to compile and run a test OpenGL program],, enable_opengltest=yes)
|
||||
|
||||
if test "x$opengl_libraries" != "x" ; then
|
||||
OPENGL_LIBS="-L$opengl_libraries"
|
||||
elif test "x$opengl_prefix" != "x" ; then
|
||||
OPENGL_LIBS="-L$opengl_prefix/lib"
|
||||
elif test "x$prefix" != "xNONE"; then
|
||||
OPENGL_LIBS="-L$libdir"
|
||||
fi
|
||||
|
||||
OPENGL_LIBS="$OPENGL_LIBS -lGL -lGLU"
|
||||
|
||||
if test "x$opengl_includes" != "x" ; then
|
||||
OPENGL_CFLAGS="-I$opengl_includes"
|
||||
elif test "x$opengl_prefix" != "x" ; then
|
||||
OPENGL_CFLAGS="-I$opengl_prefix/include"
|
||||
elif test "x$prefix" != "xNONE"; then
|
||||
OPENGL_CFLAGS=""
|
||||
fi
|
||||
|
||||
|
||||
no_opengl=""
|
||||
|
||||
|
||||
if test "x$enable_opengltest" = "xyes" ; then
|
||||
ac_save_CFLAGS="$CFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $OPENGL_CFLAGS"
|
||||
LIBS="$LIBS $OPENGL_LIBS"
|
||||
|
||||
AC_CHECK_LIB(GL, glPushMatrix,
|
||||
[AC_CHECK_HEADER(GL/gl.h,
|
||||
[AC_CHECK_LIB(GLU, gluPerspective,
|
||||
[AC_CHECK_HEADER(GL/glu.h, ,
|
||||
dnl NOTE: this is a failure
|
||||
no_opengl=yes
|
||||
)]
|
||||
)]
|
||||
)]
|
||||
)
|
||||
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
|
||||
if test "x$no_opengl" = "x" ; then
|
||||
ifelse([$1], , :, [$1])
|
||||
else
|
||||
OPENGL_CFLAGS=""
|
||||
OPENGL_LIBS=""
|
||||
ifelse([$2], , :, [$2])
|
||||
fi
|
||||
AC_SUBST(OPENGL_CFLAGS)
|
||||
AC_SUBST(OPENGL_LIBS)
|
||||
])
|
||||
+1
-1
@@ -88,7 +88,7 @@ char *ai_get_goal_ship_name(char *name, int *index)
|
||||
}
|
||||
|
||||
Assert(Total_goal_ship_names < MAX_GOAL_SHIP_NAMES);
|
||||
Assert(strlen(name) < NAME_LENGTH - 1);
|
||||
Assertion(strlen(name) < NAME_LENGTH - 1, "Ship name %s is too long. Needs to be 31 characters or less.", name);
|
||||
i = Total_goal_ship_names++;
|
||||
strcpy_s(Goal_ship_names[i], name);
|
||||
*index = i;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
struct ship_weapon;
|
||||
struct ship_subsys;
|
||||
struct object;
|
||||
struct ship_info;
|
||||
|
||||
#define AI_DEFAULT_CLASS 3 // default AI class for new ships (Fred)
|
||||
|
||||
@@ -639,6 +640,7 @@ extern ship_subsys *set_targeted_subsys(ai_info *aip, ship_subsys *new_subsys, i
|
||||
extern void ai_rearm_repair( object *objp, int docker_index, object *goal_objp, int dockee_index );
|
||||
extern void ai_add_rearm_goal( object *requester_objp, object *support_objp );
|
||||
extern void create_model_path(object *pl_objp, object *mobjp, int path_num, int subsys_path=0);
|
||||
extern int ai_find_goal_index( ai_goal* aigp, int mode, int submode = -1, int priority = -1 );
|
||||
|
||||
// Goober5000
|
||||
extern void ai_do_safety(object *objp);
|
||||
@@ -701,4 +703,8 @@ void init_aip_from_class_and_profile(ai_info *aip, ai_class *aicp, ai_profile_t
|
||||
|
||||
//SUSHI: Updating AI aim
|
||||
void ai_update_aim(ai_info *aip, object* En_Objp);
|
||||
|
||||
//SUSHI: Random evasive sidethrust
|
||||
void do_random_sidethrust(ai_info *aip, ship_info *sip);
|
||||
|
||||
#endif
|
||||
@@ -49,7 +49,6 @@ void set_flag(ai_profile_t *profile, char *name, int flag, int type)
|
||||
void parse_ai_profiles_tbl(char *filename)
|
||||
{
|
||||
int i, rval;
|
||||
bool no_create = false;
|
||||
char profile_name[NAME_LENGTH];
|
||||
ai_profile_t dummy_profile;
|
||||
char *saved_Mp = NULL;
|
||||
@@ -84,6 +83,7 @@ void parse_ai_profiles_tbl(char *filename)
|
||||
{
|
||||
ai_profile_t *profile = &dummy_profile;
|
||||
ai_profile_t *previous_profile = NULL;
|
||||
bool no_create = false;
|
||||
|
||||
// get the name
|
||||
required_string("$Profile Name:");
|
||||
@@ -393,6 +393,8 @@ void parse_ai_profiles_tbl(char *filename)
|
||||
|
||||
set_flag(profile, "$perform less checks for death screams:", AIPF2_PERFORM_LESS_SCREAM_CHECKS, AIP_FLAG2);
|
||||
|
||||
set_flag(profile, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2);
|
||||
|
||||
// if we've been through once already and are at the same place, force a move
|
||||
if ( saved_Mp && (saved_Mp == Mp) )
|
||||
Mp++;
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#define AIPF2_TURRETS_IGNORE_TARGET_RADIUS (1 << 0)
|
||||
#define AIPF2_NO_SPECIAL_PLAYER_AVOID (1 << 1)
|
||||
#define AIPF2_PERFORM_LESS_SCREAM_CHECKS (1 << 2)
|
||||
#define AIPF2_ALL_SHIPS_MANAGE_SHIELDS (1 << 3)
|
||||
|
||||
#define MAX_AI_PROFILES 5
|
||||
|
||||
|
||||
+15
-1
@@ -694,7 +694,7 @@ void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d *f
|
||||
ship_weapon *tswp = &temp_shipp->weapons;
|
||||
|
||||
if ( tswp->num_primary_banks > 0 ) {
|
||||
Assert(tswp->current_primary_bank < tswp->num_primary_banks);
|
||||
Assertion(tswp->current_primary_bank < tswp->num_primary_banks, "AI tried to select primary bank %d. Might be a model error\n", tswp->current_primary_bank);
|
||||
weapon_info *wip = &Weapon_info[tswp->primary_bank_weapons[tswp->current_primary_bank]];
|
||||
|
||||
if (dist_to_enemy < MIN((wip->max_speed * wip->lifetime), wip->weapon_range)){
|
||||
@@ -1640,6 +1640,20 @@ void ai_big_strafe()
|
||||
Int3(); // Illegal submode for AIM_STRAFE
|
||||
break;
|
||||
}
|
||||
|
||||
//Maybe apply random sidethrust, depending on the current submode
|
||||
//The following are valid targets for random sidethrust (circle strafe uses it too, but that is handled separately)
|
||||
if (aip->submode == AIS_STRAFE_ATTACK ||
|
||||
aip->submode == AIS_STRAFE_AVOID ||
|
||||
aip->submode == AIS_STRAFE_RETREAT1 ||
|
||||
aip->submode == AIS_STRAFE_RETREAT2 ||
|
||||
aip->submode == AIS_STRAFE_POSITION)
|
||||
{
|
||||
//Re-roll for random sidethrust every 2 seconds
|
||||
if (static_randf((Missiontime + static_rand(aip->shipnum)) >> 17) < aip->ai_random_sidethrust_percent) {
|
||||
do_random_sidethrust(aip, &Ship_info[Ships[Objects[aip->target_objnum].instance].ship_info_index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if Pl_objp should enter strafe mode (This is called from maybe_evade_dumbfire_weapon(), and the
|
||||
|
||||
+196
-422
@@ -304,6 +304,9 @@ typedef struct {
|
||||
// Move to a position relative to a dock bay using thrusters.
|
||||
float dock_orient_and_approach(object *docker_objp, int docker_index, object *dockee_objp, int dockee_index, int dock_mode, rotating_dockpoint_info *rdinfo = NULL);
|
||||
|
||||
// The object that is declared to be the leader of the group formation for
|
||||
// the "autopilot"
|
||||
object *Autopilot_flight_leader = NULL;
|
||||
|
||||
// ai_set_rearm_status takes a team (friendly, hostile, neutral) and a time. This function
|
||||
// sets the timestamp used to tell is it is a good time for this team to rearm. Once the timestamp
|
||||
@@ -766,6 +769,8 @@ void parse_ai_class()
|
||||
set_aic_flag(aicp, "$allow vertical dodge:", AIPF_ALLOW_VERTICAL_DODGE, AIP_FLAG);
|
||||
|
||||
set_aic_flag(aicp, "$no extra collision avoidance vs player:", AIPF2_NO_SPECIAL_PLAYER_AVOID, AIP_FLAG2);
|
||||
|
||||
set_aic_flag(aicp, "$all ships manage shields:", AIPF2_ALL_SHIPS_MANAGE_SHIELDS, AIP_FLAG2);
|
||||
}
|
||||
|
||||
void reset_ai_class_names()
|
||||
@@ -1311,40 +1316,6 @@ if (!((objp->type == OBJ_WEAPON) && (Weapon_info[Weapons[objp->instance].weapon_
|
||||
// If new target (objnum) is different than old target, reset target_time.
|
||||
int set_target_objnum(ai_info *aip, int objnum)
|
||||
{
|
||||
/*
|
||||
char old_name[32], new_name[32];
|
||||
|
||||
if (!timestamp_elapsed(aip->ok_to_target_timestamp))
|
||||
return aip->target_objnum;
|
||||
|
||||
if (Player_ship && (Ships[aip->shipnum].team == Player_ship->team)) {
|
||||
if (aip->target_objnum == -1)
|
||||
strcpy_s(old_name, "none");
|
||||
else
|
||||
strcpy_s(old_name, Ships[Objects[aip->target_objnum].instance].ship_name);
|
||||
|
||||
if (objnum == -1)
|
||||
strcpy_s(new_name, "none");
|
||||
else
|
||||
strcpy_s(new_name, Ships[Objects[objnum].instance].ship_name);
|
||||
|
||||
nprintf(("AI", "Ship %s changing target from %s to %s\n", Ships[aip->shipnum].ship_name, old_name, new_name));
|
||||
}
|
||||
*/
|
||||
|
||||
// AL 2-25-97: Ensure that a protected ship isn't being set as a target (for non-players only)
|
||||
/*
|
||||
if ( objnum >= 0 ) {
|
||||
if ( !(Objects[Ships[aip->shipnum].objnum].flags & OF_PLAYER_SHIP) ) {
|
||||
if ( Objects[objnum].flags & OF_PROTECTED ) {
|
||||
// AL 2-26-97: removing Int3() until issue with setting OF_PROTECTED in ai_set_attack_subsystem()
|
||||
//Int3(); // this should not happen
|
||||
return aip->target_objnum; // don't change targets
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if ((aip != Player_ai) && (!timestamp_elapsed(aip->ok_to_target_timestamp))) {
|
||||
return aip->target_objnum;
|
||||
}
|
||||
@@ -1446,7 +1417,6 @@ void adjust_accel_for_docking(ai_info *aip)
|
||||
|
||||
// make sure we at least some velocity
|
||||
if (ratio < 0.1f) {
|
||||
// Int3();
|
||||
ratio = 0.1f;
|
||||
}
|
||||
|
||||
@@ -1849,52 +1819,6 @@ float get_wing_lowest_max_speed(object *objp)
|
||||
return lowest_max_speed;
|
||||
}
|
||||
|
||||
/*
|
||||
// Tell everyone to ignore object objnum.
|
||||
void set_global_ignore_object(int objnum)
|
||||
{
|
||||
int i;
|
||||
|
||||
Assert(Objects[objnum].type == OBJ_SHIP);
|
||||
|
||||
nprintf(("AI", "Telling everyone to ignore object %s\n", Ships[Objects[objnum].instance].ship_name));
|
||||
|
||||
for (i=0; i<MAX_IGNORE_OBJECTS; i++) {
|
||||
if (Ignore_objects[i].objnum == -1) {
|
||||
Ignore_objects[i].objnum = objnum;
|
||||
Ignore_objects[i].signature = Objects[objnum].signature;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAX_IGNORE_OBJECTS) {
|
||||
// Couldn't find a free slot, but maybe one of these objects has died.
|
||||
for (i=0; i<MAX_IGNORE_OBJECTS; i++) {
|
||||
int o = Ignore_objects[i].objnum;
|
||||
if (Objects[o].type != OBJ_SHIP)
|
||||
break; // Not a ship, so use this slot.
|
||||
if (Objects[o].signature != Ignore_objects[i].signature)
|
||||
break; // Signatures don't match, so use this slot.
|
||||
}
|
||||
|
||||
if (i != MAX_IGNORE_OBJECTS) {
|
||||
Ignore_objects[i].objnum = objnum;
|
||||
Ignore_objects[i].signature = Objects[objnum].signature;
|
||||
} else {
|
||||
nprintf(("Warning", "Ignore_objects buffer full. Stealing a slot to ignore object #%i\n"));
|
||||
Int3();
|
||||
|
||||
int r;
|
||||
|
||||
r = objnum % MAX_IGNORE_OBJECTS;
|
||||
|
||||
Ignore_objects[r].objnum = objnum;
|
||||
Ignore_objects[r].signature = Objects[objnum].signature;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// Goober5000 - fixed up a bit
|
||||
// Determine if object objnum is supposed to be ignored by object with ai_info *aip.
|
||||
@@ -4174,13 +4098,13 @@ void ai_safety()
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// make Pl_objp fly tword a ship
|
||||
// Goal created by Kazan
|
||||
// code adapted from waypoints
|
||||
void ai_fly_to_ship()
|
||||
// make Pl_objp fly to its target's position
|
||||
// optionally returns true if Pl_objp (pl_done_p) has reached the target position (can be NULL)
|
||||
// optionally returns true if Pl_objp's (pl_treat_as_ship_p) fly to order was issued to him directly,
|
||||
// or if the order was issued to his wing (returns false) (can be NULL, and result is only
|
||||
// valid if Pl_done_p was not NULL and was set true by function.
|
||||
void ai_fly_to_target_position(vec3d* target_pos, bool* pl_done_p=NULL, bool* pl_treat_as_ship_p=NULL)
|
||||
{
|
||||
|
||||
vec3d *target_pos;
|
||||
float dot, dist_to_goal, speed;
|
||||
ship *shipp = &Ships[Pl_objp->instance];
|
||||
ship_info *sip = &Ship_info[shipp->ship_info_index];
|
||||
@@ -4190,30 +4114,25 @@ void ai_fly_to_ship()
|
||||
float prev_dot_to_goal;
|
||||
vec3d temp_vec;
|
||||
vec3d *slop_vec;
|
||||
int target_object=-1;
|
||||
int j;
|
||||
|
||||
Assert( target_pos != NULL );
|
||||
|
||||
if ( pl_done_p != NULL ) {
|
||||
// initialize this to false now incase we leave early so that that
|
||||
// the caller of this function doesn't get any funny ideas about
|
||||
// the status of the waypoint
|
||||
*pl_done_p = false;
|
||||
}
|
||||
|
||||
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
|
||||
|
||||
int i,j ;
|
||||
for (i = 0; i < MAX_AI_GOALS && target_object == -1; i++)
|
||||
{
|
||||
if (aip->goals[i].ai_mode == AIM_FLY_TO_SHIP || aip->goals[i].ai_mode == AI_GOAL_FLY_TO_SHIP)
|
||||
{
|
||||
for (j = 0; j < MAX_SHIPS; j++)
|
||||
{
|
||||
if (Ships[j].objnum != -1 && !stricmp(aip->goals[i].ship_name, Ships[j].ship_name))
|
||||
{
|
||||
target_object = Ships[j].objnum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* I shouldn't be flying to position for what ever called me any more.
|
||||
Set mode to none so that default dynamic behaviour gets started up again. */
|
||||
if ( (aip->active_goal == AI_GOAL_NONE) || (aip->active_goal == AI_ACTIVE_GOAL_DYNAMIC) ) {
|
||||
aip->mode = AIM_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
target_pos = &Objects[target_object].pos;
|
||||
speed = Pl_objp->phys_info.speed;
|
||||
|
||||
dist_to_goal = vm_vec_dist_quick(&Pl_objp->pos, target_pos);
|
||||
@@ -4247,53 +4166,54 @@ void ai_fly_to_ship()
|
||||
// If a wing leader, take turns more slowly, based on size of wing.
|
||||
int scale;
|
||||
|
||||
if (Ai_info[Ships[Pl_objp->instance].ai_index].wing >= 0) {
|
||||
scale = Wings[Ai_info[Ships[Pl_objp->instance].ai_index].wing].current_count;
|
||||
if (aip->wing >= 0) {
|
||||
scale = Wings[aip->wing].current_count;
|
||||
scale = (int) ((scale+1)/2);
|
||||
} else {
|
||||
scale = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------
|
||||
// if in autopilot mode make sure to not collide
|
||||
// and "keep reasonable distance"
|
||||
// this needs to be done for ALL SHIPS not just capships STOP CHANGING THIS
|
||||
// ----------------------------------------------
|
||||
|
||||
object *wing_leader = get_wing_leader(aip->wing);
|
||||
|
||||
vec3d perp, goal_point;
|
||||
|
||||
bool carry_flag = ((shipp->flags2 & SF2_NAVPOINT_CARRY) || ((shipp->wingnum >= 0) && (Wings[shipp->wingnum].flags & WF_NAV_CARRY)));
|
||||
|
||||
if (AutoPilotEngaged && timestamp_elapsed(LockAPConv) && carry_flag
|
||||
&& ((The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) || (Pl_objp != wing_leader)) )
|
||||
if (AutoPilotEngaged
|
||||
&& timestamp_elapsed(LockAPConv)
|
||||
&& carry_flag
|
||||
&& ((The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) || (Pl_objp != Autopilot_flight_leader)) )
|
||||
{
|
||||
Assertion( Autopilot_flight_leader != NULL, "When under autopilot there must be a flight leader" );
|
||||
// snap wings into formation them into formation
|
||||
if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) {
|
||||
if (aip->wing != -1) {
|
||||
int wing_index = get_wing_index(Pl_objp, aip->wing);
|
||||
object *wing_leader = get_wing_leader(aip->wing);
|
||||
|
||||
if (wing_leader != Pl_objp) {
|
||||
// not leader.. get our position relative to leader
|
||||
// not wing leader.. get my position relative to wing leader
|
||||
get_absolute_wing_pos_autopilot(&goal_point, wing_leader, wing_index, aip->ai_flags & AIF_FORMATION_OBJECT);
|
||||
} else {
|
||||
// Am wing leader.. get the wings position relative to the flight leader
|
||||
j = 1+int( (float)floor(double(autopilot_wings[aip->wing]-1)/2.0) );
|
||||
|
||||
switch (autopilot_wings[aip->wing] % 2) {
|
||||
case 1: // back-left
|
||||
vm_vec_copy_normalize(&perp, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_copy_normalize(&perp, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
vm_vec_scale(&perp, -166.0f*j); // 166m is supposedly the optimal range according to tolwyn
|
||||
vm_vec_add(&goal_point, &Player_obj->pos, &perp);
|
||||
vm_vec_add(&goal_point, &Autopilot_flight_leader->pos, &perp);
|
||||
break;
|
||||
|
||||
default: //back-right
|
||||
case 0:
|
||||
vm_vec_copy_normalize(&perp, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_copy_normalize(&perp, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
vm_vec_scale(&perp, 166.0f*j);
|
||||
vm_vec_add(&goal_point, &Player_obj->pos, &perp);
|
||||
vm_vec_add(&goal_point, &Autopilot_flight_leader->pos, &perp);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4302,10 +4222,10 @@ void ai_fly_to_ship()
|
||||
Pl_objp->pos = goal_point;
|
||||
}
|
||||
|
||||
vm_vec_sub(&perp, Navs[CurrentNav].GetPosition(), &Player_obj->pos);
|
||||
vm_vec_sub(&perp, Navs[CurrentNav].GetPosition(), &Autopilot_flight_leader->pos);
|
||||
vm_vector_2_matrix(&Pl_objp->orient, &perp, NULL, NULL);
|
||||
} else {
|
||||
vm_vec_scale_add(&perp, &Pl_objp->pos, &wing_leader->phys_info.vel, 1000.0f);
|
||||
vm_vec_scale_add(&perp, &Pl_objp->pos, &Autopilot_flight_leader->phys_info.vel, 1000.0f);
|
||||
ai_turn_towards_vector(&perp, Pl_objp, flFrametime, sip->srotation_time*3.0f*scale, slop_vec, NULL, 0.0f, 0);
|
||||
}
|
||||
} else {
|
||||
@@ -4320,8 +4240,6 @@ void ai_fly_to_ship()
|
||||
dot = vm_vec_dot_to_point(&nvel_vec, &Pl_objp->pos, target_pos);
|
||||
aip->prev_dot_to_goal = dot;
|
||||
|
||||
// nprintf(("AI", "Wp #%i, dot = %6.3f, next dot = %6.3f, dist = %7.2f\n", wp_index, dot, dot_to_next, dist_to_goal));
|
||||
|
||||
if (Pl_objp->phys_info.speed < 0.0f) {
|
||||
accelerate_ship(aip, 1.0f/32);
|
||||
} else if (prev_dot_to_goal > dot+0.01f) {
|
||||
@@ -4383,13 +4301,11 @@ void ai_fly_to_ship()
|
||||
|
||||
r = find_nearest_point_on_line(&nearest_point, &Pl_objp->last_pos, &Pl_objp->pos, target_pos);
|
||||
|
||||
if ( (vm_vec_dist_quick(&Pl_objp->pos, target_pos) < (MIN_DIST_TO_WAYPOINT_GOAL + fl_sqrt(Pl_objp->radius) + vm_vec_dist_quick(&Pl_objp->pos, &Pl_objp->last_pos))) ||
|
||||
((r >= 0.0f) && (r <= 1.0f)) && (vm_vec_dist_quick(&nearest_point, target_pos) < (MIN_DIST_TO_WAYPOINT_GOAL + fl_sqrt(Pl_objp->radius)))) {
|
||||
|
||||
|
||||
if ( (vm_vec_dist_quick(&Pl_objp->pos, target_pos) < (MIN_DIST_TO_WAYPOINT_GOAL + fl_sqrt(Pl_objp->radius) + vm_vec_dist_quick(&Pl_objp->pos, &Pl_objp->last_pos)))
|
||||
|| (((r >= 0.0f) && (r <= 1.0f)) && (vm_vec_dist_quick(&nearest_point, target_pos) < (MIN_DIST_TO_WAYPOINT_GOAL + fl_sqrt(Pl_objp->radius)))))
|
||||
{
|
||||
int treat_as_ship;
|
||||
|
||||
// when not repeating waypoints -- mark the goal as done and put and entry into the mission log
|
||||
// we must be careful when dealing with wings. A ship in a wing might be completing
|
||||
// a waypoint for for the entire wing, or it might be completing a goal for itself. If
|
||||
// for itself and in a wing, treat the completion as we would a ship
|
||||
@@ -4397,15 +4313,6 @@ void ai_fly_to_ship()
|
||||
if ( Ships[Pl_objp->instance].wingnum != -1 ) {
|
||||
int type;
|
||||
|
||||
// I don't think that you can fly waypoints as dynamic goals!!!
|
||||
// -- This is legal, just stupid. -- Assert( (aip->active_goal != AI_GOAL_NONE) && (aip->active_goal != AI_ACTIVE_GOAL_DYNAMIC) );
|
||||
|
||||
// Clean up from above Assert, just in case we ship without fixing it. (Encountered by JimB on 2/9/98)
|
||||
if ( (aip->active_goal == AI_GOAL_NONE) || (aip->active_goal == AI_ACTIVE_GOAL_DYNAMIC) ) {
|
||||
aip->mode = AIM_NONE;
|
||||
Int3(); // Look at the ship, find out of it's supposed to be flying waypoints. -- MK.
|
||||
}
|
||||
|
||||
type = aip->goals[aip->active_goal].type;
|
||||
if ( (type == AIG_TYPE_EVENT_WING) || (type == AIG_TYPE_PLAYER_WING) ) {
|
||||
treat_as_ship = 0;
|
||||
@@ -4413,20 +4320,20 @@ void ai_fly_to_ship()
|
||||
treat_as_ship = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if the ship is not in a wing, remove the goal and continue on
|
||||
if ( treat_as_ship ) {
|
||||
ai_mission_goal_complete( aip ); // this call should reset the AI mode
|
||||
//mission_log_add_entry(LOG_WAYPOINTS_DONE, Ships[Pl_objp->instance].ship_name, wpl->name, -1 );
|
||||
// setup out parameters
|
||||
if ( pl_done_p != NULL ) {
|
||||
*pl_done_p = true;
|
||||
if ( pl_treat_as_ship_p != NULL ) {
|
||||
if ( treat_as_ship ) {
|
||||
*pl_treat_as_ship_p = true;
|
||||
} else {
|
||||
*pl_treat_as_ship_p = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// this ship is in a wing. We must mark the goal as being completed for all ships
|
||||
// in the wing. We will also mark an entry in the log that the wing completed the goal
|
||||
// not the individual ship.
|
||||
ai_mission_wing_goal_complete( Ships[Pl_objp->instance].wingnum, &(aip->goals[aip->active_goal]) );
|
||||
//mission_log_add_entry( LOG_WAYPOINTS_DONE, Wings[Ships[Pl_objp->instance].wingnum].name, wpl->name, -1 );
|
||||
Assertion( pl_treat_as_ship_p != NULL,
|
||||
"pl_done_p cannot be NULL while pl_treat_as_ship_p is not NULL" );
|
||||
}
|
||||
//wp_index = wpl->count-1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4436,18 +4343,8 @@ void ai_fly_to_ship()
|
||||
void ai_waypoints()
|
||||
{
|
||||
int wp_index;
|
||||
vec3d *wp_cur, *wp_next;
|
||||
float dot, dist_to_goal, dist_to_next, speed, dot_to_next;
|
||||
ship *shipp = &Ships[Pl_objp->instance];
|
||||
ship_info *sip = &Ship_info[shipp->ship_info_index];
|
||||
waypoint_list *wpl;
|
||||
ai_info *aip;
|
||||
vec3d nvel_vec;
|
||||
float mag;
|
||||
float prev_dot_to_goal;
|
||||
vec3d temp_vec;
|
||||
vec3d *slop_vec;
|
||||
int j;
|
||||
waypoint_list *wpl;
|
||||
|
||||
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
|
||||
|
||||
@@ -4461,236 +4358,111 @@ void ai_waypoints()
|
||||
|
||||
wpl = &Waypoint_lists[aip->wp_list];
|
||||
|
||||
Assert(wpl->count); // What? Is this zero? Probably wp_index never got initialized!
|
||||
Assert(wpl->count > 0); // What? Is this zero? Probably wp_index never got initialized!
|
||||
|
||||
wp_cur = &wpl->waypoints[wp_index];
|
||||
wp_next = &wpl->waypoints[(wp_index+1) % wpl->count];
|
||||
speed = Pl_objp->phys_info.speed;
|
||||
bool done, treat_as_ship;
|
||||
ai_fly_to_target_position(&(wpl->waypoints[wp_index]), &done, &treat_as_ship);
|
||||
|
||||
dist_to_goal = vm_vec_dist_quick(&Pl_objp->pos, wp_cur);
|
||||
dist_to_next = vm_vec_dist_quick(&Pl_objp->pos, wp_next);
|
||||
|
||||
// Can't use fvec, need to use velocity vector because we aren't necessarily
|
||||
// moving in the direction we're facing.
|
||||
// AL 23-3-98: Account for very small velocities by checking result of vm_vec_mag().
|
||||
// If we don't vm_vec_copy_normalize() will think it is normalizing a null vector.
|
||||
// if (IS_VEC_NULL(&Pl_objp->phys_info.vel)) {
|
||||
if ( vm_vec_mag_quick(&Pl_objp->phys_info.vel) < AICODE_SMALL_MAGNITUDE ) {
|
||||
mag = 0.0f;
|
||||
vm_vec_zero(&nvel_vec);
|
||||
} else {
|
||||
mag = vm_vec_copy_normalize(&nvel_vec, &Pl_objp->phys_info.vel);
|
||||
}
|
||||
|
||||
// If moving not-very-slowly and sliding, then try to slide at goal, rather than
|
||||
// point at goal.
|
||||
slop_vec = NULL;
|
||||
if (mag < 1.0f) {
|
||||
nvel_vec = Pl_objp->orient.vec.fvec;
|
||||
} else if (mag > 5.0f) {
|
||||
float nv_dot;
|
||||
nv_dot = vm_vec_dot(&Pl_objp->orient.vec.fvec, &nvel_vec);
|
||||
if ((nv_dot > 0.5f) && (nv_dot < 0.97f)) {
|
||||
slop_vec = &temp_vec;
|
||||
vm_vec_sub(slop_vec, &nvel_vec, &Pl_objp->orient.vec.fvec);
|
||||
}
|
||||
}
|
||||
|
||||
// If a wing leader, take turns more slowly, based on size of wing.
|
||||
int scale;
|
||||
|
||||
if (aip->wing >= 0) {
|
||||
scale = Wings[aip->wing].current_count;
|
||||
scale = (int) ((scale+1)/2);
|
||||
} else {
|
||||
scale = 1;
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
// if in autopilot mode make sure to not collide
|
||||
// and "keep reasonable distance"
|
||||
// this needs to be done for ALL SHIPS not just capships STOP CHANGING THIS
|
||||
// ----------------------------------------------
|
||||
|
||||
object *wing_leader = get_wing_leader(aip->wing);
|
||||
|
||||
vec3d perp, goal_point;
|
||||
|
||||
bool carry_flag = ((shipp->flags2 & SF2_NAVPOINT_CARRY) || ((shipp->wingnum >= 0) && (Wings[shipp->wingnum].flags & WF_NAV_CARRY)));
|
||||
|
||||
if (AutoPilotEngaged && timestamp_elapsed(LockAPConv) && carry_flag
|
||||
&& ((The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) || (Pl_objp != wing_leader)) )
|
||||
{
|
||||
// snap wings into formation them into formation
|
||||
if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS) {
|
||||
if (aip->wing != -1) {
|
||||
int wing_index = get_wing_index(Pl_objp, aip->wing);
|
||||
|
||||
if (wing_leader != Pl_objp) {
|
||||
// not leader.. get our position relative to leader
|
||||
get_absolute_wing_pos_autopilot(&goal_point, wing_leader, wing_index, aip->ai_flags & AIF_FORMATION_OBJECT);
|
||||
} else {
|
||||
j = 1+int( (float)floor(double(autopilot_wings[aip->wing]-1)/2.0) );
|
||||
|
||||
switch (autopilot_wings[aip->wing] % 2) {
|
||||
case 1: // back-left
|
||||
vm_vec_copy_normalize(&perp, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_scale(&perp, -166.0f*j); // 166m is supposedly the optimal range according to tolwyn
|
||||
vm_vec_add(&goal_point, &Player_obj->pos, &perp);
|
||||
break;
|
||||
|
||||
default: //back-right
|
||||
case 0:
|
||||
vm_vec_copy_normalize(&perp, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_scale(&perp, 166.0f*j);
|
||||
vm_vec_add(&goal_point, &Player_obj->pos, &perp);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Pl_objp->pos = goal_point;
|
||||
}
|
||||
|
||||
vm_vec_sub(&perp, Navs[CurrentNav].GetPosition(), &Player_obj->pos);
|
||||
vm_vector_2_matrix(&Pl_objp->orient, &perp, NULL, NULL);
|
||||
} else {
|
||||
if ( !wing_leader )
|
||||
wing_leader = Pl_objp;
|
||||
vm_vec_scale_add(&perp, &Pl_objp->pos, &wing_leader->phys_info.vel, 1000.0f);
|
||||
ai_turn_towards_vector(&perp, Pl_objp, flFrametime, sip->srotation_time*3.0f*scale, slop_vec, NULL, 0.0f, 0);
|
||||
}
|
||||
} else {
|
||||
if (dist_to_goal > 0.1f) {
|
||||
ai_turn_towards_vector(wp_cur, Pl_objp, flFrametime, sip->srotation_time*3.0f*scale, slop_vec, NULL, 0.0f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
prev_dot_to_goal = aip->prev_dot_to_goal;
|
||||
dot = vm_vec_dot_to_point(&nvel_vec, &Pl_objp->pos, wp_cur);
|
||||
dot_to_next = vm_vec_dot_to_point(&nvel_vec, &Pl_objp->pos, wp_next);
|
||||
aip->prev_dot_to_goal = dot;
|
||||
|
||||
// If there is no next point on the path, don't care about dot to next.
|
||||
if (wp_index + 1 >= wpl->count) {
|
||||
dot_to_next = dot;
|
||||
}
|
||||
|
||||
// nprintf(("AI", "Wp #%i, dot = %6.3f, next dot = %6.3f, dist = %7.2f\n", wp_index, dot, dot_to_next, dist_to_goal));
|
||||
|
||||
if (Pl_objp->phys_info.speed < 0.0f) {
|
||||
accelerate_ship(aip, 1.0f/32);
|
||||
} else if (prev_dot_to_goal > dot+0.01f) {
|
||||
// We are further from pointing at our goal this frame than last frame, so slow down.
|
||||
set_accel_for_target_speed(Pl_objp, Pl_objp->phys_info.speed * 0.95f);
|
||||
} else if (dist_to_goal < 100.0f) {
|
||||
float slew_dot = vm_vec_dot(&Pl_objp->orient.vec.fvec, &nvel_vec);
|
||||
if (fl_abs(slew_dot) < 0.9f) {
|
||||
accelerate_ship(aip, 0.0f);
|
||||
} else if (dot < 0.88f + 0.1f*(100.0f - dist_to_goal)/100.0f) {
|
||||
accelerate_ship(aip, 0.0f);
|
||||
} else {
|
||||
accelerate_ship(aip, 0.5f * dot * dot);
|
||||
}
|
||||
} else {
|
||||
float dot1;
|
||||
if (dist_to_goal < 250.0f) {
|
||||
dot1 = dot*dot*dot; // Very important to be pointing towards goal when nearby. Note, cubing preserves sign.
|
||||
} else {
|
||||
if (dot > 0.0f) {
|
||||
dot1 = dot*dot;
|
||||
if ( done ) {
|
||||
aip->wp_index++; // go on to next waypoint in path
|
||||
if ( (aip->wp_index >= wpl->count) ) {
|
||||
// have reached the last waypoint. Do I?
|
||||
if ( ((aip->wp_flags & WPF_REPEAT) > 0) ) {
|
||||
aip->wp_index = 0; // go back to the start.
|
||||
} else {
|
||||
dot1 = dot;
|
||||
}
|
||||
}
|
||||
|
||||
if (dist_to_goal > 100.0f + Pl_objp->radius * 2) {
|
||||
if (dot < 0.2f) {
|
||||
dot1 = 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
if (sip->flags & SIF_SMALL_SHIP) {
|
||||
set_accel_for_target_speed(Pl_objp, dot1 * dist_to_goal/5.0f);
|
||||
} else {
|
||||
set_accel_for_target_speed(Pl_objp, dot1 * dist_to_goal/10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure not travelling too fast for someone to keep up.
|
||||
float max_allowed_speed = 9999.9f;
|
||||
|
||||
if (shipp->wingnum != -1) {
|
||||
max_allowed_speed = 0.9f * get_wing_lowest_max_speed(Pl_objp);
|
||||
}
|
||||
|
||||
// check if waypoint speed cap is set and adjust max speed
|
||||
if (aip->waypoint_speed_cap > 0) {
|
||||
max_allowed_speed = (float) aip->waypoint_speed_cap;
|
||||
}
|
||||
|
||||
if (aip->prev_accel * shipp->current_max_speed > max_allowed_speed) {
|
||||
accelerate_ship(aip, max_allowed_speed / shipp->current_max_speed);
|
||||
}
|
||||
|
||||
if ( (dist_to_goal < MIN_DIST_TO_WAYPOINT_GOAL) || (vm_vec_dist_quick(&Pl_objp->last_pos, &Pl_objp->pos) > 0.1f) ) {
|
||||
vec3d nearest_point;
|
||||
float r;
|
||||
|
||||
r = find_nearest_point_on_line(&nearest_point, &Pl_objp->last_pos, &Pl_objp->pos, wp_cur);
|
||||
|
||||
if ( (vm_vec_dist_quick(&Pl_objp->pos, wp_cur) < (MIN_DIST_TO_WAYPOINT_GOAL + fl_sqrt(Pl_objp->radius) + vm_vec_dist_quick(&Pl_objp->pos, &Pl_objp->last_pos))) ||
|
||||
((r >= 0.0f) && (r <= 1.0f)) && (vm_vec_dist_quick(&nearest_point, wp_cur) < (MIN_DIST_TO_WAYPOINT_GOAL + fl_sqrt(Pl_objp->radius)))) {
|
||||
wp_index++;
|
||||
if (wp_index >= wpl->count)
|
||||
if (aip->wp_flags & WPF_REPEAT) {
|
||||
wp_index = 0;
|
||||
aip->wp_index = (wpl->count - 1); // stay on the last waypoint
|
||||
// Log a message that the wing or ship reached his waypoint and
|
||||
// remove the goal from the AI goals of the ship pr wing, respectively.
|
||||
// Wether or not we should treat this as a ship or a wing is determined by
|
||||
// ai_fly_to_target_position when it marks the AI directive as complete
|
||||
if ( treat_as_ship ) {
|
||||
ai_mission_goal_complete( aip ); // this call should reset the AI mode
|
||||
mission_log_add_entry( LOG_WAYPOINTS_DONE, Ships[Pl_objp->instance].ship_name, wpl->name, -1 );
|
||||
} else {
|
||||
int treat_as_ship;
|
||||
|
||||
// when not repeating waypoints -- mark the goal as done and put and entry into the mission log
|
||||
// we must be careful when dealing with wings. A ship in a wing might be completing
|
||||
// a waypoint for for the entire wing, or it might be completing a goal for itself. If
|
||||
// for itself and in a wing, treat the completion as we would a ship
|
||||
treat_as_ship = 1;
|
||||
if ( Ships[Pl_objp->instance].wingnum != -1 ) {
|
||||
int type;
|
||||
|
||||
// I don't think that you can fly waypoints as dynamic goals!!!
|
||||
// -- This is legal, just stupid. -- Assert( (aip->active_goal != AI_GOAL_NONE) && (aip->active_goal != AI_ACTIVE_GOAL_DYNAMIC) );
|
||||
|
||||
// Clean up from above Assert, just in case we ship without fixing it. (Encountered by JimB on 2/9/98)
|
||||
if ( (aip->active_goal == AI_GOAL_NONE) || (aip->active_goal == AI_ACTIVE_GOAL_DYNAMIC) ) {
|
||||
aip->mode = AIM_NONE;
|
||||
//Int3(); // Look at the ship, find out of it's supposed to be flying waypoints. -- MK.
|
||||
}
|
||||
|
||||
type = aip->goals[aip->active_goal].type;
|
||||
if ( (type == AIG_TYPE_EVENT_WING) || (type == AIG_TYPE_PLAYER_WING) ) {
|
||||
treat_as_ship = 0;
|
||||
} else {
|
||||
treat_as_ship = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if the ship is not in a wing, remove the goal and continue on
|
||||
if ( treat_as_ship ) {
|
||||
ai_mission_goal_complete( aip ); // this call should reset the AI mode
|
||||
mission_log_add_entry(LOG_WAYPOINTS_DONE, Ships[Pl_objp->instance].ship_name, wpl->name, -1 );
|
||||
} else {
|
||||
// this ship is in a wing. We must mark the goal as being completed for all ships
|
||||
// in the wing. We will also mark an entry in the log that the wing completed the goal
|
||||
// not the individual ship.
|
||||
ai_mission_wing_goal_complete( Ships[Pl_objp->instance].wingnum, &(aip->goals[aip->active_goal]) );
|
||||
mission_log_add_entry( LOG_WAYPOINTS_DONE, Wings[Ships[Pl_objp->instance].wingnum].name, wpl->name, -1 );
|
||||
}
|
||||
//wp_index = wpl->count-1;
|
||||
ai_mission_wing_goal_complete( Ships[Pl_objp->instance].wingnum, &(aip->goals[aip->active_goal]) );
|
||||
mission_log_add_entry( LOG_WAYPOINTS_DONE, Wings[Ships[Pl_objp->instance].wingnum].name, wpl->name, -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aip->wp_index = wp_index;
|
||||
// --------------------------------------------------------------------------
|
||||
// make Pl_objp fly toward a ship
|
||||
void ai_fly_to_ship()
|
||||
{
|
||||
ai_info *aip;
|
||||
object* target_p = NULL;
|
||||
|
||||
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
|
||||
|
||||
if ( aip->mode != AIM_FLY_TO_SHIP ) {
|
||||
Warning(LOCATION,
|
||||
"ai_fly_to_ship called for '%s' when ai_info.mode not equal to AIM_FLY_TO_SHIP. Is actually '%d'",
|
||||
Ships[Pl_objp->instance].ship_name,
|
||||
aip->mode);
|
||||
aip->mode = AIM_NONE;
|
||||
return;
|
||||
}
|
||||
if ( aip->active_goal < 0 || aip->active_goal >= MAX_AI_GOALS ) {
|
||||
Warning(LOCATION,
|
||||
"'%s' is trying to fly-to a ship without an active AI_GOAL\n\n"
|
||||
"Active ai mode is '%d'",
|
||||
Ships[Pl_objp->instance].ship_name,
|
||||
aip->active_goal);
|
||||
aip->mode = AIM_NONE;
|
||||
return;
|
||||
}
|
||||
Assert( aip->goals[aip->active_goal].ship_name != NULL );
|
||||
if ( strlen(aip->goals[aip->active_goal].ship_name) == 0 ) {
|
||||
Warning(LOCATION,
|
||||
"'%s' is trying to fly-to a ship without a name for the ship",
|
||||
Ships[Pl_objp->instance].ship_name);
|
||||
aip->mode = AIM_NONE;
|
||||
ai_remove_ship_goal( aip, aip->active_goal ); // function sets aip->active_goal to NONE for me
|
||||
return;
|
||||
}
|
||||
|
||||
for (int j = 0; j < MAX_SHIPS; j++)
|
||||
{
|
||||
if (Ships[j].objnum != -1 && !stricmp(aip->goals[aip->active_goal].ship_name, Ships[j].ship_name))
|
||||
{
|
||||
target_p = &Objects[Ships[j].objnum];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( target_p == NULL ) {
|
||||
#ifndef NDEBUG
|
||||
for (int i = 0; i < MAX_AI_GOALS; i++)
|
||||
{
|
||||
if (aip->mode == AIM_FLY_TO_SHIP || aip->goals[i].ai_mode == AI_GOAL_FLY_TO_SHIP)
|
||||
{
|
||||
mprintf(("Ship '%s' told to fly to target ship '%s'",
|
||||
Ships[Pl_objp->instance].ship_name,
|
||||
aip->goals[i].ship_name));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Warning(LOCATION, "Ship '%s' told to fly to a ship but none of the ships it was told to fly to exist.\n"
|
||||
"See log before this message for list of ships set as fly-to tagets",
|
||||
Ships[Pl_objp->instance].ship_name);
|
||||
aip->mode = AIM_NONE;
|
||||
ai_remove_ship_goal( aip, aip->active_goal ); // function sets aip->active_goal to NONE for me
|
||||
return;
|
||||
} else {
|
||||
bool done, treat_as_ship;
|
||||
ai_fly_to_target_position(&(target_p->pos), &done, &treat_as_ship);
|
||||
|
||||
if ( done ) {
|
||||
// remove the goal from the AI goals of the ship pr wing, respectively.
|
||||
// Wether or not we should treat this as a ship or a wing is determined by
|
||||
// ai_fly_to_target when it marks the AI directive as complete
|
||||
if ( treat_as_ship ) {
|
||||
ai_mission_goal_complete( aip ); // this call should reset the AI mode
|
||||
} else {
|
||||
ai_mission_wing_goal_complete( Ships[Pl_objp->instance].wingnum, &(aip->goals[aip->active_goal]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5398,7 +5170,6 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags)
|
||||
{
|
||||
// this can be NULL in the case of a target death and attacker weapon
|
||||
// change. using notification message instead of a fault
|
||||
// Int3();
|
||||
mprintf(("'other_objpp == NULL' in ai_select_primary_weapon()\n"));
|
||||
return -1;
|
||||
}
|
||||
@@ -5450,7 +5221,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags)
|
||||
// ##UnknownPlayer## - removed.
|
||||
}
|
||||
|
||||
if ( Ship_info[Ships[other_objp->instance].ship_info_index].flags & ( SIF_BIG_SHIP | SIF_HUGE_SHIP))
|
||||
if ( (other_objp->type == OBJ_SHIP) && (Ship_info[Ships[other_objp->instance].ship_info_index].flags & (SIF_BIG_SHIP|SIF_HUGE_SHIP) ) )
|
||||
{
|
||||
//Check if we have a capital+ weapon on board
|
||||
for (int i = 0; i < swp->num_primary_banks; i++)
|
||||
@@ -5476,16 +5247,20 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags)
|
||||
int i;
|
||||
float i_hullfactor_prev = 0; // Previous weapon bank hull factor (this is the safe way to do it)
|
||||
int i_hullfactor_prev_bank = -1; // Bank which gave us this hull factor
|
||||
|
||||
// Find the weapon with the highest hull * damage / fire delay factor
|
||||
for (i = 0; i < swp->num_primary_banks; i++)
|
||||
{
|
||||
if (swp->primary_bank_weapons[i] > -1) // Make sure there is a weapon in the bank
|
||||
{
|
||||
if (((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev) && (!(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS) && !( Ship_info[Ships[other_objp->instance].ship_info_index].flags & ( SIF_BIG_SHIP | SIF_HUGE_SHIP))) )
|
||||
if ((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev)
|
||||
{
|
||||
// This weapon is the new candidate
|
||||
i_hullfactor_prev = ( ((Weapon_info[swp->primary_bank_weapons[i]].armor_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait );
|
||||
i_hullfactor_prev_bank = i;
|
||||
if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS) )
|
||||
{
|
||||
// This weapon is the new candidate
|
||||
i_hullfactor_prev = ( ((Weapon_info[swp->primary_bank_weapons[i]].armor_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait );
|
||||
i_hullfactor_prev_bank = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5497,15 +5272,16 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags)
|
||||
return i_hullfactor_prev_bank; // Return
|
||||
}
|
||||
|
||||
//if the shields are above lets say 10% defanantly use a pierceing weapon if there are any-Bobboau
|
||||
if (enemy_remaining_shield >= 0.10f){
|
||||
//if the shields are above lets say 10% definitely use a pierceing weapon if there are any-Bobboau
|
||||
if (enemy_remaining_shield >= 0.10f)
|
||||
{
|
||||
if (swp->current_primary_bank >= 0)
|
||||
{
|
||||
int bank_index;
|
||||
|
||||
bank_index = swp->current_primary_bank;
|
||||
|
||||
if ((Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags2 & WIF2_PIERCE_SHIELDS) && !(Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags2 & WIF2_CAPITAL_PLUS)&& !( Ship_info[Ships[other_objp->instance].ship_info_index].flags & ( SIF_BIG_SHIP | SIF_HUGE_SHIP)))
|
||||
if ((Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags2 & WIF2_PIERCE_SHIELDS) && !(Weapon_info[swp->primary_bank_weapons[bank_index]].wi_flags2 & WIF2_CAPITAL_PLUS))
|
||||
{
|
||||
return swp->current_primary_bank;
|
||||
}
|
||||
@@ -5518,7 +5294,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags)
|
||||
|
||||
if (weapon_info_index > -1)
|
||||
{
|
||||
if ((Weapon_info[weapon_info_index].wi_flags2 & WIF2_PIERCE_SHIELDS) && !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS)&& !( Ship_info[Ships[other_objp->instance].ship_info_index].flags & ( SIF_BIG_SHIP | SIF_HUGE_SHIP)))
|
||||
if ((Weapon_info[weapon_info_index].wi_flags2 & WIF2_PIERCE_SHIELDS) && !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS))
|
||||
{
|
||||
swp->current_primary_bank = i;
|
||||
return i;
|
||||
@@ -5539,11 +5315,14 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags)
|
||||
{
|
||||
if (swp->primary_bank_weapons[i] > -1) // Make sure there is a weapon in the bank
|
||||
{
|
||||
if (((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor + Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev ) && !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS)&& !( Ship_info[Ships[other_objp->instance].ship_info_index].flags & ( SIF_BIG_SHIP | SIF_HUGE_SHIP)))
|
||||
if ((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor + Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev)
|
||||
{
|
||||
// This weapon is the new candidate
|
||||
i_hullfactor_prev = ((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor + Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait));
|
||||
i_hullfactor_prev_bank = i;
|
||||
if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS) )
|
||||
{
|
||||
// This weapon is the new candidate
|
||||
i_hullfactor_prev = ((((Weapon_info[swp->primary_bank_weapons[i]].armor_factor + Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait));
|
||||
i_hullfactor_prev_bank = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5565,11 +5344,14 @@ int ai_select_primary_weapon(object *objp, object *other_objp, int flags)
|
||||
{
|
||||
if (swp->primary_bank_weapons[i] > -1) // Make sure there is a weapon in the bank
|
||||
{
|
||||
if (((((Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev ) && !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS)&& !( Ship_info[Ships[other_objp->instance].ship_info_index].flags & ( SIF_BIG_SHIP | SIF_HUGE_SHIP)))
|
||||
if ((((Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * Weapon_info[swp->primary_bank_weapons[i]].damage) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait) > i_hullfactor_prev)
|
||||
{
|
||||
// This weapon is the new candidate
|
||||
i_hullfactor_prev = ( ((Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait );
|
||||
i_hullfactor_prev_bank = i;
|
||||
if ( !(Weapon_info[swp->primary_bank_weapons[i]].wi_flags2 & WIF2_CAPITAL_PLUS) )
|
||||
{
|
||||
// This weapon is the new candidate
|
||||
i_hullfactor_prev = ( ((Weapon_info[swp->primary_bank_weapons[i]].shield_factor) * (Weapon_info[swp->primary_bank_weapons[i]].damage)) / Weapon_info[swp->primary_bank_weapons[i]].fire_wait );
|
||||
i_hullfactor_prev_bank = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5738,7 +5520,7 @@ int ai_fire_primary_weapon(object *objp)
|
||||
|
||||
if (aip->target_objnum != -1){
|
||||
enemy_objp = &Objects[aip->target_objnum];
|
||||
enemy_sip = &Ship_info[Ships[enemy_objp->instance].ship_info_index];
|
||||
enemy_sip = (enemy_objp->type == OBJ_SHIP) ? &Ship_info[Ships[enemy_objp->instance].ship_info_index] : NULL;
|
||||
} else {
|
||||
enemy_objp = NULL;
|
||||
enemy_sip = NULL;
|
||||
@@ -5775,7 +5557,7 @@ int ai_fire_primary_weapon(object *objp)
|
||||
|
||||
//SUSHI: Burst-fire for ballistic primaries.
|
||||
if (The_mission.ai_profile->primary_ammo_burst_mult[Game_skill_level] > 0 && //Make sure we are using burst fire
|
||||
enemy_objp != NULL && //We need a target, obviously
|
||||
enemy_objp != NULL && enemy_sip != NULL && //We need a target, obviously
|
||||
(enemy_objp->phys_info.speed >= 1.0f) && //Only burst for moving ships
|
||||
(enemy_sip->flags & (SIF_SMALL_SHIP | SIF_TRANSPORT)) && //Only burst for small ships (transports count)
|
||||
swp->primary_bank_start_ammo[swp->current_primary_bank] > 0 && //Prevent div by 0
|
||||
@@ -6427,7 +6209,6 @@ float ai_get_weapon_dist(ship_weapon *swp)
|
||||
// If weapon_num is illegal, return a reasonable value. A valid weapon
|
||||
// will get selected when this ship tries to fire.
|
||||
if (weapon_num == -1) {
|
||||
// Int3();
|
||||
return 1000.0f;
|
||||
}
|
||||
|
||||
@@ -6445,7 +6226,6 @@ float ai_get_weapon_speed(ship_weapon *swp)
|
||||
weapon_num = swp->primary_bank_weapons[bank_num];
|
||||
|
||||
if (weapon_num == -1) {
|
||||
//Int3();
|
||||
return 100.0f;
|
||||
}
|
||||
|
||||
@@ -8099,14 +7879,6 @@ void ai_cruiser_chase()
|
||||
ship *shipp = &Ships[Pl_objp->instance];
|
||||
ai_info *aip = &Ai_info[shipp->ai_index];
|
||||
|
||||
//WMC - We don't need/want this anymore.
|
||||
/*
|
||||
if (!(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP))) {
|
||||
Int3(); // Hmm, not a very big ship, how did we get in this function?
|
||||
aip->mode = AIM_NONE;
|
||||
return;
|
||||
}*/
|
||||
|
||||
if (En_objp->type != OBJ_SHIP) {
|
||||
Int3();
|
||||
return;
|
||||
@@ -8496,10 +8268,14 @@ void ai_chase()
|
||||
aip->submode == SM_SUPER_ATTACK ||
|
||||
aip->submode == SM_EVADE_SQUIGGLE ||
|
||||
aip->submode == SM_EVADE ||
|
||||
aip->submode == SM_GET_AWAY)
|
||||
aip->submode == SM_GET_AWAY ||
|
||||
aip->submode == AIS_CHASE_GLIDEATTACK)
|
||||
{
|
||||
//Re-roll for random sidethrust every 2 seconds
|
||||
if (static_randf((Missiontime + static_rand(aip->shipnum)) >> 17) < aip->ai_random_sidethrust_percent)
|
||||
//Also, only do this if we've recently been hit or are in current primary weapon range of target
|
||||
float current_weapon_range = Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]].weapon_range;
|
||||
if (static_randf((Missiontime + static_rand(aip->shipnum)) >> 17) < aip->ai_random_sidethrust_percent &&
|
||||
((Missiontime - aip->last_hit_time < i2f(5) && aip->hitter_objnum >= 0) || dist_to_enemy < current_weapon_range))
|
||||
{
|
||||
do_random_sidethrust(aip, sip);
|
||||
}
|
||||
@@ -8577,8 +8353,7 @@ void ai_chase()
|
||||
aip->submode_start_time = Missiontime;
|
||||
aip->submode_parm0 = SM_SF_AHEAD;
|
||||
} else if (dist_to_enemy < CIRCLE_STRAFE_MAX_DIST + En_objp->radius &&
|
||||
(En_objp->phys_info.speed < MAX(sip->max_vel.xyz.x, sip->max_vel.xyz.y)) &&
|
||||
(dot_to_enemy > 0.33) &&
|
||||
(En_objp->phys_info.speed < MAX(sip->max_vel.xyz.x, sip->max_vel.xyz.y) * 1.5f) &&
|
||||
(static_randf((Missiontime + static_rand(aip->shipnum)) >> 19) < aip->ai_circle_strafe_percent)) {
|
||||
aip->submode = AIS_CHASE_CIRCLESTRAFE;
|
||||
aip->submode_start_time = Missiontime;
|
||||
@@ -8693,8 +8468,7 @@ void ai_chase()
|
||||
aip->submode_start_time = Missiontime;
|
||||
aip->submode_parm0 = SM_SF_AHEAD;
|
||||
} else if (dist_to_enemy < CIRCLE_STRAFE_MAX_DIST + En_objp->radius &&
|
||||
(En_objp->phys_info.speed < MAX(sip->max_vel.xyz.x, sip->max_vel.xyz.y)) &&
|
||||
(dot_to_enemy > 0.33) &&
|
||||
(En_objp->phys_info.speed < MAX(sip->max_vel.xyz.x, sip->max_vel.xyz.y) * 1.5f) &&
|
||||
(static_randf((Missiontime + static_rand(aip->shipnum)) >> 19) < aip->ai_circle_strafe_percent)) {
|
||||
aip->submode = AIS_CHASE_CIRCLESTRAFE;
|
||||
aip->submode_start_time = Missiontime;
|
||||
@@ -12459,7 +12233,7 @@ void ai_manage_shield(object *objp, ai_info *aip)
|
||||
// set timestamp
|
||||
aip->shield_manage_timestamp = timestamp((int) (delay * 1000.0f));
|
||||
|
||||
if (sip->flags & SIF_SMALL_SHIP) {
|
||||
if (sip->flags & SIF_SMALL_SHIP || (aip->ai_profile_flags2 & AIPF2_ALL_SHIPS_MANAGE_SHIELDS)) {
|
||||
if (Missiontime - aip->last_hit_time < F1_0*10)
|
||||
ai_transfer_shield(objp, aip->last_hit_quadrant);
|
||||
else
|
||||
@@ -15263,7 +15037,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_
|
||||
objp_hitter = &Objects[hitter_objnum];
|
||||
|
||||
// lets not check hits by ghosts any further either
|
||||
if(objp_hitter->type & OBJ_GHOST)
|
||||
if(objp_hitter->type == OBJ_GHOST)
|
||||
return;
|
||||
|
||||
// Hit by a protected ship, don't attack it.
|
||||
|
||||
+1
-1
@@ -1008,7 +1008,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
* Pass -1 in priority to ignore priority when searching
|
||||
* Returns -1 if not found, or [0, MAX_AI_GOALS)
|
||||
*/
|
||||
int ai_find_goal_index( ai_goal* aigp, int mode, int submode = -1, int priority = -1 )
|
||||
int ai_find_goal_index( ai_goal* aigp, int mode, int submode, int priority )
|
||||
{
|
||||
Assert( aigp != NULL );
|
||||
for ( int i = 0; i < MAX_AI_GOALS; i++ )
|
||||
|
||||
+24
-24
@@ -26,35 +26,35 @@ struct ai_goal;
|
||||
// Fred. If the goal you add doesn't have a target (such as chase_any), then you don't have
|
||||
// to worry about doing this. Also add it to list in Fred\Management.cpp, and let Hoffoss know!
|
||||
// WMC - Oh and add them to Ai_goal_names plz. TY! :)
|
||||
#define AI_GOAL_CHASE (1<<1)
|
||||
#define AI_GOAL_DOCK (1<<2) // used for undocking as well
|
||||
#define AI_GOAL_WAYPOINTS (1<<3)
|
||||
#define AI_GOAL_WAYPOINTS_ONCE (1<<4)
|
||||
#define AI_GOAL_WARP (1<<5)
|
||||
#define AI_GOAL_DESTROY_SUBSYSTEM (1<<6)
|
||||
#define AI_GOAL_FORM_ON_WING (1<<7)
|
||||
#define AI_GOAL_UNDOCK (1<<8)
|
||||
#define AI_GOAL_CHASE_WING (1<<9)
|
||||
#define AI_GOAL_GUARD (1<<10)
|
||||
#define AI_GOAL_DISABLE_SHIP (1<<11)
|
||||
#define AI_GOAL_DISARM_SHIP (1<<12)
|
||||
#define AI_GOAL_CHASE_ANY (1<<13)
|
||||
#define AI_GOAL_IGNORE (1<<14)
|
||||
#define AI_GOAL_GUARD_WING (1<<15)
|
||||
#define AI_GOAL_EVADE_SHIP (1<<16)
|
||||
#define AI_GOAL_CHASE (1<<1) // 0x00000002
|
||||
#define AI_GOAL_DOCK (1<<2) // 0x00000004 // used for undocking as well
|
||||
#define AI_GOAL_WAYPOINTS (1<<3) // 0x00000008
|
||||
#define AI_GOAL_WAYPOINTS_ONCE (1<<4) // 0x00000010
|
||||
#define AI_GOAL_WARP (1<<5) // 0x00000020
|
||||
#define AI_GOAL_DESTROY_SUBSYSTEM (1<<6) // 0x00000040
|
||||
#define AI_GOAL_FORM_ON_WING (1<<7) // 0x00000080
|
||||
#define AI_GOAL_UNDOCK (1<<8) // 0x00000100
|
||||
#define AI_GOAL_CHASE_WING (1<<9) // 0x00000200
|
||||
#define AI_GOAL_GUARD (1<<10) // 0x00000400
|
||||
#define AI_GOAL_DISABLE_SHIP (1<<11) // 0x00000800
|
||||
#define AI_GOAL_DISARM_SHIP (1<<12) // 0x00001000
|
||||
#define AI_GOAL_CHASE_ANY (1<<13) // 0x00002000
|
||||
#define AI_GOAL_IGNORE (1<<14) // 0x00004000
|
||||
#define AI_GOAL_GUARD_WING (1<<15) // 0x00008000
|
||||
#define AI_GOAL_EVADE_SHIP (1<<16) // 0x00010000
|
||||
|
||||
// the next goals are for support ships only
|
||||
#define AI_GOAL_STAY_NEAR_SHIP (1<<17)
|
||||
#define AI_GOAL_KEEP_SAFE_DISTANCE (1<<18)
|
||||
#define AI_GOAL_REARM_REPAIR (1<<19)
|
||||
#define AI_GOAL_STAY_NEAR_SHIP (1<<17) // 0x00020000
|
||||
#define AI_GOAL_KEEP_SAFE_DISTANCE (1<<18) // 0x00040000
|
||||
#define AI_GOAL_REARM_REPAIR (1<<19) // 0x00080000
|
||||
|
||||
// resume regular goals
|
||||
#define AI_GOAL_STAY_STILL (1<<20)
|
||||
#define AI_GOAL_PLAY_DEAD (1<<21)
|
||||
#define AI_GOAL_CHASE_WEAPON (1<<22)
|
||||
#define AI_GOAL_STAY_STILL (1<<20) // 0x00100000
|
||||
#define AI_GOAL_PLAY_DEAD (1<<21) // 0x00200000
|
||||
#define AI_GOAL_CHASE_WEAPON (1<<22) // 0x00400000
|
||||
|
||||
#define AI_GOAL_FLY_TO_SHIP (1<<23) // kazan
|
||||
#define AI_GOAL_IGNORE_NEW (1<<24) // Goober5000
|
||||
#define AI_GOAL_FLY_TO_SHIP (1<<23) // 0x00800000
|
||||
#define AI_GOAL_IGNORE_NEW (1<<24) // 0x01000000
|
||||
|
||||
// now the masks for ship types
|
||||
|
||||
|
||||
+14
-6
@@ -1905,8 +1905,8 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
|
||||
if(num_valid < 1)
|
||||
ss->turret_enemy_objnum = -1;
|
||||
|
||||
// Maybe pick a new enemy.
|
||||
if ( turret_should_pick_new_target(ss) ) {
|
||||
// Maybe pick a new enemy, unless targeting has been taken over by scripting
|
||||
if ( turret_should_pick_new_target(ss) && !ss->scripting_target_override) {
|
||||
Num_find_turret_enemy++;
|
||||
int objnum = find_turret_enemy(ss, parent_objnum, &gpos, &gvec, ss->turret_enemy_objnum);
|
||||
//Assert(objnum < 0 || is_target_beam_valid(tp, objnum));
|
||||
@@ -2141,6 +2141,12 @@ void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum)
|
||||
turret_fire_weapon(valid_weapons[0], ss, parent_objnum, &gpos, &tv2e, &predicted_enemy_pos);
|
||||
else
|
||||
turret_fire_weapon(valid_weapons[i], ss, parent_objnum, &gpos, &tv2e, &predicted_enemy_pos);
|
||||
} else {
|
||||
// make sure salvo fire mode does not turn into autofire
|
||||
if ((tp->flags & MSS_FLAG_TURRET_SALVO) && ((i + 1) == number_of_firings)) {
|
||||
ai_info *parent_aip = &Ai_info[Ships[Objects[parent_objnum].instance].ai_index];
|
||||
turret_set_next_fire_timestamp(valid_weapons[0], wip, ss, parent_aip);
|
||||
}
|
||||
}
|
||||
// moved this here so we increment the fire pos only after we have fired and not during it
|
||||
ss->turret_next_fire_pos++;
|
||||
@@ -2213,14 +2219,16 @@ bool turret_adv_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mo
|
||||
if (((dot + size_mod) > tp->turret_fov) && ((dot - size_mod) <= tp->turret_max_fov)) {
|
||||
vec3d of_dst;
|
||||
vm_vec_rotate( &of_dst, v2e, &ss->world_to_turret_matrix );
|
||||
vm_vec_normalize(&of_dst);
|
||||
if ((of_dst.xyz.x == 0) && (of_dst.xyz.y == 0)) {
|
||||
return true;
|
||||
} else {
|
||||
of_dst.xyz.z = 0;
|
||||
// now we have 2d vector with lenght of 1 that points at the targets direction after being rotated to turrets FOR
|
||||
if ((-of_dst.xyz.y + size_mod) > tp->turret_y_fov)
|
||||
return true;
|
||||
if (!IS_VEC_NULL_SQ_SAFE(&of_dst)) {
|
||||
vm_vec_normalize(&of_dst);
|
||||
// now we have 2d vector with lenght of 1 that points at the targets direction after being rotated to turrets FOR
|
||||
if ((-of_dst.xyz.y + size_mod) > tp->turret_y_fov)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1085,11 +1085,9 @@ void anim_reverse_direction(anim_instance *ai)
|
||||
{
|
||||
int temp;
|
||||
|
||||
if(!(ai->parent->flags & ANF_ALL_KEYFRAMES)){
|
||||
// you're not allowed to call anim_reverse_direction(...) unless every frame is a keyframe!!!!
|
||||
// The God of Delta-RLE demands it be thus.
|
||||
Int3();
|
||||
}
|
||||
// you're not allowed to call anim_reverse_direction(...) unless every frame is a keyframe!!!!
|
||||
// The God of Delta-RLE demands it be thus.
|
||||
Assertion( ai->parent->flags & ANF_ALL_KEYFRAMES, "Ani was set to play backwards. In order to enable this, all frames of the animation MUST be keyframes.");
|
||||
|
||||
// flip the animation direction
|
||||
if(ai->direction == ANIM_DIRECT_FORWARD){
|
||||
|
||||
+1
-149
@@ -168,154 +168,6 @@ ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap
|
||||
return inst->frame;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// anim_get_frame()
|
||||
//
|
||||
// Get a bitmap id from the anim_instance for the specified frame_num
|
||||
//
|
||||
// input: *inst => pointer to anim instance
|
||||
// frame_num => frame number to get (first frame is 0)
|
||||
// xlate_pal => DEFAULT PARM (value 1): whether to translate the palette
|
||||
// to the current game palette
|
||||
//
|
||||
int anim_get_frame(anim_instance *inst, int frame_num, int xlate_pal)
|
||||
{
|
||||
/*
|
||||
int bm, bitmap_flags, key = 0, offset = 0;
|
||||
int idx;
|
||||
|
||||
if ((frame_num < 0) || (frame_num >= inst->parent->total_frames)) // illegal frame number
|
||||
return -1;
|
||||
|
||||
int need_reset = 0;
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
if ( inst->file_offset < 0 ) {
|
||||
need_reset = 1;
|
||||
}
|
||||
} else {
|
||||
if ( !inst->data ) {
|
||||
need_reset = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_reset || (inst->frame_num >= inst->parent->total_frames)) { // reset to valid info
|
||||
inst->data = inst->parent->data;
|
||||
inst->file_offset = inst->parent->file_offset;
|
||||
inst->frame_num = 0;
|
||||
}
|
||||
|
||||
bitmap_flags = 0;
|
||||
if (inst->parent->flags & ANF_XPARENT) {
|
||||
// bitmap_flags = BMP_XPARENT;
|
||||
bitmap_flags = 0;
|
||||
}
|
||||
|
||||
if ( inst->frame_num == frame_num ) {
|
||||
bm = bm_create(16, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
|
||||
bm_unload(bm);
|
||||
return bm;
|
||||
}
|
||||
|
||||
if (inst->parent->flags & ANF_XPARENT){
|
||||
// bitmap_flags = BMP_XPARENT;
|
||||
bitmap_flags = 0;
|
||||
} else {
|
||||
bitmap_flags = 0;
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
key = 0;
|
||||
while(idx < inst->parent->num_keys){
|
||||
if (( (inst->parent->keys[idx].frame_num-1) <= frame_num) && ( (inst->parent->keys[idx].frame_num-1) > key)) { // find closest key
|
||||
key = inst->parent->keys[idx].frame_num - 1;
|
||||
offset = inst->parent->keys[idx].offset;
|
||||
|
||||
if ( key == frame_num )
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
if ( key == frame_num ) {
|
||||
inst->frame_num = key;
|
||||
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
inst->file_offset = inst->parent->file_offset + offset;
|
||||
} else {
|
||||
inst->data = inst->parent->data + offset;
|
||||
}
|
||||
|
||||
anim_check_for_palette_change(inst);
|
||||
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
if ( xlate_pal ){
|
||||
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
||||
} else {
|
||||
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
||||
}
|
||||
} else {
|
||||
if ( xlate_pal ){
|
||||
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
||||
} else {
|
||||
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
goto create_bitmap;
|
||||
}
|
||||
|
||||
if (key > inst->frame_num) // best key is closer than current position
|
||||
{
|
||||
inst->frame_num = key;
|
||||
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
inst->file_offset = inst->parent->file_offset + offset;
|
||||
} else {
|
||||
inst->data = inst->parent->data + offset;
|
||||
}
|
||||
|
||||
anim_check_for_palette_change(inst);
|
||||
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
if ( xlate_pal )
|
||||
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
||||
else
|
||||
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
||||
} else {
|
||||
if ( xlate_pal )
|
||||
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
||||
else
|
||||
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
while (inst->frame_num != frame_num) {
|
||||
anim_check_for_palette_change(inst);
|
||||
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
if ( xlate_pal )
|
||||
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
||||
else
|
||||
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
||||
} else {
|
||||
if ( xlate_pal )
|
||||
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation);
|
||||
else
|
||||
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL);
|
||||
}
|
||||
inst->frame_num++;
|
||||
}
|
||||
|
||||
create_bitmap:
|
||||
|
||||
bm = bm_create(16, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
|
||||
bm_unload(bm);
|
||||
return bm;
|
||||
*/
|
||||
Int3();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// frame = frame pixel data to pack
|
||||
// save = memory to store packed data to
|
||||
// size = number of bytes to pack
|
||||
@@ -1173,7 +1025,7 @@ int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Int3(); // unknown packing method
|
||||
// unknown packing method
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,6 @@ void anim_init();
|
||||
anim_instance *init_anim_instance(anim *ptr, int bpp);
|
||||
void free_anim_instance(anim_instance *inst);
|
||||
int anim_get_next_frame(anim_instance *inst);
|
||||
int anim_get_frame(anim_instance *inst, int frame_num, int xlate_pal=1);
|
||||
ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp);
|
||||
void anim_set_palette(anim *a);
|
||||
void anim_check_for_palette_change(anim_instance *inst);
|
||||
|
||||
+199
-142
@@ -39,6 +39,7 @@ extern int Cmdline_autopilot_interruptable;
|
||||
// Module variables
|
||||
bool AutoPilotEngaged;
|
||||
bool UseCutsceneBars;
|
||||
bool LockWeaponsDuringAutopilot;
|
||||
int CurrentNav;
|
||||
float ramp_bias;
|
||||
NavPoint Navs[MAX_NAVPOINTS];
|
||||
@@ -55,6 +56,9 @@ bool CinematicStarted, CameraMoving;
|
||||
vec3d cameraPos, cameraTarget;
|
||||
std::map<int,int> autopilot_wings;
|
||||
|
||||
int AutopilotMinEnemyDistance;
|
||||
int AutopilotMinAsteroidDistance;
|
||||
|
||||
// used for ramping time compression;
|
||||
int start_dist;
|
||||
|
||||
@@ -149,12 +153,7 @@ char* NavPoint::GetInteralName()
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
// Tell us if autopilot is allowed
|
||||
// This needs:
|
||||
// * Nav point selected
|
||||
// * No enemies within X distance
|
||||
// * Destination > 1,000 meters away
|
||||
bool CanAutopilot(bool send_msg)
|
||||
bool CanAutopilot(vec3d targetPos, bool send_msg)
|
||||
{
|
||||
if (CurrentNav == -1)
|
||||
{
|
||||
@@ -162,99 +161,69 @@ bool CanAutopilot(bool send_msg)
|
||||
send_autopilot_msgID(NP_MSG_FAIL_NOSEL);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (object_get_gliding(Player_obj))
|
||||
{
|
||||
if (send_msg)
|
||||
send_autopilot_msgID(NP_MSG_FAIL_GLIDING);
|
||||
return false;
|
||||
}
|
||||
|
||||
// You cannot autopilot if you're within 1000 meters of your destination nav point
|
||||
if (vm_vec_dist_quick(&Player_obj->pos, Navs[CurrentNav].GetPosition()) < 1000)
|
||||
{
|
||||
if (vm_vec_dist_quick(&targetPos, Navs[CurrentNav].GetPosition()) < 1000) {
|
||||
if (send_msg)
|
||||
send_autopilot_msgID(NP_MSG_FAIL_TOCLOSE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// see if any hostiles are nearby
|
||||
for (ship_obj *so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so))
|
||||
{
|
||||
object *other_objp = &Objects[so->objnum];
|
||||
|
||||
// attacks player?
|
||||
if (iff_x_attacks_y(obj_team(other_objp), obj_team(Player_obj))
|
||||
&& !(Ship_info[Ships[other_objp->instance].ship_info_index].flags & SIF_CARGO))
|
||||
if ( AutopilotMinEnemyDistance > 0 ) {
|
||||
// see if any hostiles are nearby
|
||||
for (ship_obj *so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so))
|
||||
{
|
||||
// Cannot autopilot if enemy within 5,000 meters
|
||||
if (vm_vec_dist_quick(&Player_obj->pos, &other_objp->pos) < 5000)
|
||||
object *other_objp = &Objects[so->objnum];
|
||||
// attacks player?
|
||||
if (iff_x_attacks_y(obj_team(other_objp), obj_team(Player_obj))
|
||||
&& !(Ship_info[Ships[other_objp->instance].ship_info_index].flags & SIF_CARGO)) // ignore cargo
|
||||
{
|
||||
if (send_msg)
|
||||
send_autopilot_msgID(NP_MSG_FAIL_HOSTILES);
|
||||
return false;
|
||||
// Cannot autopilot if enemy within AutopilotMinEnemyDistance meters
|
||||
if (vm_vec_dist_quick(&targetPos, &other_objp->pos) < AutopilotMinEnemyDistance) {
|
||||
if (send_msg)
|
||||
send_autopilot_msgID(NP_MSG_FAIL_HOSTILES);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check for asteroids
|
||||
for (int n=0; n<MAX_ASTEROIDS; n++)
|
||||
{
|
||||
// asteroid
|
||||
if (Asteroids[n].flags & AF_USED)
|
||||
{
|
||||
// Cannot autopilot if asteroid within 1,000 meters
|
||||
if (vm_vec_dist_quick(&Player_obj->pos, &Objects[Asteroids[n].objnum].pos) < 1000)
|
||||
{
|
||||
if (send_msg)
|
||||
send_autopilot_msgID(NP_MSG_FAIL_HAZARD);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
// Tell us if autopilot is allowed at a certain position (only performs checks based on that position)
|
||||
// This needs:
|
||||
// * Nav point selected
|
||||
// * No enemies within X distance
|
||||
// * Destination > 1,000 meters away
|
||||
bool CanAutopilotPos(vec3d targetPos)
|
||||
{
|
||||
// You cannot autopilot if you're within 1000 meters of your destination nav point
|
||||
if (vm_vec_dist_quick(&targetPos, Navs[CurrentNav].GetPosition()) < 1000)
|
||||
return false;
|
||||
// see if any hostiles are nearby
|
||||
for (ship_obj *so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so))
|
||||
{
|
||||
object *other_objp = &Objects[so->objnum];
|
||||
// attacks player?
|
||||
if (iff_x_attacks_y(obj_team(other_objp), obj_team(Player_obj))
|
||||
&& !(Ship_info[Ships[other_objp->instance].ship_info_index].flags & SIF_CARGO)) // ignore cargo
|
||||
{
|
||||
// Cannot autopilot if enemy within 5,000 meters
|
||||
if (vm_vec_dist_quick(&targetPos, &other_objp->pos) < 5000)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//check for asteroids
|
||||
for (int n=0; n<MAX_ASTEROIDS; n++)
|
||||
{
|
||||
// asteroid
|
||||
if (Asteroids[n].flags & AF_USED)
|
||||
if ( AutopilotMinAsteroidDistance > 0 ) {
|
||||
//check for asteroids
|
||||
for (int n=0; n<MAX_ASTEROIDS; n++)
|
||||
{
|
||||
// Cannot autopilot if asteroid within 1,000 meters
|
||||
if (vm_vec_dist_quick(&targetPos, &Objects[Asteroids[n].objnum].pos) < 1000)
|
||||
return false;
|
||||
// asteroid
|
||||
if (Asteroids[n].flags & AF_USED)
|
||||
{
|
||||
// Cannot autopilot if asteroid within AutopilotMinAsteroidDistance meters
|
||||
if (vm_vec_dist_quick(&targetPos, &Objects[Asteroids[n].objnum].pos) < AutopilotMinAsteroidDistance) {
|
||||
if (send_msg)
|
||||
send_autopilot_msgID(NP_MSG_FAIL_HAZARD);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for support ships
|
||||
// cannot autopilot if support ship present
|
||||
if ( ship_find_repair_ship(Player_obj) != NULL ) {
|
||||
if (send_msg)
|
||||
send_autopilot_msgID(NP_MSG_FAIL_SUPPORT_PRESENT);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern object* Autopilot_flight_leader;
|
||||
// ********************************************************************************************
|
||||
// Engages autopilot
|
||||
// This does:
|
||||
@@ -263,13 +232,54 @@ bool CanAutopilotPos(vec3d targetPos)
|
||||
// * Lock time compression -WMC
|
||||
// * Tell AI to fly to targetted Nav Point (for all nav-status wings/ships)
|
||||
// * Sets max waypoint speed to the best-speed of the slowest ship tagged
|
||||
void StartAutopilot()
|
||||
bool StartAutopilot()
|
||||
{
|
||||
// Check for support ship and dismiss it if it is not doing anything.
|
||||
// If the support ship is doing something then tell the user such.
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
object* support_ship_op = ship_find_repair_ship(Player_obj);
|
||||
if ( support_ship_op == NULL ) {
|
||||
// no more
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Assert( support_ship_op->type == OBJ_SHIP );
|
||||
Assert( support_ship_op->instance >= 0 );
|
||||
Assert( support_ship_op->instance < MAX_SHIPS );
|
||||
Assert( Ships[support_ship_op->instance].ai_index != -1 );
|
||||
|
||||
ai_info* support_ship_aip = &(Ai_info[Ships[support_ship_op->instance].ai_index]);
|
||||
|
||||
// is support ship trying to rearm-repair
|
||||
if ( ai_find_goal_index( support_ship_aip->goals, AI_GOAL_REARM_REPAIR ) == -1 ) {
|
||||
// no, so tell it to depart
|
||||
ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_WARP, -1, NULL, support_ship_aip );
|
||||
} else {
|
||||
// yes
|
||||
send_autopilot_msgID(NP_MSG_FAIL_SUPPORT_WORKING);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
if (!CanAutopilot())
|
||||
return;
|
||||
return false;
|
||||
|
||||
AutoPilotEngaged = true;
|
||||
|
||||
// find the ship that is "leading" all of the ships when the player starts
|
||||
// autopilot
|
||||
// by default the ship that is leading the autopilot session the player's
|
||||
// wing leader (if the player is the wing leader then it will be the
|
||||
// player).
|
||||
// TODO:implement a way to allow a FREDer to say a different ship is leader
|
||||
Autopilot_flight_leader = get_wing_leader(Player_ship->wingnum);
|
||||
if ( Autopilot_flight_leader == NULL ) {
|
||||
// force player to be the leader if he doesn't have a wing
|
||||
Autopilot_flight_leader = Player_obj;
|
||||
}
|
||||
|
||||
if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)
|
||||
LockAPConv = timestamp(); // lock convergence instantly
|
||||
else
|
||||
@@ -328,10 +338,20 @@ void StartAutopilot()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// damp speed_cap to 90% of actual -- to make sure ships stay in formation
|
||||
if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS)
|
||||
speed_cap = 0.90f * speed_cap;
|
||||
|
||||
if ( speed_cap < 1.0f ) {
|
||||
/* We need to deal with this so that incorrectly flagged ships will not
|
||||
cause the engine to fail to limit all the ships speeds correctly. */
|
||||
Warning(LOCATION, "Ship speed cap is way too small (%f)!\n"
|
||||
"This is normally caused by a ship that has nav-carry-status set, but cannot move itself (like a Cargo container).\n"
|
||||
"Speed cap has been set to 1.0 m/s.",
|
||||
speed_cap);
|
||||
speed_cap = 1.0f;
|
||||
}
|
||||
|
||||
ramp_bias = speed_cap/50.0f;
|
||||
|
||||
// assign ship goals
|
||||
@@ -397,10 +417,10 @@ void StartAutopilot()
|
||||
vm_vector_2_matrix(&Objects[Ships[i].objnum].orient, &norm1, NULL, NULL);
|
||||
}
|
||||
|
||||
// snap wings into formation them into formation
|
||||
// snap wings into formation
|
||||
if (The_mission.flags & MISSION_FLAG_USE_AP_CINEMATICS && // only if using cinematics
|
||||
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY) // only if in a wing
|
||||
&& Player_obj != &Objects[Ships[i].objnum]) //only if not player object
|
||||
&& Autopilot_flight_leader != &Objects[Ships[i].objnum]) //only if not flight leader's object
|
||||
{
|
||||
ai_info *aip = &Ai_info[Ships[i].ai_index];
|
||||
int wingnum = aip->wing, wing_index = get_wing_index(&Objects[Ships[i].objnum], wingnum);
|
||||
@@ -419,33 +439,34 @@ void StartAutopilot()
|
||||
switch (wcount % 2)
|
||||
{
|
||||
case 1: // back-left
|
||||
vm_vec_add(&perp, &zero, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
//vm_vec_sub(&perp, &perp, &Player_obj->orient.vec.fvec);
|
||||
vm_vec_normalize(&perp);
|
||||
vm_vec_scale(&perp, -166.0f*j); // 166m is supposedly the optimal range according to tolwyn
|
||||
vm_vec_add(&goal_point, &Player_obj->pos, &perp);
|
||||
vm_vec_add(&goal_point, &Autopilot_flight_leader->pos, &perp);
|
||||
break;
|
||||
|
||||
default: //back-right
|
||||
case 0:
|
||||
vm_vec_add(&perp, &zero, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
//vm_vec_sub(&perp, &perp, &Player_obj->orient.vec.fvec);
|
||||
vm_vec_normalize(&perp);
|
||||
vm_vec_scale(&perp, 166.0f*j);
|
||||
vm_vec_add(&goal_point, &Player_obj->pos, &perp);
|
||||
vm_vec_add(&goal_point, &Autopilot_flight_leader->pos, &perp);
|
||||
break;
|
||||
}
|
||||
autopilot_wings[wingnum] = wcount;
|
||||
wcount++;
|
||||
}
|
||||
Objects[Ships[i].objnum].pos = goal_point;
|
||||
if (vm_vec_dist_quick(&Player_obj->pos, &Objects[Ships[i].objnum].pos) > distance)
|
||||
if (vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[i].objnum].pos) > distance)
|
||||
{
|
||||
distance = vm_vec_dist_quick(&Player_obj->pos, &Objects[Ships[i].objnum].pos);
|
||||
distance = vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[i].objnum].pos);
|
||||
}
|
||||
}
|
||||
// lock primary and secondary weapons
|
||||
//Ships[i].flags2 |= (SF2_PRIMARIES_LOCKED | SF2_SECONDARIES_LOCKED);
|
||||
if ( LockWeaponsDuringAutopilot )
|
||||
Ships[i].flags2 |= (SF2_PRIMARIES_LOCKED | SF2_SECONDARIES_LOCKED);
|
||||
|
||||
// clear the ship goals and cap the waypoint speed
|
||||
ai_clear_ship_goals(&Ai_info[Ships[i].ai_index]);
|
||||
@@ -540,9 +561,9 @@ void StartAutopilot()
|
||||
vec3d right, front, up, offset;
|
||||
for (i = 0; i < (int)capIndexes.size(); i++)
|
||||
{
|
||||
vm_vec_add(&right, &Player_obj->orient.vec.rvec, &zero);
|
||||
vm_vec_add(&front, &Player_obj->orient.vec.fvec, &zero);
|
||||
vm_vec_add(&up, &Player_obj->orient.vec.uvec, &zero);
|
||||
vm_vec_add(&right, &Autopilot_flight_leader->orient.vec.rvec, &zero);
|
||||
vm_vec_add(&front, &Autopilot_flight_leader->orient.vec.fvec, &zero);
|
||||
vm_vec_add(&up, &Autopilot_flight_leader->orient.vec.uvec, &zero);
|
||||
vm_vec_add(&offset, &zero, &zero);
|
||||
if (Ship_info[Ships[capIndexes[i]].ship_info_index].flags & (SIF_CAPITAL | SIF_SUPERCAP))
|
||||
{
|
||||
@@ -610,7 +631,7 @@ void StartAutopilot()
|
||||
vm_vec_scale(&up, (1+((float)floor((float)capship_placed[1]/3))));
|
||||
|
||||
// move ourselves up and out of the way of the smaller ships
|
||||
vm_vec_add(&perp, &Player_obj->orient.vec.uvec, &zero);
|
||||
vm_vec_add(&perp, &Autopilot_flight_leader->orient.vec.uvec, &zero);
|
||||
vm_vec_scale(&perp, capship_spreads[2]);
|
||||
vm_vec_add(&up, &up, &perp);
|
||||
|
||||
@@ -665,7 +686,7 @@ void StartAutopilot()
|
||||
vm_vec_scale(&front, 2*(1+((float)floor((float)capship_placed[2]/3))));
|
||||
|
||||
// move "out" by 166*(wcount-1) so we don't bump into fighters
|
||||
vm_vec_add(&perp, &Player_obj->orient.vec.rvec, &zero);
|
||||
vm_vec_add(&perp, &Autopilot_flight_leader->orient.vec.rvec, &zero);
|
||||
vm_vec_scale(&perp, 166.0f*float(wcount-1));
|
||||
if ( (capship_placed[2] % 2) == 0)
|
||||
vm_vec_add(&right, &right, &perp);
|
||||
@@ -687,16 +708,16 @@ void StartAutopilot()
|
||||
// global scale the position by 50%
|
||||
//vm_vec_scale(&offset, 1.5);
|
||||
|
||||
vm_vec_add(&Objects[Ships[capIndexes[i]].objnum].pos, &Player_obj->pos, &offset);
|
||||
vm_vec_add(&Objects[Ships[capIndexes[i]].objnum].pos, &Autopilot_flight_leader->pos, &offset);
|
||||
|
||||
if (vm_vec_dist_quick(&Player_obj->pos, &Objects[Ships[i].objnum].pos) > distance)
|
||||
if (vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[i].objnum].pos) > distance)
|
||||
{
|
||||
distance = vm_vec_dist_quick(&Player_obj->pos, &Objects[Ships[i].objnum].pos);
|
||||
distance = vm_vec_dist_quick(&Autopilot_flight_leader->pos, &Objects[Ships[i].objnum].pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ftemp = floor(Player_obj->phys_info.max_vel.xyz.z/speed_cap);
|
||||
ftemp = floor(Autopilot_flight_leader->phys_info.max_vel.xyz.z/speed_cap);
|
||||
if (ftemp >= 2.0f && ftemp < 4.0f)
|
||||
tc_factor = 2;
|
||||
else if (ftemp >= 4.0f && ftemp < 8.0f)
|
||||
@@ -708,11 +729,11 @@ void StartAutopilot()
|
||||
|
||||
tpos = *Navs[CurrentNav].GetPosition();
|
||||
// determine distance toward nav at which camera will be
|
||||
vm_vec_sub(&pos, &tpos, &Player_obj->pos);
|
||||
vm_vec_sub(&pos, &tpos, &Autopilot_flight_leader->pos);
|
||||
vm_vec_normalize(&pos); // pos is now a unit vector in the direction we will be moving the camera
|
||||
//norm1 = pos;
|
||||
vm_vec_scale(&pos, 5*speed_cap*tc_factor); // pos is now scaled by 5 times the speed (5 seconds ahead)
|
||||
vm_vec_add(&pos, &pos, &Player_obj->pos); // pos is now 5*speed cap in front of player ship
|
||||
vm_vec_add(&pos, &pos, &Autopilot_flight_leader->pos); // pos is now 5*speed cap in front of player ship
|
||||
|
||||
switch (myrand()%24)
|
||||
// 8 different ways of getting perp points
|
||||
@@ -723,74 +744,74 @@ void StartAutopilot()
|
||||
case 9:
|
||||
case 16:
|
||||
if (capship_placed[0] == 0)
|
||||
vm_vec_sub(&perp, &zero, &Player_obj->orient.vec.uvec);
|
||||
vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.uvec);
|
||||
else
|
||||
{ // become up-left
|
||||
vm_vec_add(&perp, &zero, &Player_obj->orient.vec.uvec);
|
||||
vm_vec_sub(&perp, &perp, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.uvec);
|
||||
vm_vec_sub(&perp, &perp, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // up
|
||||
case 10:
|
||||
case 23:
|
||||
vm_vec_add(&perp, &perp, &Player_obj->orient.vec.uvec);
|
||||
vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
|
||||
if (capshipPresent) // become up-right
|
||||
vm_vec_add(&perp, &perp, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
break;
|
||||
|
||||
case 3: // left
|
||||
case 11:
|
||||
case 22:
|
||||
vm_vec_sub(&perp, &zero, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
break;
|
||||
|
||||
case 4: // up-left
|
||||
case 12:
|
||||
case 21:
|
||||
vm_vec_sub(&perp, &zero, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_add(&perp, &perp, &Player_obj->orient.vec.uvec);
|
||||
vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
|
||||
break;
|
||||
|
||||
case 5: // up-right
|
||||
case 13:
|
||||
case 20:
|
||||
vm_vec_add(&perp, &zero, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_add(&perp, &perp, &Player_obj->orient.vec.uvec);
|
||||
vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
|
||||
break;
|
||||
|
||||
case 6: // down-left
|
||||
case 14:
|
||||
case 19:
|
||||
vm_vec_sub(&perp, &zero, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_sub(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
if (capship_placed[0] < 2)
|
||||
vm_vec_sub(&perp, &perp, &Player_obj->orient.vec.uvec);
|
||||
vm_vec_sub(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
|
||||
else
|
||||
vm_vec_add(&perp, &perp, &Player_obj->orient.vec.uvec);
|
||||
vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
|
||||
break;
|
||||
|
||||
case 7: // down-right
|
||||
case 15:
|
||||
case 18:
|
||||
vm_vec_add(&perp, &zero, &Player_obj->orient.vec.rvec);
|
||||
vm_vec_add(&perp, &zero, &Autopilot_flight_leader->orient.vec.rvec);
|
||||
if (capship_placed[0] < 1)
|
||||
vm_vec_sub(&perp, &perp, &Player_obj->orient.vec.uvec);
|
||||
vm_vec_sub(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
|
||||
else
|
||||
vm_vec_add(&perp, &perp, &Player_obj->orient.vec.uvec);
|
||||
vm_vec_add(&perp, &perp, &Autopilot_flight_leader->orient.vec.uvec);
|
||||
break;
|
||||
|
||||
default:
|
||||
case 0: // right
|
||||
case 8:
|
||||
case 17:
|
||||
perp = Player_obj->orient.vec.rvec;
|
||||
perp = Autopilot_flight_leader->orient.vec.rvec;
|
||||
break;
|
||||
|
||||
}
|
||||
vm_vec_normalize(&perp);
|
||||
//vm_vec_scale(&perp, 2*radius+distance);
|
||||
|
||||
vm_vec_scale(&perp, Player_obj->radius+radius);
|
||||
vm_vec_scale(&perp, Autopilot_flight_leader->radius+radius);
|
||||
|
||||
// randomly scale up/down by up to 20%
|
||||
j = 20-myrand()%40; // [-20,20]
|
||||
@@ -830,16 +851,8 @@ void StartAutopilot()
|
||||
camMovingTime = int(4.5*float(tc_factor));
|
||||
set_time_compression((float)tc_factor);
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
// Checks if autopilot should automatically die
|
||||
// Returns true if:
|
||||
// * Targetted waypoint < 10,000 meters away
|
||||
// * Enemy < 10,000 meters
|
||||
bool Autopilot_AutoDiable()
|
||||
{
|
||||
return !CanAutopilot();
|
||||
return true;
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
@@ -852,6 +865,8 @@ void EndAutoPilot()
|
||||
{
|
||||
AutoPilotEngaged = false;
|
||||
|
||||
Autopilot_flight_leader = NULL;
|
||||
|
||||
set_time_compression(1);
|
||||
lock_time_compression(false);
|
||||
Player_use_ai = 0;
|
||||
@@ -899,8 +914,10 @@ void EndAutoPilot()
|
||||
)
|
||||
{
|
||||
//unlock their weaponry
|
||||
//Ships[i].flags2 &= ~(SF2_PRIMARIES_LOCKED | SF2_SECONDARIES_LOCKED);
|
||||
if ( LockWeaponsDuringAutopilot )
|
||||
Ships[i].flags2 &= ~(SF2_PRIMARIES_LOCKED | SF2_SECONDARIES_LOCKED);
|
||||
Ai_info[Ships[i].ai_index].waypoint_speed_cap = -1; // uncap their speed
|
||||
Ai_info[Ships[i].ai_index].mode = AIM_NONE; // make AI re-evaluate current ship mode
|
||||
|
||||
for (j = 0; j < MAX_AI_GOALS; j++)
|
||||
{
|
||||
@@ -975,34 +992,54 @@ camera* nav_get_set_camera()
|
||||
|
||||
void nav_warp(bool prewarp=false)
|
||||
{
|
||||
// ok... find our end distance - norm1 is still a unit vector in the direction from the player to the navpoint
|
||||
vec3d targetPos, tpos=Player_obj->pos, pos;
|
||||
|
||||
vm_vec_sub(&pos, Navs[CurrentNav].GetPosition(), &Player_obj->pos);
|
||||
/* ok... find our end distance - norm1 is still a unit vector in the
|
||||
direction from the flight leader to the navpoint */
|
||||
vec3d targetPos, tpos=Autopilot_flight_leader->pos, pos, velocity;
|
||||
|
||||
/* calculate a vector that we can use to make a path from the flight
|
||||
leader's location to the nav point */
|
||||
vm_vec_sub(&pos, Navs[CurrentNav].GetPosition(), &Autopilot_flight_leader->pos);
|
||||
vm_vec_normalize(&pos);
|
||||
velocity = pos; // make a copy for later when we do setup veleocity vector
|
||||
vm_vec_scale(&pos, 250.0f); // we move by increments of 250
|
||||
|
||||
while (CanAutopilotPos(tpos))
|
||||
/* using the vector of the flight leaders's path, simulate moving the
|
||||
flight along this path by checking the autopilot conditions as specific
|
||||
intervals along the path*/
|
||||
while (CanAutopilot(tpos))
|
||||
{
|
||||
vm_vec_add(&tpos, &tpos, &pos);
|
||||
}
|
||||
vm_vec_sub(&targetPos, &tpos, &Player_obj->pos); //targetPos is actually a projection in a the direction toward the nav
|
||||
vm_vec_sub(&targetPos, &tpos, &Autopilot_flight_leader->pos);
|
||||
/* targetPos is actually a vector that describes the exact 3D movement that
|
||||
the flgith leader needs to execute to reach the location that the auto
|
||||
pilot is to shut off */
|
||||
|
||||
// Check if we are actually just setting up for the cinimatic shot of the
|
||||
// flight flying on autopilot. Only jump halfway. Also we also need to
|
||||
// put the camera in the correct position to show the player this cinimatic
|
||||
if (prewarp)
|
||||
{
|
||||
vm_vec_scale(&targetPos, 0.5);
|
||||
vm_vec_add(&cameraPos, &cameraPos, &targetPos);
|
||||
}
|
||||
|
||||
/* calcuate the speed that everyone is supposed to be going so that there
|
||||
is no need for anyone to accelerate or decelerate (most obvious with
|
||||
the player's fighter slowing down as it changes the camera pan speed). */
|
||||
Assert( Ai_info[Ships[Autopilot_flight_leader->instance].ai_index].waypoint_speed_cap > 0 );
|
||||
vm_vec_scale(&velocity, (float)Ai_info[Ships[Autopilot_flight_leader->instance].ai_index].waypoint_speed_cap);
|
||||
|
||||
// Find all ships that are supposed to autopilot with the player and move them
|
||||
// to the cinimatic location or the final destination
|
||||
for (int i = 0; i < MAX_SHIPS; i++)
|
||||
{
|
||||
if (Ships[i].objnum != -1 &&
|
||||
(Ships[i].flags2 & SF2_NAVPOINT_CARRY ||
|
||||
(Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY)
|
||||
)
|
||||
)
|
||||
if (Ships[i].objnum != -1
|
||||
&& (Ships[i].flags2 & SF2_NAVPOINT_CARRY
|
||||
|| (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY)))
|
||||
{
|
||||
vm_vec_add(&Objects[Ships[i].objnum].pos, &Objects[Ships[i].objnum].pos, &targetPos);
|
||||
Objects[Ships[i].objnum].phys_info.vel = velocity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1041,7 +1078,7 @@ void NavSystem_Do()
|
||||
}
|
||||
|
||||
|
||||
if (timestamp() >= EndAPCinematic || Autopilot_AutoDiable())
|
||||
if (timestamp() >= EndAPCinematic || !CanAutopilot())
|
||||
{
|
||||
nav_warp();
|
||||
EndAutoPilot();
|
||||
@@ -1060,7 +1097,7 @@ void NavSystem_Do()
|
||||
if(cam != NULL)
|
||||
{
|
||||
cam->set_position(&cameraPos);
|
||||
cam->set_rotation_facing(&Player_obj->pos);
|
||||
cam->set_rotation_facing(&Autopilot_flight_leader->pos);
|
||||
}
|
||||
|
||||
CinematicStarted = true;
|
||||
@@ -1068,7 +1105,7 @@ void NavSystem_Do()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Autopilot_AutoDiable())
|
||||
if (!CanAutopilot())
|
||||
EndAutoPilot();
|
||||
|
||||
}
|
||||
@@ -1141,7 +1178,10 @@ void NavSystem_Do()
|
||||
}
|
||||
}
|
||||
|
||||
// autopilot linking
|
||||
/* Link in any ships that need to be linked in when the player gets close
|
||||
enough. Always done by the player because: "making sure the AI fighters
|
||||
are where they're supposed to be at all times is like herding cats" -Woolie Wool
|
||||
*/
|
||||
for (int i = 0; i < MAX_SHIPS; i++)
|
||||
{
|
||||
if (Ships[i].objnum != -1 && Ships[i].flags2 & SF2_NAVPOINT_NEEDSLINK)
|
||||
@@ -1191,7 +1231,7 @@ void send_autopilot_msg(char *msg, char *snd)
|
||||
// send/play
|
||||
if (audio_handle != -1)
|
||||
{
|
||||
audiostream_play(audio_handle, Master_event_music_volume, 0);
|
||||
audiostream_play(audio_handle, (Master_event_music_volume * aav_music_volume), 0);
|
||||
}
|
||||
|
||||
if (strlen(msg) != 0 && strcmp(msg, "none"))
|
||||
@@ -1247,6 +1287,21 @@ void parse_autopilot_table(char *filename)
|
||||
required_string("$Link Distance:");
|
||||
stuff_int(&NavLinkDistance);
|
||||
|
||||
if (optional_string("$Interrupt autopilot if enemy within distance:"))
|
||||
stuff_int(&AutopilotMinEnemyDistance);
|
||||
else
|
||||
AutopilotMinEnemyDistance = 5000;
|
||||
|
||||
if (optional_string("$Interrupt autopilot if asteroid within distance:"))
|
||||
stuff_int(&AutopilotMinAsteroidDistance);
|
||||
else
|
||||
AutopilotMinAsteroidDistance = 1000;
|
||||
|
||||
if (optional_string("$Lock Weapons During Autopilot:"))
|
||||
stuff_boolean(&LockWeaponsDuringAutopilot);
|
||||
else
|
||||
LockWeaponsDuringAutopilot = false;
|
||||
|
||||
// optional no cutscene bars
|
||||
if (optional_string("+No_Cutscene_Bars"))
|
||||
UseCutsceneBars = false;
|
||||
@@ -1255,7 +1310,9 @@ void parse_autopilot_table(char *filename)
|
||||
Cmdline_autopilot_interruptable = 0;
|
||||
|
||||
// No Nav selected message
|
||||
char *msg_tags[] = { "$No Nav Selected:", "$Gliding:", "$Too Close:", "$Hostiles:", "$Linked:", "$Hazard:" };
|
||||
char *msg_tags[] = { "$No Nav Selected:", "$Gliding:",
|
||||
"$Too Close:", "$Hostiles:", "$Linked:", "$Hazard:",
|
||||
"$Support Present:", "$Support Working:" };
|
||||
for (int i = 0; i < NP_NUM_MESSAGES; i++)
|
||||
{
|
||||
required_string(msg_tags[i]);
|
||||
|
||||
+17
-13
@@ -8,6 +8,7 @@
|
||||
#define _AUTOPILOT_H_
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "object/object.h"
|
||||
#include <map>
|
||||
|
||||
// milliseconds between updates
|
||||
@@ -37,13 +38,15 @@ struct NavPoint
|
||||
};
|
||||
|
||||
|
||||
#define NP_NUM_MESSAGES 6
|
||||
#define NP_MSG_FAIL_NOSEL 0
|
||||
#define NP_MSG_FAIL_GLIDING 1
|
||||
#define NP_MSG_FAIL_TOCLOSE 2
|
||||
#define NP_MSG_FAIL_HOSTILES 3
|
||||
#define NP_MSG_MISC_LINKED 4
|
||||
#define NP_MSG_FAIL_HAZARD 5
|
||||
#define NP_MSG_FAIL_SUPPORT_PRESENT 6
|
||||
#define NP_MSG_FAIL_SUPPORT_WORKING 7
|
||||
#define NP_NUM_MESSAGES 8
|
||||
|
||||
struct NavMessage
|
||||
{
|
||||
@@ -62,27 +65,28 @@ extern std::map<int,int> autopilot_wings;
|
||||
bool Sel_NextNav();
|
||||
|
||||
|
||||
// Tell us is autopilot is allow
|
||||
// Tell us if autopilot is allowed
|
||||
// This needs:
|
||||
// * Nav point selected
|
||||
// * No enemies within 5,000 meters
|
||||
// * No enemies within AutopilotMinEnemyDistance meters
|
||||
// * No asteroids within AutopilotMinAsteroidDistance meters
|
||||
// * Destination > 1,000 meters away
|
||||
bool CanAutopilot(bool send_msg=false);
|
||||
bool CanAutopilotPos(vec3d targetPos);
|
||||
// * Support ship not present or is actively leaving
|
||||
bool CanAutopilot(vec3d targetPos, bool send_msg=false);
|
||||
|
||||
// Check if autopilot is allowed at player's current position
|
||||
// See CanAutopilot(vec3d, bool) for more information
|
||||
inline bool CanAutopilot(bool send_msg=false) { return CanAutopilot(Player_obj->pos, send_msg); }
|
||||
|
||||
// Engages autopilot
|
||||
// This does:
|
||||
// * Checks if Autopilot is allowed. See CanAutopilot() for conditions.
|
||||
// * Control switched from player to AI
|
||||
// * Time compression to 32x
|
||||
// * Tell AI to fly to targetted Nav Point (for all nav-status wings/ships)
|
||||
// * Sets max waypoint speed to the best-speed of the slowest ship tagged
|
||||
void StartAutopilot();
|
||||
|
||||
// Checks if autopilot should automatically die
|
||||
// Returns true if:
|
||||
// * Targetted waypoint < 1,000 meters away
|
||||
// * Enemy < 5,000 meters
|
||||
bool Autopilot_AutoDiable();
|
||||
// * Sets max waypoint speed to the best-speed of the slowest ship tagged
|
||||
// Returns false if autopilot cannot be started. True otherwise.
|
||||
bool StartAutopilot();
|
||||
|
||||
// Disengages autopilot
|
||||
// this does:
|
||||
|
||||
+5
-11
@@ -534,7 +534,7 @@ int bm_load( char *real_filename )
|
||||
}
|
||||
|
||||
if (free_slot < 0) {
|
||||
Int3();
|
||||
Assertion(free_slot < 0, "Could not find free BMPMAN slot for bitmap: %s", real_filename);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
@@ -1046,7 +1046,7 @@ int bm_get_info( int handle, int *w, int * h, ubyte * flags, int *nframes, int *
|
||||
}
|
||||
#endif
|
||||
|
||||
Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE!
|
||||
Assertion( bm_bitmaps[bitmapnum].handle == handle, "Invalid bitmap handle %d passed to bm_get_info().\nThis might be due to an invalid animation somewhere else.\n", handle ); // INVALID BITMAP HANDLE!
|
||||
|
||||
if ( (bm_bitmaps[bitmapnum].type == BM_TYPE_NONE) || (bm_bitmaps[bitmapnum].handle != handle) ) {
|
||||
if (w) *w = 0;
|
||||
@@ -1089,7 +1089,7 @@ unsigned int bm_get_signature(int handle)
|
||||
if ( !bm_inited ) bm_init();
|
||||
|
||||
int bitmapnum = handle % MAX_BITMAPS;
|
||||
Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE
|
||||
Assertion( bm_bitmaps[bitmapnum].handle == handle, "Invalid bitmap handle %d passed to bm_get_signature().\nThis might be due to an invalid animation somewhere else.\n", handle ); // INVALID BITMAP HANDLE!
|
||||
|
||||
return bm_bitmaps[bitmapnum].signature;
|
||||
}
|
||||
@@ -1100,7 +1100,7 @@ ubyte bm_get_type(int handle)
|
||||
if ( !bm_inited ) bm_init();
|
||||
|
||||
int bitmapnum = handle % MAX_BITMAPS;
|
||||
Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE
|
||||
Assertion( bm_bitmaps[bitmapnum].handle == handle, "Invalid bitmap handle %d passed to bm_get_type().\nThis might be due to an invalid animation somewhere else.\n", handle ); // INVALID BITMAP HANDLE!
|
||||
|
||||
return bm_bitmaps[bitmapnum].type;
|
||||
}
|
||||
@@ -1597,13 +1597,7 @@ bitmap * bm_lock( int handle, ubyte bpp, ubyte flags )
|
||||
|
||||
int bitmapnum = handle % MAX_BITMAPS;
|
||||
|
||||
#ifndef NDEBUG
|
||||
if(bm_bitmaps[bitmapnum].handle != handle) {
|
||||
mprintf(("bm_lock - %s: bm_bitmaps[%d].handle = %d, handle = %d\n", bm_bitmaps[bitmapnum].filename, bitmapnum, bm_bitmaps[bitmapnum].handle, handle));
|
||||
}
|
||||
#endif
|
||||
|
||||
Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE
|
||||
Assertion( bm_bitmaps[bitmapnum].handle == handle, "Invalid handle %d passed to bm_lock. This might be due to an animation elsewhere in the code being too short.\n", handle ); // INVALID BITMAP HANDLE
|
||||
|
||||
// flags &= (~BMP_RLE);
|
||||
|
||||
|
||||
+7
-49
@@ -147,9 +147,14 @@ int cfile_in_root_dir(char *exe_path)
|
||||
token_count++;
|
||||
tok = strtok(NULL, DIR_SEPARATOR_STR);
|
||||
} while(tok != NULL);
|
||||
|
||||
// root directory if we have <= 1 slash
|
||||
|
||||
#ifdef SCP_UNIX
|
||||
// /freespace works, / does not
|
||||
if(token_count <= 1) {
|
||||
#else
|
||||
// C:/freespace works, C:/ does not
|
||||
if(token_count <= 2){
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -813,53 +818,6 @@ CFILE *cfopen_special(char *file_path, char *mode, const int size, const int off
|
||||
// it's a normal file
|
||||
return cf_open_fill_cfblock(fp, dir_type);
|
||||
}
|
||||
|
||||
/* char longname[_MAX_PATH];
|
||||
|
||||
if ( !cfile_inited ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//================================================
|
||||
// Check that all the parameters make sense
|
||||
Assert( file_path && strlen(file_path) );
|
||||
Assert( mode != NULL );
|
||||
|
||||
if ( (ext_num <= 0) || (!ext_list) ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// cfopen_ext() only supports reading files, not creating them
|
||||
if ( strchr(mode, 'w') ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//================================================
|
||||
// Search for file on disk, on cdrom, or in a packfile
|
||||
|
||||
int offset, size;
|
||||
char copy_file_path[MAX_PATH_LEN]; // FIX change in memory from cf_find_file_location
|
||||
strcpy_s(copy_file_path, file_path);
|
||||
|
||||
if ( cf_find_file_location_ext(copy_file_path, ext_num, ext_list, dir_type, sizeof(longname) - 1, longname, &size, &offset, localize) ) {
|
||||
// Fount it, now create a cfile out of it
|
||||
FILE *fp = fopen( longname, "rb" );
|
||||
|
||||
if ( fp ) {
|
||||
if ( offset ) {
|
||||
// Found it in a pack file
|
||||
return cf_open_packed_cfblock(fp, dir_type, offset, size );
|
||||
} else {
|
||||
// Found it in a normal file
|
||||
return cf_open_fill_cfblock(fp, dir_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -136,8 +136,6 @@ Flag exe_params[] =
|
||||
{ "-3dwarp", "Enable 3d warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dwarp", },
|
||||
{ "-warp_flash", "Enable flash upon warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-warp_flash", },
|
||||
{ "-no_ap_interrupt", "Disable interrupting autopilot", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ap_interrupt", },
|
||||
{ "-tbp", "Toggle features for The Babylon Project", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-tbp", }, // TBP warp effects -Et1
|
||||
{ "-wcsaga", "Toggle features for Wing Commander Saga", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-wcsaga", },
|
||||
|
||||
{ "-snd_preload", "Preload mission game sounds", true, EASY_MEM_ALL_ON, EASY_DEFAULT_MEM, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-snd_preload", },
|
||||
{ "-nosound", "Disable sound and music", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
|
||||
@@ -175,7 +173,7 @@ Flag exe_params[] =
|
||||
{ "-pos", "Show position of camera", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pos", },
|
||||
{ "-window", "Run in window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-window", },
|
||||
{ "-fullscreen_window", "Run in fullscreen window", false, 0, EASY_DEFAULT, "Dev Tool", "", },
|
||||
{ "-timerbar", "", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-timerbar", },
|
||||
|
||||
{ "-stats", "Show statistics", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stats", },
|
||||
{ "-coords", "Show coordinates", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-coords", },
|
||||
{ "-show_mem_usage", "Show memory usage", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-show_mem_usage", },
|
||||
@@ -335,10 +333,8 @@ int Cmdline_voice_recognition = 0;
|
||||
|
||||
// MOD related
|
||||
cmdline_parm mod_arg("-mod", NULL, true); // Cmdline_mod -- DTP modsupport
|
||||
cmdline_parm tbp("-tbp", NULL); // Cmdline_tbp -- TBP warp effects -Et1
|
||||
|
||||
char *Cmdline_mod = NULL; //DTP for mod arguement
|
||||
int Cmdline_tbp = 0;
|
||||
|
||||
// Multiplayer/Network related
|
||||
cmdline_parm almission_arg("-almission", NULL); // Cmdline_almission -- DTP for autoload Multi mission
|
||||
@@ -920,7 +916,9 @@ bool SetCmdlineParams()
|
||||
}
|
||||
|
||||
if (timerbar_arg.found()) {
|
||||
Cmdline_timerbar = 1;
|
||||
#ifdef WIN32
|
||||
MessageBox(NULL, "the timerbar has been disabled in builds after August 31, 2010. Please remove the \"-timerbar\" command line from the launcher to prevent this message from appearing the the future.", "", MB_OK | MB_ICONINFORMATION);
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( missioncrcspew_arg.found() ) {
|
||||
@@ -1182,16 +1180,6 @@ bool SetCmdlineParams()
|
||||
Cmdline_orb_radar = 1;
|
||||
}
|
||||
|
||||
// TBP warp effects -Et1
|
||||
// Chief1983 - Add 3d shockwave, ship choice 3d and weapon choice 3d if TBP is checked
|
||||
if( tbp.found() )
|
||||
{
|
||||
Cmdline_tbp = 1;
|
||||
Cmdline_enable_3d_shockwave = 1;
|
||||
Cmdline_ship_choice_3d = 1;
|
||||
Cmdline_weapon_choice_3d = 1;
|
||||
}
|
||||
|
||||
if ( use_3dwarp.found() ) {
|
||||
Cmdline_3dwarp = 1;
|
||||
}
|
||||
|
||||
@@ -104,8 +104,6 @@ extern int Cmdline_voice_recognition;
|
||||
|
||||
// MOD related
|
||||
extern char *Cmdline_mod; // DTP for mod support
|
||||
extern int Cmdline_tbp;
|
||||
|
||||
// Multiplayer/Network related
|
||||
extern char *Cmdline_almission; // DTP for autoload mission (for multi only)
|
||||
extern int Cmdline_ingamejoin;
|
||||
|
||||
@@ -922,7 +922,9 @@ int fireball_create( vec3d * pos, int fireball_type, int render_type, int parent
|
||||
}
|
||||
|
||||
if ( fb->fireball_render_type == FIREBALL_WARP_EFFECT ) {
|
||||
Assert( warp_lifetime > 4.0f ); // Warp lifetime must be at least 4 seconds!
|
||||
Assert( warp_lifetime >= 4.0f ); // Warp lifetime must be at least 4 seconds!
|
||||
if ( warp_lifetime < 4.0f )
|
||||
warp_lifetime = 4.0f;
|
||||
fb->total_time = warp_lifetime; // in seconds
|
||||
} else {
|
||||
fb->total_time = i2fl(fl->num_frames) / fl->fps; // in seconds
|
||||
|
||||
+37
-2
@@ -28,6 +28,8 @@
|
||||
#include "debugconsole/dbugfile.h"
|
||||
#include "globalincs/mspdb_callstack.h"
|
||||
|
||||
#include "AFXADV.H"
|
||||
|
||||
#ifdef NDEBUG
|
||||
#ifndef FRED
|
||||
#error macro FRED is not defined when trying to build release Fred. Please define FRED macro in build settings in all Fred projects
|
||||
@@ -80,12 +82,12 @@ window_data Mission_notes_wnd_data;
|
||||
BEGIN_MESSAGE_MAP(CFREDApp, CWinApp)
|
||||
//{{AFX_MSG_MAP(CFREDApp)
|
||||
ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
|
||||
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
|
||||
// NOTE - the ClassWizard will add and remove mapping macros here.
|
||||
// DO NOT EDIT what you see in these blocks of generated code!
|
||||
//}}AFX_MSG_MAP
|
||||
// Standard file based document commands
|
||||
ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
|
||||
ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
|
||||
// Standard print setup command
|
||||
ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
|
||||
END_MESSAGE_MAP()
|
||||
@@ -236,9 +238,23 @@ BOOL CFREDApp::InitInstance()
|
||||
*str_end = '\0';
|
||||
|
||||
|
||||
// Goober5000 - figure out where the FRED file dialog should go
|
||||
if ((m_pRecentFileList != NULL) && (m_pRecentFileList->GetSize() > 0))
|
||||
{
|
||||
// use the most recently opened file to supply the default folder
|
||||
m_sInitialDir = m_pRecentFileList->operator[](0); // lol syntax
|
||||
}
|
||||
else
|
||||
{
|
||||
// use FRED's own directory to search for missions
|
||||
m_sInitialDir = Fred_base_dir;
|
||||
m_sInitialDir += "\\data\\missions";
|
||||
}
|
||||
|
||||
|
||||
// Parse command line for standard shell commands, DDE, file open
|
||||
CCommandLineInfo cmdInfo;
|
||||
ParseCommandLine(cmdInfo);
|
||||
ParseCommandLine(cmdInfo);
|
||||
|
||||
m_nCmdShow = Main_wnd_data.p.showCmd;
|
||||
|
||||
@@ -309,6 +325,25 @@ void CFREDApp::OnAppAbout()
|
||||
aboutDlg.DoModal();
|
||||
}
|
||||
|
||||
// G5K - from http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/Q_20155824.html
|
||||
void CFREDApp::OnFileOpen()
|
||||
{
|
||||
// use the initial dir the first time we prompt for a file
|
||||
// name. after a successful open, the file name will be
|
||||
// changed to be the empty string and the default dir
|
||||
// will be supplied by the CFileDialog internal memory
|
||||
if(!DoPromptFileName(m_sInitialDir, AFX_IDS_OPENFILE, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, NULL))
|
||||
{
|
||||
// open cancelled
|
||||
return;
|
||||
}
|
||||
AfxGetApp()->OpenDocumentFile(m_sInitialDir);
|
||||
// if returns NULL, the user has already been alerted
|
||||
|
||||
// now erase the initial dir since we only want to use it once
|
||||
m_sInitialDir.Empty();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CFREDApp commands
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ typedef struct window_data {
|
||||
class CFREDApp : public CWinApp
|
||||
{
|
||||
int app_init;
|
||||
CString m_sInitialDir;
|
||||
|
||||
public:
|
||||
void record_window_data(window_data *wndd, CWnd *wnd);
|
||||
@@ -75,6 +76,7 @@ public:
|
||||
|
||||
//{{AFX_MSG(CFREDApp)
|
||||
afx_msg void OnAppAbout();
|
||||
afx_msg void OnFileOpen();
|
||||
// NOTE - the ClassWizard will add and remove member functions here.
|
||||
// DO NOT EDIT what you see in these blocks of generated code !
|
||||
//}}AFX_MSG
|
||||
|
||||
+9
-5
@@ -2457,17 +2457,18 @@ BEGIN
|
||||
WS_TABSTOP
|
||||
LTEXT "Example",IDC_LBL_EXAMPLE,17,158,31,10
|
||||
EDITTEXT IDC_EXAMPLE,49,156,77,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
CONTROL "Don't replace existing file names",IDC_NO_REPLACE,
|
||||
CONTROL "Include sender name in filename",IDC_INCLUDE_SENDER,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,175,112,10
|
||||
PUSHBUTTON "Generate File Names",IDC_GENERATE_FILE_NAMES,12,190,120,
|
||||
14
|
||||
CONTROL "Don't replace existing file names",IDC_NO_REPLACE,
|
||||
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,186,112,10
|
||||
PUSHBUTTON "Generate File Names",IDC_GENERATE_FILE_NAMES,12,198,120,14
|
||||
GROUPBOX "Script Options",IDC_SCRIPT_OPTIONS,143,7,257,204
|
||||
GROUPBOX "Script Entry Format",IDC_ENTRY,149,17,246,76
|
||||
EDITTEXT IDC_ENTRY_FORMAT,154,28,109,56,ES_MULTILINE |
|
||||
ES_AUTOHSCROLL | ES_WANTRETURN
|
||||
LTEXT "$filename - name of the message file\r\n$message - text of the message\r\n$persona - persona of the sender\r\n$sender - name of the sender\r\n\r\nNote that $persona and $sender will only appear for the Message section.",
|
||||
IDC_STATIC,270,28,120,58
|
||||
GROUPBOX "Export",IDC_EXPORT,149,98,119,64
|
||||
GROUPBOX "Export",IDC_EXPORT,149,98,119,83
|
||||
CONTROL "Everything",IDC_EXPORT_EVERYTHING,"Button",
|
||||
BS_AUTORADIOBUTTON,153,108,99,9
|
||||
CONTROL "Just Command Briefings",IDC_EXPORT_COMMAND_BRIEFINGS,
|
||||
@@ -2479,6 +2480,9 @@ BEGIN
|
||||
CONTROL "Just Messages",IDC_EXPORT_MESSAGES,"Button",
|
||||
BS_AUTORADIOBUTTON,153,148,99,9
|
||||
PUSHBUTTON "Generate Script",IDC_GENERATE_SCRIPT,149,190,120,14
|
||||
CONTROL "Group send-message-list messages before others",
|
||||
IDC_GROUP_MESSAGES,"Button",BS_AUTOCHECKBOX | BS_TOP |
|
||||
BS_MULTILINE | WS_TABSTOP,166,159,100,19
|
||||
END
|
||||
|
||||
IDD_BRIEFING_PERSONAS DIALOG DISCARDABLE 0, 0, 320, 201
|
||||
@@ -2559,7 +2563,7 @@ END
|
||||
IDD_SOUND_ENVIRONMENT DIALOGEX 0, 0, 315, 89
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Sound Environment"
|
||||
FONT 8, "MS Sans Serif"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x1
|
||||
BEGIN
|
||||
COMBOBOX IDC_SOUND_ENVIRONMENT,75,9,117,30,CBS_DROPDOWN |
|
||||
WS_VSCROLL | WS_TABSTOP
|
||||
|
||||
@@ -188,7 +188,6 @@ int Framerate_delay;
|
||||
void game_start_time(){}
|
||||
void game_stop_time(){}
|
||||
int game_get_default_skill_level(){return 0;}
|
||||
void game_load_palette(){}
|
||||
float FreeSpace_gamma;
|
||||
int set_cdrom_path(int){return 0;}
|
||||
int find_freespace_cd(char*){return 0;}
|
||||
|
||||
@@ -1139,6 +1139,8 @@
|
||||
#define IDC_SOUND_ENVIRONMENT_DECAY 1625
|
||||
#define IDC_SOUND_ENVIRONMENT_BUTTON 1626
|
||||
#define IDC_SOUND_ENVIRONMENT_TEST 1627
|
||||
#define IDC_GROUP_MESSAGES 1628
|
||||
#define IDC_INCLUDE_SENDER 1629
|
||||
#define ID_FILE_MISSIONNOTES 32771
|
||||
#define ID_DUPLICATE 32774
|
||||
#define ID_VIEW_ROTATE 32775
|
||||
@@ -1432,7 +1434,7 @@
|
||||
#define _APS_3D_CONTROLS 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 320
|
||||
#define _APS_NEXT_COMMAND_VALUE 33098
|
||||
#define _APS_NEXT_CONTROL_VALUE 1628
|
||||
#define _APS_NEXT_CONTROL_VALUE 1629
|
||||
#define _APS_NEXT_SYMED_VALUE 105
|
||||
#endif
|
||||
#endif
|
||||
@@ -2576,6 +2576,11 @@ int sexp_tree::get_default_value(sexp_list_item *item, int op, int i)
|
||||
|
||||
case OPF_FONT:
|
||||
str = Fonts[0].filename;
|
||||
break;
|
||||
|
||||
case OPF_AUDIO_VOLUME_OPTION:
|
||||
str = "Music";
|
||||
break;
|
||||
|
||||
default:
|
||||
str = "<new default required!>";
|
||||
@@ -2660,6 +2665,9 @@ int sexp_tree::query_default_argument_available(int op, int i)
|
||||
case OPF_HUD_ELEMENT:
|
||||
case OPF_SOUND_ENVIRONMENT:
|
||||
case OPF_SOUND_ENVIRONMENT_OPTION:
|
||||
case OPF_EXPLOSION_OPTION:
|
||||
case OPF_AUDIO_VOLUME_OPTION:
|
||||
case OPF_WEAPON_BANK_NUMBER:
|
||||
return 1;
|
||||
|
||||
case OPF_SHIP:
|
||||
@@ -4369,6 +4377,18 @@ sexp_list_item *sexp_tree::get_listing_opf(int opf, int parent_node, int arg_ind
|
||||
list = get_listing_opf_sound_environment_option();
|
||||
break;
|
||||
|
||||
case OPF_AUDIO_VOLUME_OPTION:
|
||||
list = get_listing_opf_adjust_audio_volume();
|
||||
break;
|
||||
|
||||
case OPF_EXPLOSION_OPTION:
|
||||
list = get_listing_opf_explosion_option();
|
||||
break;
|
||||
|
||||
case OPF_WEAPON_BANK_NUMBER:
|
||||
list = get_listing_opf_weapon_banks();
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3(); // unknown OPF code
|
||||
list = NULL;
|
||||
@@ -5234,6 +5254,26 @@ sexp_list_item *sexp_tree::get_listing_opf_sound_environment_option()
|
||||
return head.next;
|
||||
}
|
||||
|
||||
sexp_list_item *sexp_tree::get_listing_opf_adjust_audio_volume()
|
||||
{
|
||||
sexp_list_item head;
|
||||
|
||||
for (int i = 0; i < Num_adjust_audio_options; i++)
|
||||
head.add_data(Adjust_audio_options[i]);
|
||||
|
||||
return head.next;
|
||||
}
|
||||
|
||||
sexp_list_item *sexp_tree::get_listing_opf_explosion_option()
|
||||
{
|
||||
sexp_list_item head;
|
||||
|
||||
for (int i = 0; i < Num_explosion_options; i++)
|
||||
head.add_data(Explosion_option[i]);
|
||||
|
||||
return head.next;
|
||||
}
|
||||
|
||||
sexp_list_item *sexp_tree::get_listing_opf_waypoint_path()
|
||||
{
|
||||
int i;
|
||||
@@ -5464,7 +5504,7 @@ sexp_list_item *sexp_tree::get_listing_opf_string()
|
||||
{
|
||||
sexp_list_item head;
|
||||
|
||||
head.add_data("<any string>");
|
||||
head.add_data(SEXP_ANY_STRING);
|
||||
|
||||
return head.next;
|
||||
}
|
||||
@@ -5731,6 +5771,14 @@ sexp_list_item *sexp_tree::get_listing_opf_hud_elements()
|
||||
return head.next;
|
||||
}
|
||||
|
||||
sexp_list_item *sexp_tree::get_listing_opf_weapon_banks()
|
||||
{
|
||||
sexp_list_item head;
|
||||
head.add_data(SEXP_ALL_BANKS_STRING);
|
||||
|
||||
return head.next;
|
||||
}
|
||||
|
||||
// Deletes sexp_variable from sexp_tree.
|
||||
// resets tree to not include given variable, and resets text and type
|
||||
void sexp_tree::delete_sexp_tree_variable(const char *var_name)
|
||||
|
||||
@@ -260,6 +260,9 @@ public:
|
||||
sexp_list_item *get_listing_opf_hud_elements();
|
||||
sexp_list_item *get_listing_opf_sound_environment();
|
||||
sexp_list_item *get_listing_opf_sound_environment_option();
|
||||
sexp_list_item *get_listing_opf_explosion_option();
|
||||
sexp_list_item *get_listing_opf_adjust_audio_volume();
|
||||
sexp_list_item *get_listing_opf_weapon_banks();
|
||||
|
||||
int m_mode;
|
||||
int item_index;
|
||||
|
||||
@@ -2,14 +2,18 @@
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <string.h>
|
||||
#include "fred.h"
|
||||
#include "fred2/freddoc.h"
|
||||
#include "VoiceActingManager.h"
|
||||
#include "missionui/missioncmdbrief.h"
|
||||
#include "mission/missionbriefcommon.h"
|
||||
#include "mission/missionmessage.h"
|
||||
#include "mission/missiongoals.h"
|
||||
#include "hud/hudtarget.h"
|
||||
#include "parse/sexp.h"
|
||||
#include "iff_defs/iff_defs.h"
|
||||
#include "mission/missiongoals.h"
|
||||
#include <math.h>
|
||||
|
||||
#ifdef _DEBUG
|
||||
@@ -18,6 +22,8 @@
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
#define INVALID_MESSAGE ((MMessage*)0xFFFFFFFF)
|
||||
|
||||
// to keep track of data
|
||||
char Voice_abbrev_briefing[NAME_LENGTH];
|
||||
char Voice_abbrev_campaign[NAME_LENGTH];
|
||||
@@ -28,6 +34,7 @@ char Voice_abbrev_mission[NAME_LENGTH];
|
||||
bool Voice_no_replace_filenames;
|
||||
char Voice_script_entry_format[NOTES_LENGTH];
|
||||
int Voice_export_selection;
|
||||
bool Voice_group_messages;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -44,6 +51,7 @@ VoiceActingManager::VoiceActingManager(CWnd* pParent /*=NULL*/)
|
||||
m_abbrev_debriefing = _T("");
|
||||
m_abbrev_message = _T("");
|
||||
m_abbrev_mission = _T("");
|
||||
m_use_sender_in_filename = FALSE;
|
||||
m_example = _T("");
|
||||
m_no_replace = FALSE;
|
||||
m_script_entry_format = _T("");
|
||||
@@ -52,6 +60,7 @@ VoiceActingManager::VoiceActingManager(CWnd* pParent /*=NULL*/)
|
||||
m_export_briefings = FALSE;
|
||||
m_export_debriefings = FALSE;
|
||||
m_export_messages = FALSE;
|
||||
m_group_messages = FALSE;
|
||||
//}}AFX_DATA_INIT
|
||||
}
|
||||
|
||||
@@ -68,12 +77,14 @@ void VoiceActingManager::DoDataExchange(CDataExchange* pDX)
|
||||
DDX_Text(pDX, IDC_ABBREV_MISSION, m_abbrev_mission);
|
||||
DDX_Text(pDX, IDC_EXAMPLE, m_example);
|
||||
DDX_Check(pDX, IDC_NO_REPLACE, m_no_replace);
|
||||
DDX_Check(pDX, IDC_INCLUDE_SENDER, m_use_sender_in_filename);
|
||||
DDX_Text(pDX, IDC_ENTRY_FORMAT, m_script_entry_format);
|
||||
DDX_Check(pDX, IDC_EXPORT_EVERYTHING, m_export_everything);
|
||||
DDX_Check(pDX, IDC_EXPORT_COMMAND_BRIEFINGS, m_export_command_briefings);
|
||||
DDX_Check(pDX, IDC_EXPORT_BRIEFINGS, m_export_briefings);
|
||||
DDX_Check(pDX, IDC_EXPORT_DEBRIEFINGS, m_export_debriefings);
|
||||
DDX_Check(pDX, IDC_EXPORT_MESSAGES, m_export_messages);
|
||||
DDX_Check(pDX, IDC_GROUP_MESSAGES, m_group_messages);
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
@@ -98,6 +109,12 @@ BEGIN_MESSAGE_MAP(VoiceActingManager, CDialog)
|
||||
ON_BN_CLICKED(IDC_NO_REPLACE, OnChangeNoReplace)
|
||||
ON_BN_CLICKED(IDC_GENERATE_FILE_NAMES, OnGenerateFileNames)
|
||||
ON_BN_CLICKED(IDC_GENERATE_SCRIPT, OnGenerateScript)
|
||||
ON_BN_CLICKED(IDC_EXPORT_EVERYTHING, OnExportEverything)
|
||||
ON_BN_CLICKED(IDC_EXPORT_COMMAND_BRIEFINGS, OnExportCommandBriefings)
|
||||
ON_BN_CLICKED(IDC_EXPORT_BRIEFINGS, OnExportBriefings)
|
||||
ON_BN_CLICKED(IDC_EXPORT_DEBRIEFINGS, OnExportDebriefings)
|
||||
ON_BN_CLICKED(IDC_EXPORT_MESSAGES, OnExportMessages)
|
||||
ON_BN_CLICKED(IDC_INCLUDE_SENDER, OnBnClickedIncludeSender)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
@@ -133,6 +150,10 @@ BOOL VoiceActingManager::OnInitDialog()
|
||||
m_export_messages = TRUE;
|
||||
else
|
||||
m_export_everything = TRUE;
|
||||
m_group_messages = Voice_group_messages;
|
||||
|
||||
CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
|
||||
button->EnableWindow(m_export_everything || m_export_messages);
|
||||
|
||||
UpdateData(FALSE);
|
||||
|
||||
@@ -150,7 +171,7 @@ void VoiceActingManager::OnClose()
|
||||
strcpy_s(Voice_abbrev_debriefing, m_abbrev_debriefing);
|
||||
strcpy_s(Voice_abbrev_message, m_abbrev_message);
|
||||
strcpy_s(Voice_abbrev_mission, m_abbrev_mission);
|
||||
Voice_no_replace_filenames = m_no_replace == TRUE ? true : false;
|
||||
Voice_no_replace_filenames = (m_no_replace == TRUE) ? true : false;
|
||||
|
||||
// save data for script
|
||||
strcpy_s(Voice_script_entry_format, m_script_entry_format);
|
||||
@@ -164,6 +185,7 @@ void VoiceActingManager::OnClose()
|
||||
Voice_export_selection = 4;
|
||||
else
|
||||
Voice_export_selection = 0;
|
||||
Voice_group_messages = (m_group_messages == TRUE) ? true : false;
|
||||
|
||||
CDialog::OnClose();
|
||||
}
|
||||
@@ -213,10 +235,10 @@ void VoiceActingManager::build_example(CString section)
|
||||
return;
|
||||
}
|
||||
|
||||
m_example = generate_filename(section, 1, 2);
|
||||
m_example = generate_filename(section, 1, 2, INVALID_MESSAGE);
|
||||
}
|
||||
|
||||
CString VoiceActingManager::generate_filename(CString section, int number, int digits)
|
||||
CString VoiceActingManager::generate_filename(CString section, int number, int digits, MMessage *message)
|
||||
{
|
||||
if (section == "")
|
||||
return "none.wav";
|
||||
@@ -241,9 +263,52 @@ CString VoiceActingManager::generate_filename(CString section, int number, int d
|
||||
}
|
||||
str = str + num;
|
||||
|
||||
|
||||
const CString suffix = get_suffix();
|
||||
// append sender name if supposed to and I have been passed a message
|
||||
// to get the sender from
|
||||
if ( message != NULL && m_use_sender_in_filename ) {
|
||||
size_t allow_to_copy = NAME_LENGTH - suffix.GetLength() - str.GetLength();
|
||||
char sender[NAME_LENGTH];
|
||||
if ( message == INVALID_MESSAGE ) {
|
||||
strcpy_s(sender, "Alpha 1");
|
||||
} else {
|
||||
get_valid_sender(sender, sizeof(sender), message);
|
||||
}
|
||||
|
||||
// truncate sender to that we don't overflow filename
|
||||
sender[allow_to_copy] = '\0';
|
||||
size_t j;
|
||||
for( j = 0; sender[j] != '\0'; j++ ) {
|
||||
// lower case letter
|
||||
sender[j] = (char)tolower(sender[j]);
|
||||
|
||||
// replace any non alpha numeric with a underscore
|
||||
if ( !isalnum( sender[j] ) )
|
||||
sender[j] = '_';
|
||||
}
|
||||
|
||||
// flatten muliple underscores
|
||||
j = 1;
|
||||
while( sender[j] != '\0' ) {
|
||||
if ( sender[j-1] == '_' && sender[j] == '_' ) {
|
||||
size_t k;
|
||||
for (k = j + 1; sender[k] != '\0'; k++ )
|
||||
sender[k - 1] = sender[k];
|
||||
sender[k - 1] = '\0';
|
||||
} else {
|
||||
// only increment on rounds when I am not moving the string down
|
||||
j++;
|
||||
}
|
||||
}
|
||||
str = str + sender;
|
||||
}
|
||||
|
||||
// suffix
|
||||
str = str + get_suffix();
|
||||
|
||||
Assert( str.GetLength() < NAME_LENGTH );
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -251,6 +316,7 @@ void VoiceActingManager::OnGenerateFileNames()
|
||||
{
|
||||
int i;
|
||||
int digits;
|
||||
size_t modified_filenames = 0;
|
||||
|
||||
// stuff data to variables
|
||||
UpdateData(TRUE);
|
||||
@@ -262,9 +328,10 @@ void VoiceActingManager::OnGenerateFileNames()
|
||||
char *filename = Cmd_briefs[0].stage[i].wave_filename;
|
||||
|
||||
// generate only if we're replacing or if it has a replaceable name
|
||||
if (!m_no_replace || !strlen(filename) || !strnicmp(filename, "none.wav", 4) || message_filename_is_generic(filename))
|
||||
if (!m_no_replace || !strlen(filename) || message_filename_is_generic(filename))
|
||||
{
|
||||
strcpy(filename, LPCTSTR(generate_filename(m_abbrev_command_briefing, i + 1, digits)));
|
||||
modified_filenames++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,9 +342,10 @@ void VoiceActingManager::OnGenerateFileNames()
|
||||
char *filename = Briefings[0].stages[i].voice;
|
||||
|
||||
// generate only if we're replacing or if it has a replaceable name
|
||||
if (!m_no_replace || !strlen(filename) || !strnicmp(filename, "none.wav", 4) || message_filename_is_generic(filename))
|
||||
if (!m_no_replace || !strlen(filename) || message_filename_is_generic(filename))
|
||||
{
|
||||
strcpy(filename, LPCTSTR(generate_filename(m_abbrev_briefing, i + 1, digits)));
|
||||
modified_filenames++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,9 +356,10 @@ void VoiceActingManager::OnGenerateFileNames()
|
||||
char *filename = Debriefings[0].stages[i].voice;
|
||||
|
||||
// generate only if we're replacing or if it has a replaceable name
|
||||
if (!m_no_replace || !strlen(filename) || !strnicmp(filename, "none.wav", 4) || message_filename_is_generic(filename))
|
||||
if (!m_no_replace || !strlen(filename) || message_filename_is_generic(filename))
|
||||
{
|
||||
strcpy(filename, LPCTSTR(generate_filename(m_abbrev_debriefing, i + 1, digits)));
|
||||
modified_filenames++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,21 +368,30 @@ void VoiceActingManager::OnGenerateFileNames()
|
||||
for (i = 0; i < Num_messages - Num_builtin_messages; i++)
|
||||
{
|
||||
char *filename = Messages[i + Num_builtin_messages].wave_info.name;
|
||||
MMessage *message = &Messages[i + Num_builtin_messages];
|
||||
|
||||
// generate only if we're replacing or if it has a replaceable name
|
||||
if (!m_no_replace || !filename || !strlen(filename) || !strnicmp(filename, "none.wav", 4) || message_filename_is_generic(filename))
|
||||
if (!m_no_replace || !strlen(filename) || !strlen(filename) || message_filename_is_generic(filename))
|
||||
{
|
||||
// free existing filename
|
||||
if (filename != NULL)
|
||||
free(filename);
|
||||
|
||||
// allocate new filename
|
||||
Messages[i + Num_builtin_messages].wave_info.name = strdup(LPCTSTR(generate_filename(m_abbrev_message, i + 1, digits)));
|
||||
Messages[i + Num_builtin_messages].wave_info.name = strdup(LPCTSTR(generate_filename(m_abbrev_message, i + 1, digits, message)));
|
||||
modified_filenames++;
|
||||
}
|
||||
}
|
||||
|
||||
// notify
|
||||
MessageBox("File name generation complete.", "Woohoo!");
|
||||
if ( modified_filenames > 0 ) {
|
||||
// Tell FRED that we actually modified something
|
||||
set_modified(TRUE);
|
||||
}
|
||||
|
||||
// notify user that we are done and how many filenames were changed
|
||||
char message[128] = { '\0' };
|
||||
snprintf(message, sizeof(message), "File name generation complete. Modified %d messages.", modified_filenames);
|
||||
MessageBox(message, "Woohoo!");
|
||||
}
|
||||
|
||||
void VoiceActingManager::OnGenerateScript()
|
||||
@@ -402,56 +480,27 @@ void VoiceActingManager::OnGenerateScript()
|
||||
{
|
||||
fout("\n\nMessages\n--------\n\n");
|
||||
|
||||
for (i = 0; i < Num_messages - Num_builtin_messages; i++)
|
||||
if (m_group_messages)
|
||||
{
|
||||
CString entry = m_script_entry_format;
|
||||
entry.Replace("\r\n", "\n");
|
||||
SCP_vector<int> message_indexes;
|
||||
for (i = 0; i < Num_messages - Num_builtin_messages; i++)
|
||||
message_indexes.push_back(i + Num_builtin_messages);
|
||||
|
||||
MMessage *message = &Messages[i + Num_builtin_messages];
|
||||
group_message_indexes(message_indexes);
|
||||
|
||||
// replace file name
|
||||
entry.Replace("$filename", message->wave_info.name);
|
||||
|
||||
// determine and replace persona
|
||||
entry.Replace("$message", message->message);
|
||||
if (message->persona_index >= 0)
|
||||
entry.Replace("$persona", Personas[message->persona_index].name);
|
||||
else
|
||||
entry.Replace("$persona", "<none>");
|
||||
|
||||
// determine sender
|
||||
char sender[NAME_LENGTH+1];
|
||||
strcpy_s(sender, get_message_sender(message->name));
|
||||
int shipnum = ship_name_lookup(sender);
|
||||
|
||||
if (shipnum >= 0)
|
||||
for (i = 0; i < message_indexes.size(); i++)
|
||||
{
|
||||
ship *shipp = &Ships[shipnum];
|
||||
|
||||
// we may have to use the callsign
|
||||
if (*Fred_callsigns[shipnum])
|
||||
{
|
||||
hud_stuff_ship_callsign(sender, shipp);
|
||||
}
|
||||
// account for hidden ship names
|
||||
else if ( ((Iff_info[shipp->team].flags & IFFF_WING_NAME_HIDDEN) && (shipp->wingnum != -1)) || (shipp->flags2 & SF2_HIDE_SHIP_NAME) )
|
||||
{
|
||||
hud_stuff_ship_class(sender, shipp);
|
||||
}
|
||||
// use the regular sender text
|
||||
else
|
||||
{
|
||||
end_string_at_first_hash_symbol(sender);
|
||||
}
|
||||
MMessage *message = &Messages[message_indexes[i]];
|
||||
export_one_message(message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < Num_messages - Num_builtin_messages; i++)
|
||||
{
|
||||
MMessage *message = &Messages[i + Num_builtin_messages];
|
||||
export_one_message(message);
|
||||
}
|
||||
|
||||
// replace sender (but print #Command as Command)
|
||||
if (*sender == '#')
|
||||
entry.Replace("$sender", &sender[1]);
|
||||
else
|
||||
entry.Replace("$sender", sender);
|
||||
|
||||
fout("%s\n\n\n", (char *) (LPCTSTR) entry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,6 +510,76 @@ void VoiceActingManager::OnGenerateScript()
|
||||
MessageBox("Script generation complete.", "Woohoo!");
|
||||
}
|
||||
|
||||
void VoiceActingManager::export_one_message(MMessage *message)
|
||||
{
|
||||
CString entry = m_script_entry_format;
|
||||
entry.Replace("\r\n", "\n");
|
||||
|
||||
// replace file name
|
||||
entry.Replace("$filename", message->wave_info.name);
|
||||
|
||||
// determine and replace persona
|
||||
entry.Replace("$message", message->message);
|
||||
if (message->persona_index >= 0)
|
||||
entry.Replace("$persona", Personas[message->persona_index].name);
|
||||
else
|
||||
entry.Replace("$persona", "<none>");
|
||||
|
||||
// determine sender
|
||||
char sender[NAME_LENGTH+1];
|
||||
|
||||
get_valid_sender(sender, sizeof(sender), message);
|
||||
|
||||
// replace sender (but print #Command as Command)
|
||||
if (*sender == '#')
|
||||
entry.Replace("$sender", &sender[1]);
|
||||
else
|
||||
entry.Replace("$sender", sender);
|
||||
|
||||
fout("%s\n\n\n", (char *) (LPCTSTR) entry);
|
||||
}
|
||||
|
||||
/** Passed sender string will have either have the senders name
|
||||
or '<none>'*/
|
||||
void VoiceActingManager::get_valid_sender(char *sender, size_t sender_size, MMessage *message) {
|
||||
Assert( sender != NULL );
|
||||
Assert( message != NULL );
|
||||
|
||||
strncpy(sender, get_message_sender(message->name), sender_size);
|
||||
|
||||
// strip hash if present
|
||||
if ( sender[0] == '#' ) {
|
||||
size_t i = 1;
|
||||
for(; sender[i] != '\0'; i++ ) {
|
||||
sender[i-1] = sender[i];
|
||||
}
|
||||
sender[i-1] = '\0';
|
||||
}
|
||||
|
||||
int shipnum = ship_name_lookup(sender, 1); // The player's ship is valid for this search.
|
||||
|
||||
if (shipnum >= 0)
|
||||
{
|
||||
ship *shipp = &Ships[shipnum];
|
||||
|
||||
// we may have to use the callsign
|
||||
if (*Fred_callsigns[shipnum])
|
||||
{
|
||||
hud_stuff_ship_callsign(sender, shipp);
|
||||
}
|
||||
// account for hidden ship names
|
||||
else if ( ((Iff_info[shipp->team].flags & IFFF_WING_NAME_HIDDEN) && (shipp->wingnum != -1)) || (shipp->flags2 & SF2_HIDE_SHIP_NAME) )
|
||||
{
|
||||
hud_stuff_ship_class(sender, shipp);
|
||||
}
|
||||
// use the regular sender text
|
||||
else
|
||||
{
|
||||
end_string_at_first_hash_symbol(sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoiceActingManager::OnSetfocusAbbrevBriefing()
|
||||
{
|
||||
UpdateData(TRUE);
|
||||
@@ -667,3 +786,146 @@ char *VoiceActingManager::get_message_sender(char *message)
|
||||
|
||||
return "<none>";
|
||||
}
|
||||
|
||||
void VoiceActingManager::group_message_indexes(SCP_vector<int> &message_indexes)
|
||||
{
|
||||
int i;
|
||||
#ifndef NDEBUG
|
||||
int initial_size = message_indexes.size();
|
||||
#endif
|
||||
|
||||
SCP_vector<int> temp_message_indexes = message_indexes;
|
||||
message_indexes.clear();
|
||||
|
||||
// add all messages found in send-message-list or send-random-message node trees
|
||||
for (i = 0; i < Num_mission_events; i++)
|
||||
{
|
||||
mission_event *event = &Mission_events[i];
|
||||
group_message_indexes_in_tree(event->formula, temp_message_indexes, message_indexes);
|
||||
}
|
||||
|
||||
// add remaining messages
|
||||
for (i = 0; i < temp_message_indexes.size(); i++)
|
||||
message_indexes.push_back(temp_message_indexes[i]);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (initial_size > message_indexes.size())
|
||||
{
|
||||
Warning(LOCATION, "Initial size is greater than size after sorting!");
|
||||
}
|
||||
else if (initial_size < message_indexes.size())
|
||||
{
|
||||
Warning(LOCATION, "Initial size is less than size after sorting!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void VoiceActingManager::group_message_indexes_in_tree(int node, SCP_vector<int> &source_list, SCP_vector<int> &destination_list)
|
||||
{
|
||||
int i, op, n;
|
||||
|
||||
if (node < 0)
|
||||
return;
|
||||
if (Sexp_nodes[node].type == SEXP_NOT_USED)
|
||||
return;
|
||||
|
||||
// stuff
|
||||
op = get_operator_const(Sexp_nodes[node].text);
|
||||
n = CDR(node);
|
||||
|
||||
if (op == OP_SEND_MESSAGE_LIST)
|
||||
{
|
||||
// check the argument list
|
||||
while (n != -1)
|
||||
{
|
||||
// the third argument is a message
|
||||
char *message_name = Sexp_nodes[CDDR(n)].text;
|
||||
|
||||
// check source messages
|
||||
for (i = 0; i < source_list.size(); i++)
|
||||
{
|
||||
if (!strcmp(message_name, Messages[source_list[i]].name))
|
||||
{
|
||||
// move it from source to destination
|
||||
destination_list.push_back(source_list[i]);
|
||||
source_list.erase(source_list.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// iterate along the list
|
||||
n = CDDDDR(n);
|
||||
}
|
||||
}
|
||||
else if (op == OP_SEND_RANDOM_MESSAGE)
|
||||
{
|
||||
// check the argument list
|
||||
n = CDDR(n);
|
||||
while (n != -1)
|
||||
{
|
||||
// each argument from this point on is a message
|
||||
char *message_name = Sexp_nodes[n].text;
|
||||
|
||||
// check source messages
|
||||
for (i = 0; i < source_list.size(); i++)
|
||||
{
|
||||
if (!strcmp(message_name, Messages[source_list[i]].name))
|
||||
{
|
||||
// move it from source to destination
|
||||
destination_list.push_back(source_list[i]);
|
||||
source_list.erase(source_list.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// iterate along the list
|
||||
n = CDR(n);
|
||||
}
|
||||
}
|
||||
|
||||
// iterate on first element
|
||||
group_message_indexes_in_tree(CAR(node), source_list, destination_list);
|
||||
|
||||
// iterate on rest of elements
|
||||
group_message_indexes_in_tree(CDR(node), source_list, destination_list);
|
||||
}
|
||||
|
||||
void VoiceActingManager::OnExportEverything()
|
||||
{
|
||||
CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
|
||||
button->EnableWindow(TRUE);
|
||||
}
|
||||
|
||||
void VoiceActingManager::OnExportCommandBriefings()
|
||||
{
|
||||
CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
|
||||
button->EnableWindow(FALSE);
|
||||
}
|
||||
|
||||
void VoiceActingManager::OnExportBriefings()
|
||||
{
|
||||
CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
|
||||
button->EnableWindow(FALSE);
|
||||
}
|
||||
|
||||
void VoiceActingManager::OnExportDebriefings()
|
||||
{
|
||||
CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
|
||||
button->EnableWindow(FALSE);
|
||||
}
|
||||
|
||||
void VoiceActingManager::OnExportMessages()
|
||||
{
|
||||
CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
|
||||
button->EnableWindow(TRUE);
|
||||
}
|
||||
|
||||
|
||||
void VoiceActingManager::OnBnClickedIncludeSender()
|
||||
{
|
||||
UpdateData(TRUE);
|
||||
|
||||
build_example();
|
||||
|
||||
UpdateData(FALSE);
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
// VoiceActingManager.h : header file
|
||||
//
|
||||
|
||||
#include "mission/missionmessage.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// VoiceActingManager dialog
|
||||
|
||||
@@ -25,6 +27,7 @@ public:
|
||||
CString m_abbrev_debriefing;
|
||||
CString m_abbrev_message;
|
||||
CString m_abbrev_mission;
|
||||
BOOL m_use_sender_in_filename;
|
||||
CString m_example;
|
||||
BOOL m_no_replace;
|
||||
CString m_script_entry_format;
|
||||
@@ -33,6 +36,7 @@ public:
|
||||
BOOL m_export_briefings;
|
||||
BOOL m_export_debriefings;
|
||||
BOOL m_export_messages;
|
||||
BOOL m_group_messages;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
||||
@@ -50,8 +54,12 @@ protected:
|
||||
int calc_digits(int size);
|
||||
void build_example();
|
||||
void build_example(CString section);
|
||||
CString generate_filename(CString section, int number, int digits);
|
||||
CString generate_filename(CString section, int number, int digits, MMessage *message=NULL);
|
||||
char *get_message_sender(char *message);
|
||||
void export_one_message(MMessage *message);
|
||||
void get_valid_sender(char *sender, size_t sender_size, MMessage *message);
|
||||
void group_message_indexes(SCP_vector<int> &message_indexes);
|
||||
void group_message_indexes_in_tree(int node, SCP_vector<int> &source_list, SCP_vector<int> &destination_list);
|
||||
|
||||
CFILE *fp;
|
||||
int fout(char *format, ...);
|
||||
@@ -77,6 +85,12 @@ protected:
|
||||
afx_msg void OnChangeNoReplace();
|
||||
afx_msg void OnGenerateFileNames();
|
||||
afx_msg void OnGenerateScript();
|
||||
afx_msg void OnExportEverything();
|
||||
afx_msg void OnExportCommandBriefings();
|
||||
afx_msg void OnExportBriefings();
|
||||
afx_msg void OnExportDebriefings();
|
||||
afx_msg void OnExportMessages();
|
||||
afx_msg void OnBnClickedIncludeSender();
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
|
||||
@@ -1132,8 +1132,7 @@ void game_level_init(int seed)
|
||||
supernova_level_init();
|
||||
cam_init();
|
||||
subtitles_init();
|
||||
|
||||
|
||||
snd_aav_init();
|
||||
|
||||
// multiplayer dogfight hack
|
||||
dogfight_blown = 0;
|
||||
@@ -1193,32 +1192,6 @@ void game_do_networking()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Loads the best palette for this level, based
|
||||
// on nebula color and hud color. You could just call palette_load_table with
|
||||
// the appropriate filename, but who wants to do that.
|
||||
void game_load_palette()
|
||||
{
|
||||
char palette_filename[1024];
|
||||
|
||||
// We only use 3 hud colors right now
|
||||
// Assert( HUD_config.color >= 0 );
|
||||
// Assert( HUD_config.color <= 2 );
|
||||
|
||||
Assert( Mission_palette >= 0 );
|
||||
Assert( Mission_palette <= 98 );
|
||||
|
||||
// if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
|
||||
strcpy_s( palette_filename, NOX("gamepalette-subspace") );
|
||||
// } else {
|
||||
// sprintf( palette_filename, NOX("gamepalette%d-%02d"), HUD_config.color+1, Mission_palette+1 );
|
||||
// }
|
||||
|
||||
mprintf(( "Loading palette %s\n", palette_filename ));
|
||||
|
||||
// palette_load_table(palette_filename);
|
||||
}
|
||||
|
||||
// An estimate as to how high the count passed to game_loading_callback will go.
|
||||
// This is just a guess, it seems to always be about the same. The count is
|
||||
// proportional to the code being executed, not the time, so this works good
|
||||
@@ -1265,7 +1238,7 @@ void game_loading_callback(int count)
|
||||
game_do_networking();
|
||||
|
||||
Assert( Game_loading_callback_inited==1 );
|
||||
Assert( Game_loading_ani.num_frames > 0 );
|
||||
Assertion( Game_loading_ani.num_frames > 0, "Load Screen animation %s not found, or corrupted. Needs to be an animation with at least 1 frame.", Game_loading_ani.filename );
|
||||
|
||||
int do_flip = 0;
|
||||
|
||||
@@ -1382,7 +1355,7 @@ void game_loading_callback_init()
|
||||
strcpy(Game_loading_ani.filename, Game_loading_ani_fname[gr_screen.res]);
|
||||
generic_anim_init(&Game_loading_ani, Game_loading_ani.filename);
|
||||
generic_anim_load(&Game_loading_ani);
|
||||
Assert( Game_loading_ani.num_frames > 0 );
|
||||
Assertion( Game_loading_ani.num_frames > 0, "Load Screen animation %s not found, or corrupted. Needs to be an animation with at least 1 frame.", Game_loading_ani.filename );
|
||||
|
||||
Game_loading_callback_inited = 1;
|
||||
Mouse_hidden = 1;
|
||||
@@ -1617,14 +1590,6 @@ int game_start_mission()
|
||||
extern void stop_parse();
|
||||
stop_parse();
|
||||
|
||||
//WMC - *sigh* more mprintf clutter. It was commented out when I got here
|
||||
/*
|
||||
// the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
|
||||
if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
|
||||
mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
|
||||
// game_load_palette();
|
||||
}*/
|
||||
|
||||
game_busy( NOX("** starting game_post_level_init() **") );
|
||||
load_post_level_init = (uint) time(NULL);
|
||||
game_post_level_init();
|
||||
@@ -5022,7 +4987,7 @@ void game_set_frametime(int state)
|
||||
}
|
||||
#endif
|
||||
|
||||
Assert( Framerate_cap > 0 );
|
||||
Assertion( Framerate_cap > 0, "Framerate cap %d is too low. Needs to be a positive, non-zero number", Framerate_cap );
|
||||
|
||||
// Cap the framerate so it doesn't get too high.
|
||||
if (!Cmdline_NoFPSCap)
|
||||
@@ -6095,6 +6060,7 @@ void game_leave_state( int old_state, int new_state )
|
||||
if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
|
||||
multi_quit_game(PROMPT_NONE);
|
||||
}
|
||||
snd_aav_init();
|
||||
|
||||
freespace_stop_mission();
|
||||
}
|
||||
|
||||
@@ -192,11 +192,6 @@ void big_explosion_flash(float flash);
|
||||
// flash effect to 0.
|
||||
void game_flash_diminish();
|
||||
|
||||
// Loads the best palette for this level, based
|
||||
// on nebula color and hud color. You could just call palette_load_table with
|
||||
// the appropriate filename, but who wants to do that.
|
||||
void game_load_palette();
|
||||
|
||||
//================================================================
|
||||
|
||||
// Call at the beginning of each frame
|
||||
|
||||
@@ -66,7 +66,8 @@ static bool do_full_packet = true;
|
||||
|
||||
static int Local_timeout = -1;
|
||||
static int Next_gameserver_update = -1;
|
||||
static int Last_pong = -1;
|
||||
static int Ping_timestamp = -1;
|
||||
static int Last_activity = -1;
|
||||
static int Login_retry_time = -1;
|
||||
|
||||
static SCP_vector<file_record> FS2NetD_file_list;
|
||||
@@ -92,7 +93,8 @@ static void fs2netd_reset_state()
|
||||
do_full_packet = true;
|
||||
Local_timeout = -1;
|
||||
Next_gameserver_update = -1;
|
||||
Last_pong = -1;
|
||||
Last_activity = -1;
|
||||
Ping_timestamp = -1;
|
||||
Duplicate_login_detected = false;
|
||||
Login_retry_time = -1;
|
||||
}
|
||||
@@ -167,19 +169,38 @@ void fs2netd_reset_connection()
|
||||
|
||||
FS2NetD_Disconnect();
|
||||
|
||||
// wait a little to allow for the port to clear
|
||||
Sleep(250);
|
||||
|
||||
fs2netd_reset_state();
|
||||
|
||||
// wait a little to allow for the port to clear
|
||||
Sleep(500);
|
||||
|
||||
// try to reinit the server connection
|
||||
fs2netd_login();
|
||||
|
||||
if (reset_gameserver) {
|
||||
Sleep(250);
|
||||
|
||||
if ( reset_gameserver && fs2netd_is_online() ) {
|
||||
fs2netd_gameserver_start();
|
||||
}
|
||||
}
|
||||
|
||||
void fs2netd_disconnect()
|
||||
{
|
||||
if ( !Is_connected ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Net_player->flags & NETINFO_FLAG_MT_CONNECTED) {
|
||||
fs2netd_gameserver_disconnect();
|
||||
}
|
||||
|
||||
FS2NetD_Disconnect();
|
||||
|
||||
fs2netd_reset_state();
|
||||
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
static int fs2netd_connect_do()
|
||||
{
|
||||
int retval = FS2NetD_ConnectToServer(Multi_options_g.game_tracker_ip, Multi_options_g.tracker_port);
|
||||
@@ -307,6 +328,10 @@ int fs2netd_login_do()
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (do_full_packet) {
|
||||
ml_printf("FS2NetD MSG: Requesting login pilot stats for '%s' ...", Players[Player_num].callsign);
|
||||
}
|
||||
|
||||
int rescode = FS2NetD_GetPlayerData(Players[Player_num].callsign, &Players[Player_num], true, do_full_packet);
|
||||
|
||||
do_full_packet = false;
|
||||
@@ -469,6 +494,9 @@ bool fs2netd_login()
|
||||
if (retval) {
|
||||
Logged_in = true;
|
||||
sprintf(Multi_tracker_id_string, "%d", Multi_tracker_id);
|
||||
} else {
|
||||
// clear and reset connection, for the next time we try...
|
||||
fs2netd_disconnect();
|
||||
}
|
||||
|
||||
if (Is_standalone) {
|
||||
@@ -480,11 +508,13 @@ bool fs2netd_login()
|
||||
|
||||
static void fs2netd_handle_ping()
|
||||
{
|
||||
static int Next_ping = -1;
|
||||
bool reset = false;
|
||||
static int CONN_check = -1;
|
||||
|
||||
// if we didn't get a pong within 30 seconds of a ping then assume that the
|
||||
// server connection must of have dropped or is otherwise unresponsive
|
||||
if ( (Ping_timestamp != -1) && ((timer_get_seconds() - Ping_timestamp) > 30) ) {
|
||||
Ping_timestamp = -1;
|
||||
|
||||
// if we didn't get a PONG within 4 minutes the server connection must have dropped
|
||||
if ( (Last_pong != -1) && ((Next_ping - Last_pong) > 240) ) {
|
||||
ml_string("FS2NetD WARNING: Lost connection to server!");
|
||||
fs2netd_reset_connection();
|
||||
|
||||
@@ -496,11 +526,11 @@ static void fs2netd_handle_ping()
|
||||
}
|
||||
|
||||
ml_string("FS2NetD ERROR: Lost connection to the FS2NetD server!");
|
||||
FS2NetD_Disconnect();
|
||||
fs2netd_reset_state();
|
||||
|
||||
ml_string("FS2NetD MSG: Will attempt an automatic reconnect to server in 30 minutes...");
|
||||
Login_retry_time = timer_get_seconds() + 1800;
|
||||
fs2netd_disconnect();
|
||||
|
||||
ml_string("FS2NetD MSG: Will attempt an automatic reconnect to server in 5 minutes...");
|
||||
Login_retry_time = timer_get_seconds() + 300;
|
||||
|
||||
return;
|
||||
} else {
|
||||
@@ -508,24 +538,24 @@ static void fs2netd_handle_ping()
|
||||
}
|
||||
}
|
||||
|
||||
// send out ping every 90 seconds
|
||||
if ( (Next_ping == -1) || (timer_get_seconds() >= Next_ping) ) {
|
||||
// if we have seen a long period of time between pings then reset the pong time too
|
||||
if ( (timer_get_seconds() - Next_ping) > 120 ) {
|
||||
reset = true;
|
||||
}
|
||||
|
||||
Next_ping = timer_get_seconds() + 90;
|
||||
|
||||
// we go ahead and set the initial Last_pong here, even though we haven't gotten a pong yet
|
||||
if ( (Last_pong == -1) || reset ) {
|
||||
Last_pong = Next_ping;
|
||||
reset = false;
|
||||
}
|
||||
|
||||
// send out a ping after 5 minutes of no other activity to make sure the server
|
||||
// is still responding (probably not though)
|
||||
if ( (Ping_timestamp == -1) && (timer_get_seconds() >= (Last_activity + 300)) ) {
|
||||
Ping_timestamp = timer_get_seconds();
|
||||
FS2NetD_Ping();
|
||||
ml_string("FS2NetD sent PING");
|
||||
|
||||
// also send out a ID check to keep our login verified
|
||||
if (Last_activity < 0) {
|
||||
Last_activity = timer_get_seconds();
|
||||
}
|
||||
}
|
||||
|
||||
// check for a valid connection (SID, duplicate login, etc.)
|
||||
if ( (CONN_check == -1) || (timer_get_seconds() >= CONN_check) ) {
|
||||
// every 3 minutes
|
||||
CONN_check = timer_get_seconds() + 180;
|
||||
|
||||
// session ID check
|
||||
if ( FS2NetD_CheckValidID() < 0 ) {
|
||||
ml_string("FS2NetD WARNING: Unable to validate login!");
|
||||
fs2netd_reset_connection();
|
||||
@@ -538,11 +568,11 @@ static void fs2netd_handle_ping()
|
||||
}
|
||||
|
||||
ml_string("FS2NetD ERROR: Lost connection to the FS2NetD server!");
|
||||
FS2NetD_Disconnect();
|
||||
fs2netd_reset_state();
|
||||
|
||||
ml_string("FS2NetD MSG: Will attempt an automatic reconnect to server in 30 minutes...");
|
||||
Login_retry_time = timer_get_seconds() + 1800;
|
||||
fs2netd_disconnect();
|
||||
|
||||
ml_string("FS2NetD MSG: Will attempt an automatic reconnect to server in 5 minutes...");
|
||||
Login_retry_time = timer_get_seconds() + 300;
|
||||
|
||||
return;
|
||||
} else {
|
||||
@@ -555,7 +585,7 @@ static void fs2netd_handle_ping()
|
||||
FS2NetD_CheckDuplicateLogin();
|
||||
}
|
||||
|
||||
ml_string("FS2NetD sent PING/IDENT");
|
||||
ml_string("FS2NetD sent IDENT check");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,6 +614,8 @@ static void fs2netd_handle_messages()
|
||||
return;
|
||||
}
|
||||
|
||||
Last_activity = timer_get_seconds();
|
||||
|
||||
buffer_offset = 0;
|
||||
|
||||
while (buffer_offset+BASE_PACKET_SIZE <= bytes_read) {
|
||||
@@ -612,7 +644,8 @@ static void fs2netd_handle_messages()
|
||||
|
||||
ml_printf("FS2NetD PONG: %d ms", timer_get_milliseconds() - itemp);
|
||||
|
||||
Last_pong = timer_get_seconds();
|
||||
// reset timestamp, since the ping was successful
|
||||
Ping_timestamp = -1;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -739,8 +772,8 @@ void fs2netd_do_frame()
|
||||
fs2netd_login();
|
||||
|
||||
if ( !Logged_in ) {
|
||||
// bah! try again in another 30 minutes
|
||||
Login_retry_time = timer_get_seconds() + 1800;
|
||||
// bah! try again in another 5 minutes
|
||||
Login_retry_time = timer_get_seconds() + 300;
|
||||
} else {
|
||||
Login_retry_time = -1;
|
||||
}
|
||||
@@ -1550,6 +1583,10 @@ int fs2netd_get_pilot_info(const char *callsign, player *out_plr, bool first_cal
|
||||
In_process = true;
|
||||
}
|
||||
|
||||
if (first_call) {
|
||||
ml_printf("FS2NetD MSG: Requesting pilot stats for '%s' ...", callsign);
|
||||
}
|
||||
|
||||
int rc = FS2NetD_GetPlayerData(callsign, &new_plr, false, first_call);
|
||||
|
||||
// some sort of failure
|
||||
|
||||
@@ -47,6 +47,7 @@ extern tracker_game_data Multi_tracker_game_data;
|
||||
bool fs2netd_is_online();
|
||||
|
||||
void fs2netd_reset_connection();
|
||||
void fs2netd_disconnect();
|
||||
|
||||
void fs2netd_close();
|
||||
|
||||
|
||||
@@ -265,8 +265,8 @@ int FS2NetD_GetPlayerData(const char *player_name, player *pl, bool can_create,
|
||||
|
||||
PXO_GET_DATA( reply_type );
|
||||
|
||||
// if we weren't retrieved or created then bail out now
|
||||
if (reply_type > 1) {
|
||||
// if we weren't retrieved then bail out now
|
||||
if (reply_type != 0) {
|
||||
return (int)reply_type;
|
||||
}
|
||||
|
||||
|
||||
@@ -368,17 +368,13 @@ void help_overlay_init()
|
||||
{
|
||||
// load right_bracket bitmap
|
||||
help_right_bracket_bitmap = bm_load("right_bracket");
|
||||
if(help_right_bracket_bitmap < 0){
|
||||
// we failed to load the bitmap - this is very bad
|
||||
Int3();
|
||||
}
|
||||
// we failed to load the bitmap - this is very bad
|
||||
Assertion( help_right_bracket_bitmap >= 0, "Failed to load bitmap right_bracket for help overlay\n");
|
||||
|
||||
// load left_bracket bitmap
|
||||
help_left_bracket_bitmap = bm_load("left_bracket");
|
||||
if(help_left_bracket_bitmap < 0){
|
||||
// we failed to load the bitmap - this is very bad
|
||||
Int3();
|
||||
}
|
||||
// we failed to load the bitmap - this is very bad
|
||||
Assertion( help_left_bracket_bitmap >= 0, "Failed to load bitmap left_bracket for help overlay\n");
|
||||
|
||||
atexit(close_help);
|
||||
// parse help.tbl
|
||||
|
||||
@@ -407,7 +407,7 @@ void event_music_force_switch()
|
||||
return; // invalid pattern
|
||||
|
||||
Assert(new_pattern >= 0 && new_pattern < MAX_PATTERNS);
|
||||
audiostream_play(Patterns[new_pattern].handle, Master_event_music_volume, 0); // no looping
|
||||
audiostream_play(Patterns[new_pattern].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
|
||||
audiostream_set_sample_cutoff(Patterns[new_pattern].handle, fl2i(Patterns[new_pattern].num_measures * Patterns[new_pattern].samples_per_measure) );
|
||||
Patterns[Current_pattern].next_pattern = Patterns[Current_pattern].default_next_pattern;
|
||||
Patterns[Current_pattern].force_pattern = FALSE;
|
||||
@@ -440,7 +440,7 @@ void event_music_do_frame()
|
||||
if ( Current_pattern != -1 && Patterns[Current_pattern].handle >= 0) {
|
||||
//WMC - removed in favor of if
|
||||
//Assert(Patterns[Current_pattern].handle >= 0 );
|
||||
audiostream_play(Patterns[Current_pattern].handle, Master_event_music_volume, 0); // no looping
|
||||
audiostream_play(Patterns[Current_pattern].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
|
||||
audiostream_set_sample_cutoff(Patterns[Current_pattern].handle, fl2i(Patterns[Current_pattern].num_measures * Patterns[Current_pattern].samples_per_measure) );
|
||||
}
|
||||
}
|
||||
@@ -462,7 +462,7 @@ void event_music_do_frame()
|
||||
audiostream_stop(pat->handle); // stop current and rewind
|
||||
pat->loop_for--;
|
||||
if ( pat->loop_for > 0 ) {
|
||||
audiostream_play(pat->handle, Master_event_music_volume, 0); // no looping
|
||||
audiostream_play(pat->handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
|
||||
audiostream_set_sample_cutoff(Patterns[Current_pattern].handle, fl2i(Patterns[Current_pattern].num_measures * Patterns[Current_pattern].samples_per_measure) );
|
||||
}
|
||||
else {
|
||||
@@ -924,7 +924,7 @@ int event_music_friendly_arrival()
|
||||
// Goober5000 - I didn't touch this part... for some reason, FS2 only has one
|
||||
// arrival music pattern, and this is it
|
||||
Assert(Patterns[SONG_AARV_1].handle >= 0 );
|
||||
audiostream_play(Patterns[SONG_AARV_1].handle, Master_event_music_volume, 0); // no looping
|
||||
audiostream_play(Patterns[SONG_AARV_1].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
|
||||
audiostream_set_sample_cutoff(Patterns[SONG_AARV_1].handle, fl2i(Patterns[SONG_AARV_1].num_measures * Patterns[SONG_AARV_1].samples_per_measure) );
|
||||
}
|
||||
// don't overlay
|
||||
@@ -1198,9 +1198,7 @@ void parse_soundtrack()
|
||||
}
|
||||
|
||||
//Track doesn't exist and has nocreate, so don't create it
|
||||
if ( !skip_to_start_of_string_either("#SoundTrack Start", "#Menu Music Start") && !skip_to_string("#SoundTrack End")) {
|
||||
Int3();
|
||||
}
|
||||
Assertion(skip_to_start_of_string_either("#SoundTrack Start", "#Menu Music Start") || skip_to_string("#SoundTrack End"), "Couldn't find #Soundtrack Start, #Menu Music Start or #Soundtrack End. Music.tbl or -mus.tbm is invalid.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1336,9 +1334,7 @@ void parse_menumusic()
|
||||
Warning(LOCATION, "Could not load spooled music file after '%s' as maximum number of spooled music was reached (Max is %d)", Spooled_music[Num_music_files - 1].name, MAX_SPOOLED_MUSIC);
|
||||
}
|
||||
|
||||
if(!skip_to_start_of_string_either("$Name:", "#Menu Music End")) {
|
||||
Int3();
|
||||
}
|
||||
Assertion(skip_to_start_of_string_either("$Name:", "#Menu Music End"), "Couldn't find $Name or #Menu Music End. Music.tbl or -mus.tbm is invalid.\n");
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1591,7 +1587,7 @@ void event_music_unpause()
|
||||
|
||||
Assert( Current_pattern >= 0 && Current_pattern < MAX_PATTERNS );
|
||||
if ( audiostream_is_paused(Patterns[Current_pattern].handle) == TRUE ) {
|
||||
audiostream_play(Patterns[Current_pattern].handle, Master_event_music_volume, 0); // no looping
|
||||
audiostream_play(Patterns[Current_pattern].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
|
||||
audiostream_set_sample_cutoff(Patterns[Current_pattern].handle, fl2i(Patterns[Current_pattern].num_measures * Patterns[Current_pattern].samples_per_measure) );
|
||||
}
|
||||
}
|
||||
|
||||
+84
-68
@@ -14,14 +14,13 @@
|
||||
#include "species_defs/species_defs.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "sound/ds.h"
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
int Num_game_sounds = 0;
|
||||
game_snd *Snds = NULL;
|
||||
SCP_vector<game_snd> Snds;
|
||||
|
||||
int Num_iface_sounds = 0;
|
||||
game_snd *Snds_iface = NULL;
|
||||
int *Snds_iface_handle = NULL;
|
||||
SCP_vector<game_snd> Snds_iface;
|
||||
SCP_vector<int> Snds_iface_handle;
|
||||
|
||||
#define GAME_SND 0
|
||||
#define IFACE_SND 1
|
||||
@@ -39,7 +38,8 @@ void gamesnd_play_iface(int n)
|
||||
//WMC - now ignores file extension.
|
||||
int gamesnd_get_by_name(char* name)
|
||||
{
|
||||
for(int i = 0; i < Num_game_sounds; i++)
|
||||
Assert( Snds.size() <= INT_MAX );
|
||||
for(int i = 0; i < (int)Snds.size(); i++)
|
||||
{
|
||||
char *p = strrchr( Snds[i].filename, '.' );
|
||||
if(p == NULL)
|
||||
@@ -57,6 +57,31 @@ int gamesnd_get_by_name(char* name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gamesnd_get_by_tbl_index(int index)
|
||||
{
|
||||
Assert( Snds.size() <= INT_MAX );
|
||||
for(int i = 0; i < (int)Snds.size(); i++) {
|
||||
if ( Snds[i].sig == index )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gamesnd_get_by_iface_tbl_index(int index)
|
||||
{
|
||||
Assert( Snds_iface.size() <= INT_MAX );
|
||||
Assert( Snds_iface.size() == Snds_iface_handle.size() );
|
||||
for(int i = 0; i < (int)Snds_iface.size(); i++) {
|
||||
if ( Snds_iface[i].sig == index )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Takes a tag, a sound index destination, and the object name being parsed
|
||||
//tag and object_name are mostly so that we can debug stuff
|
||||
//This also means you shouldn't use optional_string or required_string,
|
||||
@@ -74,12 +99,18 @@ void parse_sound(char* tag, int *idx_dest, char* object_name)
|
||||
if(idx != -1)
|
||||
(*idx_dest) = idx;
|
||||
else
|
||||
(*idx_dest) = atoi(buf);
|
||||
|
||||
//Ensure sound is in range
|
||||
if((*idx_dest) < -1 || (*idx_dest) >= Num_game_sounds)
|
||||
{
|
||||
Warning(LOCATION, "%s sound index out of range on '%s'. Must be between 0 and %d. Forcing to -1 (Nonexistant sound).\n", tag, object_name, Num_game_sounds);
|
||||
idx = gamesnd_get_by_tbl_index(atoi(buf));
|
||||
if (idx != -1)
|
||||
(*idx_dest) = idx;
|
||||
}
|
||||
|
||||
Assert( Snds.size() <= INT_MAX );
|
||||
//Ensure sound is in range
|
||||
if((*idx_dest) < -1 || (*idx_dest) >= (int)Snds.size())
|
||||
{
|
||||
(*idx_dest) = -1;
|
||||
Warning(LOCATION, "%s sound index out of range on '%s'. Must be between 0 and %d. Forcing to -1 (Nonexistant sound).\n", tag, object_name, Snds.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +128,8 @@ void gamesnd_preload_common_sounds()
|
||||
if ( !Sound_enabled )
|
||||
return;
|
||||
|
||||
for ( i = 0; i < Num_game_sounds; i++ ) {
|
||||
Assert( Snds.size() <= INT_MAX );
|
||||
for ( i = 0; i < (int)Snds.size(); i++ ) {
|
||||
gs = &Snds[i];
|
||||
if ( gs->filename[0] != 0 && strnicmp(gs->filename, NOX("none.wav"), 4) ) {
|
||||
if ( gs->preload ) {
|
||||
@@ -121,7 +153,8 @@ void gamesnd_load_gameplay_sounds()
|
||||
if ( !Sound_enabled )
|
||||
return;
|
||||
|
||||
for ( i = 0; i < Num_game_sounds; i++ ) {
|
||||
Assert( Snds.size() <= INT_MAX );
|
||||
for ( i = 0; i < (int)Snds.size(); i++ ) {
|
||||
gs = &Snds[i];
|
||||
if ( gs->filename[0] != 0 && strnicmp(gs->filename, NOX("none.wav"), 4) ) {
|
||||
if ( !gs->preload ) { // don't try to load anything that's already preloaded
|
||||
@@ -142,7 +175,8 @@ void gamesnd_unload_gameplay_sounds()
|
||||
int i;
|
||||
game_snd *gs;
|
||||
|
||||
for ( i = 0; i < Num_game_sounds; i++ ) {
|
||||
Assert( Snds.size() <= INT_MAX );
|
||||
for ( i = 0; i < (int)Snds.size(); i++ ) {
|
||||
gs = &Snds[i];
|
||||
if ( gs->id != -1 ) {
|
||||
snd_unload( gs->id );
|
||||
@@ -164,7 +198,8 @@ void gamesnd_load_interface_sounds()
|
||||
if ( !Sound_enabled )
|
||||
return;
|
||||
|
||||
for ( i = 0; i < Num_iface_sounds; i++ ) {
|
||||
Assert( Snds_iface.size() < INT_MAX );
|
||||
for ( i = 0; i < (int)Snds_iface.size(); i++ ) {
|
||||
gs = &Snds_iface[i];
|
||||
if ( gs->filename[0] != 0 && strnicmp(gs->filename, NOX("none.wav"), 4) ) {
|
||||
gs->id = snd_load(gs);
|
||||
@@ -182,7 +217,8 @@ void gamesnd_unload_interface_sounds()
|
||||
int i;
|
||||
game_snd *gs;
|
||||
|
||||
for ( i = 0; i < Num_iface_sounds; i++ ) {
|
||||
Assert( Snds_iface.size() < INT_MAX );
|
||||
for ( i = 0; i < (int)Snds_iface.size(); i++ ) {
|
||||
gs = &Snds_iface[i];
|
||||
if ( gs->id != -1 ) {
|
||||
snd_unload( gs->id );
|
||||
@@ -256,7 +292,8 @@ void gamesnd_parse_soundstbl()
|
||||
// Parse the gameplay sounds section
|
||||
required_string("#Game Sounds Start");
|
||||
while (required_string_either("#Game Sounds End","$Name:")) {
|
||||
Assert( num_game_sounds < Num_game_sounds);
|
||||
Assert( Snds.size() < INT_MAX );
|
||||
Assert( num_game_sounds < (int)Snds.size() );
|
||||
gamesnd_parse_line( &Snds[num_game_sounds], "$Name:" );
|
||||
num_game_sounds++;
|
||||
gamesnd_add_sound_slot( GAME_SND, num_game_sounds );
|
||||
@@ -266,7 +303,8 @@ void gamesnd_parse_soundstbl()
|
||||
// Parse the interface sounds section
|
||||
required_string("#Interface Sounds Start");
|
||||
while (required_string_either("#Interface Sounds End","$Name:")) {
|
||||
Assert( num_iface_sounds < Num_iface_sounds);
|
||||
Assert( Snds_iface_handle.size() < INT_MAX );
|
||||
Assert( num_iface_sounds < (int)Snds_iface.size() );
|
||||
gamesnd_parse_line(&Snds_iface[num_iface_sounds], "$Name:");
|
||||
num_iface_sounds++;
|
||||
gamesnd_add_sound_slot( IFACE_SND, num_iface_sounds );
|
||||
@@ -467,6 +505,7 @@ void gamesnd_parse_soundstbl()
|
||||
//
|
||||
void gamesnd_init_struct(game_snd *gs)
|
||||
{
|
||||
gs->sig = -1;
|
||||
gs->filename[0] = 0;
|
||||
gs->id = -1;
|
||||
gs->id_sig = -1;
|
||||
@@ -482,33 +521,26 @@ void gamesnd_init_sounds()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (Snds == NULL) {
|
||||
Snds = (game_snd *) vm_malloc (sizeof(game_snd) * MIN_GAME_SOUNDS);
|
||||
Verify( Snds != NULL );
|
||||
Num_game_sounds = MIN_GAME_SOUNDS;
|
||||
}
|
||||
Snds.clear();
|
||||
Snds.resize(MIN_GAME_SOUNDS);
|
||||
|
||||
Assert( Num_game_sounds > 0 );
|
||||
Assert( Snds.size() > 0 );
|
||||
|
||||
Assert( Snds.size() <= INT_MAX );
|
||||
// init the gameplay sounds
|
||||
for ( i = 0; i < Num_game_sounds; i++ ) {
|
||||
for ( i = 0; i < (int)Snds.size(); i++ ) {
|
||||
gamesnd_init_struct(&Snds[i]);
|
||||
}
|
||||
|
||||
if (Snds_iface == NULL) {
|
||||
Snds_iface = (game_snd *) vm_malloc (sizeof(game_snd) * MIN_INTERFACE_SOUNDS);
|
||||
Verify( Snds_iface != NULL );
|
||||
Num_iface_sounds = MIN_INTERFACE_SOUNDS;
|
||||
|
||||
Assert( Snds_iface_handle == NULL );
|
||||
Snds_iface_handle = (int *) vm_malloc (sizeof(int) * Num_iface_sounds);
|
||||
Verify( Snds_iface_handle != NULL );
|
||||
}
|
||||
|
||||
Assert( Num_iface_sounds > 0 );
|
||||
Snds_iface.clear();
|
||||
Snds_iface.resize(MIN_INTERFACE_SOUNDS);
|
||||
Snds_iface_handle.resize(MIN_INTERFACE_SOUNDS);
|
||||
|
||||
Assert( Snds_iface.size() > 0 );
|
||||
|
||||
Assert( Snds_iface.size() < INT_MAX );
|
||||
// init the interface sounds
|
||||
for ( i = 0; i < Num_iface_sounds; i++ ) {
|
||||
for ( i = 0; i < (int)Snds_iface.size(); i++ ) {
|
||||
gamesnd_init_struct(&Snds_iface[i]);
|
||||
Snds_iface_handle[i] = -1;
|
||||
}
|
||||
@@ -517,20 +549,9 @@ void gamesnd_init_sounds()
|
||||
// close out gamesnd, ONLY CALL FROM game_shutdown()!!!!
|
||||
void gamesnd_close()
|
||||
{
|
||||
if (Snds != NULL) {
|
||||
vm_free(Snds);
|
||||
Snds = NULL;
|
||||
}
|
||||
|
||||
if (Snds_iface != NULL) {
|
||||
vm_free(Snds_iface);
|
||||
Snds_iface = NULL;
|
||||
}
|
||||
|
||||
if (Snds_iface_handle != NULL) {
|
||||
vm_free(Snds_iface_handle);
|
||||
Snds_iface_handle = NULL;
|
||||
}
|
||||
Snds.clear();
|
||||
Snds_iface.clear();
|
||||
Snds_iface_handle.clear();
|
||||
}
|
||||
|
||||
// callback function for the UI code to call when the mouse first goes over a button.
|
||||
@@ -552,16 +573,14 @@ void gamesnd_add_sound_slot(int type, int num)
|
||||
switch (type) {
|
||||
case GAME_SND:
|
||||
{
|
||||
Assert( Snds != NULL );
|
||||
Assert( num < (Num_game_sounds + increase_by) );
|
||||
Assert( Snds.size() <= INT_MAX );
|
||||
Assert( num < ((int)Snds.size() + increase_by) );
|
||||
|
||||
if (num >= Num_game_sounds) {
|
||||
Snds = (game_snd *) vm_realloc (Snds, sizeof(game_snd) * (Num_game_sounds + increase_by));
|
||||
Verify( Snds != NULL );
|
||||
Num_game_sounds += increase_by;
|
||||
if (num >= (int)Snds.size()) {
|
||||
Snds.resize(Snds.size() + increase_by);
|
||||
|
||||
// default all new entries
|
||||
for (i = (Num_game_sounds - increase_by); i < Num_game_sounds; i++) {
|
||||
for (i = ((int)Snds.size() - increase_by); i < (int)Snds.size(); i++) {
|
||||
gamesnd_init_struct(&Snds[i]);
|
||||
}
|
||||
}
|
||||
@@ -570,20 +589,17 @@ void gamesnd_add_sound_slot(int type, int num)
|
||||
|
||||
case IFACE_SND:
|
||||
{
|
||||
Assert( Snds_iface != NULL );
|
||||
Assert( num < (Num_game_sounds + increase_by) );
|
||||
Assert( Snds_iface.size() < INT_MAX );
|
||||
Assert( num < ((int)Snds_iface.size() + increase_by) );
|
||||
|
||||
if (num >= Num_iface_sounds) {
|
||||
Snds_iface = (game_snd *) vm_realloc (Snds_iface, sizeof(game_snd) * (Num_iface_sounds + increase_by));
|
||||
Verify( Snds_iface != NULL );
|
||||
Num_iface_sounds += increase_by;
|
||||
if (num >= (int)Snds_iface.size()) {
|
||||
Snds_iface.resize(Snds_iface.size() + increase_by);
|
||||
|
||||
Assert( Snds_iface_handle != NULL );
|
||||
Snds_iface_handle = (int *) vm_realloc (Snds_iface_handle, sizeof(int) * Num_iface_sounds);
|
||||
Verify( Snds_iface_handle != NULL );
|
||||
Snds_iface_handle.resize(Snds_iface.size());
|
||||
Assert( Snds_iface.size() < INT_MAX );
|
||||
|
||||
// default all new entries
|
||||
for (i = (Num_iface_sounds - increase_by); i < Num_iface_sounds; i++) {
|
||||
for (i = ((int)Snds_iface_handle.size() - increase_by); i < (int)Snds_iface_handle.size(); i++) {
|
||||
gamesnd_init_struct(&Snds_iface[i]);
|
||||
Snds_iface_handle[i] = -1;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ void gamesnd_preload_common_sounds();
|
||||
void gamesnd_play_iface(int n);
|
||||
void gamesnd_play_error_beep();
|
||||
int gamesnd_get_by_name(char* name);
|
||||
int gamesnd_get_by_tbl_index(int index);
|
||||
int gamesnd_get_by_iface_tbl_index(int index);
|
||||
|
||||
//This should handle NO_SOUND just fine since it doesn't directly access lowlevel code
|
||||
//Does all parsing for a sound
|
||||
@@ -40,11 +42,8 @@ void common_play_highlight_sound();
|
||||
#define MIN_GAME_SOUNDS 202
|
||||
#define MIN_INTERFACE_SOUNDS 70
|
||||
|
||||
extern int Num_game_sounds;
|
||||
extern int Num_iface_sounds;
|
||||
|
||||
extern game_snd *Snds;
|
||||
extern game_snd *Snds_iface;
|
||||
extern SCP_vector<game_snd> Snds;
|
||||
extern SCP_vector<game_snd> Snds_iface;
|
||||
|
||||
|
||||
// symbolic names for misc. game sounds. The order here must match the order in
|
||||
|
||||
@@ -30,7 +30,7 @@ color *Color_netplayer[20] = {
|
||||
&Color_bright_blue,
|
||||
&Color_green,
|
||||
&Color_bright_green,
|
||||
&Color_black,
|
||||
&Color_pink,
|
||||
&Color_grey,
|
||||
&Color_silver,
|
||||
&Color_white,
|
||||
|
||||
@@ -990,6 +990,10 @@ $no extra collision avoidance vs player: NO \n\
|
||||
;; before making it give a death scream \n\
|
||||
$perform less checks for death screams: NO \n\
|
||||
\n\
|
||||
;; If set, allows shield management for all ships \n\
|
||||
;; (including capships). \n\
|
||||
$all ships manage shields: NO \n\
|
||||
\n\
|
||||
#End \n\
|
||||
";
|
||||
|
||||
@@ -1021,6 +1025,12 @@ $Linked: \n\
|
||||
+Snd File: none \n\
|
||||
$Hazard: \n\
|
||||
+Msg: Cannot engage autopilot: Hazard Near \n\
|
||||
+Snd File: none \n\
|
||||
$Support Present: \n\
|
||||
+Msg: Cannot engage autopilot: Support Ship Present \n\
|
||||
+Snd File: none \n\
|
||||
$Support Working: \n\
|
||||
+Msg: Cannot engage autopilot: Support Ship is rearming or repairing a ship \n\
|
||||
+Snd File: none \n\
|
||||
\n\
|
||||
#END \n\
|
||||
|
||||
@@ -230,7 +230,7 @@ extern int Global_error_count;
|
||||
|
||||
// Assertion can only use its proper fuctionality in compilers that support variadic macro
|
||||
# ifndef _MSC_VER // non MS compilers
|
||||
# define Assertion(x, y, ...) do { if (!(x)){ WinAssert(#x,__FILE__,__LINE__, y, __VA_ARGS__ ); } } while (0)
|
||||
# define Assertion(x, y, ...) do { if (!(x)){ WinAssert(#x,__FILE__,__LINE__, y , ##__VA_ARGS__ ); } } while (0)
|
||||
# else
|
||||
# if _MSC_VER >= 1400 // VC 2005 or greater
|
||||
# define Assertion(x, y, ...) do { if (!(x)){ WinAssert(#x,__FILE__,__LINE__, y, __VA_ARGS__ ); } ASSUME(x); } while (0)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "globalincs/globals.h"
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "graphics/generic.h"
|
||||
#include "graphics/2d.h"
|
||||
@@ -19,6 +20,54 @@
|
||||
//we check background type to avoid messed up colours for ANI
|
||||
#define ANI_BPP_CHECK (ga->ani.bg_type == BM_TYPE_PCX) ? 16 : 32
|
||||
|
||||
// Goober5000
|
||||
int generic_anim_init_and_stream(generic_anim *anim, char *anim_filename, ubyte bg_type, bool attempt_hi_res)
|
||||
{
|
||||
int stream_result = -1;
|
||||
char filename[NAME_LENGTH];
|
||||
char *p;
|
||||
|
||||
Assert(anim != NULL);
|
||||
Assert(anim_filename != NULL);
|
||||
|
||||
// hi-res support
|
||||
if (attempt_hi_res && (gr_screen.res == GR_1024)) {
|
||||
// attempt to load a hi-res animation
|
||||
memset(filename, 0, NAME_LENGTH);
|
||||
strcpy_s(filename, "2_");
|
||||
strncat(filename, anim_filename, NAME_LENGTH - 3);
|
||||
|
||||
// remove extension
|
||||
p = strchr(filename, '.');
|
||||
if(p) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
// attempt to stream the hi-res ani
|
||||
generic_anim_init(anim, filename);
|
||||
anim->ani.bg_type = bg_type;
|
||||
stream_result = generic_anim_stream(anim);
|
||||
}
|
||||
|
||||
// we failed to stream hi-res, or we aren't running in hi-res, so try low-res
|
||||
if (stream_result < 0) {
|
||||
strcpy_s(filename, anim_filename);
|
||||
|
||||
// remove extension
|
||||
p = strchr(filename, '.');
|
||||
if(p) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
// attempt to stream the low-res ani
|
||||
generic_anim_init(anim, filename);
|
||||
anim->ani.bg_type = bg_type;
|
||||
stream_result = generic_anim_stream(anim);
|
||||
}
|
||||
|
||||
return stream_result;
|
||||
}
|
||||
|
||||
// Goober5000
|
||||
void generic_anim_init(generic_anim *ga, char *filename)
|
||||
{
|
||||
|
||||
@@ -52,7 +52,7 @@ typedef struct generic_bitmap {
|
||||
int bitmap_id;
|
||||
} generic_bitmap;
|
||||
|
||||
|
||||
int generic_anim_init_and_stream(generic_anim *anim, char *anim_filename, ubyte bg_type, bool attempt_hi_res);
|
||||
void generic_anim_init(generic_anim *ga, char *filename = NULL);
|
||||
void generic_bitmap_init(generic_bitmap *gb, char *filename = NULL);
|
||||
int generic_anim_load(generic_anim *ga);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "graphics/2d.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "render/3d.h"
|
||||
|
||||
#include "bmpman/bmpman.h"
|
||||
|
||||
geometry_batcher::~geometry_batcher()
|
||||
{
|
||||
@@ -618,7 +618,7 @@ int batch_add_bitmap(int texture, int tmap_flags, vertex *pnt, int orient, float
|
||||
int index = find_good_batch_item(texture);
|
||||
Assert( index >= 0 );
|
||||
|
||||
Assert( geometry_map[index].laser == false );
|
||||
Assertion( (geometry_map[index].laser == false), "Particle effect %s used as laser glow or laser bitmap\n", bm_get_filename(texture) );
|
||||
|
||||
geometry_map[index].tmap_flags = tmap_flags;
|
||||
geometry_map[index].alpha = alpha;
|
||||
|
||||
@@ -147,7 +147,7 @@ ogl_extension GL_Extensions[NUM_OGL_EXTENSIONS] =
|
||||
{ false, false, 1, { "GL_ARB_fragment_shader" }, 0, { NULL } },
|
||||
|
||||
// shader version 3.0 detection extensions (if any of these extensions exist then we should have a SM3.0 compatible card, hopefully)
|
||||
{ false, false, 3, { "GL_ARB_shader_texture_lod", "GL_NV_vertex_program3", "GL_ATI_shader_texture_lod" }, 0, { NULL } }
|
||||
{ false, false, 2, { "GL_ARB_shader_texture_lod", "GL_NV_vertex_program" }, 0, { NULL } }
|
||||
};
|
||||
|
||||
// ogl_funcion is:
|
||||
@@ -370,7 +370,7 @@ void opengl_extensions_init()
|
||||
// }
|
||||
|
||||
if ( !Cmdline_noglsl && Is_Extension_Enabled(OGL_ARB_SHADER_OBJECTS) && Is_Extension_Enabled(OGL_ARB_FRAGMENT_SHADER)
|
||||
&& Is_Extension_Enabled(OGL_ARB_VERTEX_SHADER) && Is_Extension_Enabled(OGL_SM30) )
|
||||
&& Is_Extension_Enabled(OGL_ARB_VERTEX_SHADER) /*&& Is_Extension_Enabled(OGL_SM30)*/ )
|
||||
{
|
||||
Use_GLSL = 1;
|
||||
}
|
||||
|
||||
@@ -687,7 +687,6 @@ void hud_config_synch_sliders(int i)
|
||||
// reset some ui components based on HUD config data
|
||||
void hud_config_synch_ui()
|
||||
{
|
||||
// game_load_palette();
|
||||
HUD_init_hud_color_array();
|
||||
// HC_sliders[gr_screen.res][HC_BRIGHTNESS_SLIDER].slider.pos = HUD_color_alpha-3; // convert to value from 0-10
|
||||
|
||||
@@ -1014,8 +1013,6 @@ void hud_config_set_color(int color)
|
||||
|
||||
hud_config_record_color(color);
|
||||
|
||||
// game_load_palette();
|
||||
|
||||
HUD_init_hud_color_array();
|
||||
|
||||
// apply the color to all gauges
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "graphics/2d.h"
|
||||
#include "localization/localize.h"
|
||||
#include "hud/hud.h"
|
||||
#include "mission/missiontraining.h" //for Max_directives
|
||||
#include "hud/hudescort.h"
|
||||
//#include "weapon/emp.h"
|
||||
#include "hud/hudparse.h" //Duh.
|
||||
@@ -523,6 +524,11 @@ void parse_hud_gauges_tbl(char *filename)
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
if(optional_string("$Max Directives:"))
|
||||
{
|
||||
stuff_int(&Max_directives);
|
||||
}
|
||||
|
||||
if(optional_string("$Max Escort Ships:"))
|
||||
{
|
||||
stuff_int(&Max_escort_ships);
|
||||
|
||||
@@ -2026,7 +2026,7 @@ void hud_squadmsg_call_reinforcement(int reinforcement_num, int player_num)
|
||||
// function to display a list of reinforcements available to the player
|
||||
void hud_squadmsg_reinforcement_select()
|
||||
{
|
||||
int i, k;
|
||||
int i, k, wingnum;
|
||||
reinforcements *rp;
|
||||
|
||||
if ( Num_menu_items == -1 ) {
|
||||
@@ -2042,7 +2042,32 @@ void hud_squadmsg_reinforcement_select()
|
||||
// don't put items which are not on my team
|
||||
if((Player_ship != NULL) && (ship_get_reinforcement_team(i) != Player_ship->team)){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// check the arrival cue sexpression of the ship/wing of this reinforcement.
|
||||
// Goober5000 - if it can't arrive, it doesn't count. This should check
|
||||
// for SEXP_FALSE as well as SEXP_KNOWN_FALSE, otherwise you end up with
|
||||
// a reinforcement menu containing no valid selections.
|
||||
if ( (wingnum = wing_name_lookup(rp->name, 1)) != -1 ) {
|
||||
Assert ( Wings[wingnum].arrival_cue >= 0 );
|
||||
if ( Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_FALSE
|
||||
|| Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_KNOWN_FALSE ){
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
p_object *p_objp;
|
||||
|
||||
p_objp = mission_parse_get_arrival_ship( rp->name );
|
||||
if ( p_objp != NULL ) {
|
||||
if ( Sexp_nodes[p_objp->arrival_cue].value == SEXP_FALSE
|
||||
|| Sexp_nodes[p_objp->arrival_cue].value == SEXP_KNOWN_FALSE ){
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
Int3(); // allender says bogus! reinforcement should be here since it wasn't a wing!
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Assert ( Num_menu_items < MAX_MENU_ITEMS );
|
||||
strcpy_s( MsgItems[Num_menu_items].text, rp->name );
|
||||
|
||||
@@ -1809,8 +1809,8 @@ void hud_target_live_turret(int next_flag, int auto_advance, int only_player_tar
|
||||
} else if (turret_weapon_has_subtype(&A->weapons, WP_LASER)) {
|
||||
ent[num_live_turrets].type = TYPE_FACING_LASER;
|
||||
} else {
|
||||
Int3();
|
||||
ent[num_live_turrets].type = TYPE_FACING_LASER;
|
||||
//Turret not live, bail
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1671,13 +1671,13 @@ void game_process_keys()
|
||||
}
|
||||
|
||||
//If topdown view in non-2D mission, go back to cockpit view.
|
||||
if ( (Viewer_mode & VM_TOPDOWN) && !(The_mission.flags & MISSION_FLAG_2D_MISSION)) {
|
||||
if ( (Viewer_mode & VM_TOPDOWN) && !(The_mission.flags & MISSION_FLAG_2D_MISSION) && !(Perspective_locked) ) {
|
||||
Viewer_mode &= ~VM_TOPDOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
// if in external view or chase view, go back to cockpit view
|
||||
if ( Viewer_mode & (VM_EXTERNAL|VM_CHASE|VM_OTHER_SHIP) ) {
|
||||
if ( (Viewer_mode & (VM_EXTERNAL|VM_CHASE|VM_OTHER_SHIP)) && !(Perspective_locked) ) {
|
||||
Viewer_mode &= ~(VM_EXTERNAL|VM_CHASE|VM_OTHER_SHIP);
|
||||
break;
|
||||
}
|
||||
@@ -2846,11 +2846,7 @@ int button_function(int n)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CanAutopilot(true))
|
||||
{
|
||||
StartAutopilot();
|
||||
}
|
||||
else
|
||||
if (!StartAutopilot())
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "mission/missionparse.h"
|
||||
#include "species_defs/species_defs.h"
|
||||
#include "playerman/managepilot.h"
|
||||
#include "object/objectsnd.h"
|
||||
|
||||
// flags
|
||||
#define LAB_FLAG_NORMAL (0) // default
|
||||
@@ -1848,6 +1849,7 @@ void labviewer_change_ship_lod(Tree* caller)
|
||||
The_mission.ai_profile = &Ai_profiles[Default_ai_profile];
|
||||
int test_idx = ship_create(&vmd_identity_matrix, &vmd_zero_vector, ship_index);
|
||||
obj_delete(test_idx);
|
||||
obj_snd_level_close();
|
||||
}
|
||||
|
||||
Lab_last_selected_ship = Lab_selected_index;
|
||||
|
||||
@@ -35,6 +35,9 @@ int static_rand(int num)
|
||||
{
|
||||
int a, b, c;
|
||||
|
||||
if (num < 0)
|
||||
num *= -1;
|
||||
|
||||
if (!Semirand_inited)
|
||||
init_semirand();
|
||||
|
||||
|
||||
@@ -1630,7 +1630,11 @@ void vm_matrix_to_rot_axis_and_angle(matrix *m, float *theta, vec3d *rot_axis)
|
||||
rot_axis->xyz.x = (m->vec.uvec.xyz.z - m->vec.fvec.xyz.y);
|
||||
rot_axis->xyz.y = (m->vec.fvec.xyz.x - m->vec.rvec.xyz.z);
|
||||
rot_axis->xyz.z = (m->vec.rvec.xyz.y - m->vec.uvec.xyz.x);
|
||||
vm_vec_normalize(rot_axis);
|
||||
if (IS_VEC_NULL_SQ_SAFE(rot_axis)) {
|
||||
vm_vec_make(rot_axis, 1.0f, 0.0f, 0.0f);
|
||||
} else {
|
||||
vm_vec_normalize(rot_axis);
|
||||
}
|
||||
} else { // angle is PI within limits
|
||||
*theta = PI;
|
||||
|
||||
|
||||
+33
-30
@@ -33,41 +33,42 @@
|
||||
// This is the fs2_open credit list, please only add yourself if you have actually contributed code
|
||||
// Rules!
|
||||
char *fs2_open_credit_text =
|
||||
"SOURCE CODE PROJECT STAFF:\n"
|
||||
"SOURCE CODE PROJECT STAFF:\n"
|
||||
"\n"
|
||||
"Project Leaders:\n"
|
||||
"\n"
|
||||
"Ian \"Goober5000\" Warfield\n"
|
||||
"Cliff \"chief1983\" Gordon"
|
||||
"\n"
|
||||
"Senior Advisors:\n"
|
||||
"\n"
|
||||
"Taylor Richards\n"
|
||||
"\n"
|
||||
"Senior Advisor\n"
|
||||
"\n"
|
||||
"Ian \"Goober5000\" Warfield\n"
|
||||
"Edward \"Inquisitor\" Gardner\n"
|
||||
"\n"
|
||||
"Programmers:\n"
|
||||
"\n"
|
||||
"Mike \"Bobboau\" Abegg\n"
|
||||
"Dennis \"DTP\" Pedersen\n"
|
||||
"\"EdrickV\"\n"
|
||||
"Derek \"Kazan\" Meek\n"
|
||||
"Ian \"Goober5000\" Warfield\n"
|
||||
"\"Mysterial\"\n"
|
||||
"Joe \"Righteous1\" Dowd\n"
|
||||
"Jon \"Sesquipedalian\" Stovell\n"
|
||||
"Matt \"Sticks\" Nischan\n"
|
||||
"Mike \"penguin\" Harris\n"
|
||||
"Nick \"phreak\" Iannetta\n"
|
||||
"Thomas \"RandomTiger\" Whittaker\n"
|
||||
"Taylor Richards\n"
|
||||
"Will \"##Unknown Player##\" Rousnel\n"
|
||||
"\"WMCoolmon\"\n"
|
||||
"Hassan \"Karajorma\" Kazmi\n"
|
||||
"Derek \"Kazan\" Meek\n"
|
||||
"Nick \"phreak\" Iannetta\n"
|
||||
"Mike \"Bobboau\" Abegg\n"
|
||||
"Backslash\n"
|
||||
"Echelon9\n"
|
||||
"Flaming_Sword\n"
|
||||
"FUBAR\n"
|
||||
"Iss Mneur\n"
|
||||
"kkmic\n"
|
||||
"Michael \"Zacam\" LaFleur\n"
|
||||
"Shade\n"
|
||||
"Soulstorm\n"
|
||||
"Sushi\n"
|
||||
"Swifty\n"
|
||||
"Wanderer\n"
|
||||
"Fabian \"The E\" Woltermann\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Readme Staff:\n"
|
||||
"\n"
|
||||
"\"Bottomfan\"\n"
|
||||
"Peter \"Flipside\" Dibble\n"
|
||||
"Jonathan \"Redmenace\" Willsher\n"
|
||||
"\n"
|
||||
"Web Support:\n"
|
||||
"\n"
|
||||
@@ -77,12 +78,10 @@ char *fs2_open_credit_text =
|
||||
"\n"
|
||||
"Special thanks to:\n"
|
||||
"\n"
|
||||
"\"Maeglamor\"\n"
|
||||
"for donating a graphics card!\n"
|
||||
"\n"
|
||||
"\"Lightspeed\"\n"
|
||||
"\"DaBrain\"\n"
|
||||
"for helping out with the graphics enhancements\n"
|
||||
"portej05\n"
|
||||
"Hery\n"
|
||||
"QuantumDelta\n"
|
||||
"Fury\n"
|
||||
"\n"
|
||||
"Linux and OSX version with the support of\n"
|
||||
"the icculus.org FreeSpace2 project:\n"
|
||||
@@ -102,8 +101,12 @@ char *fs2_open_credit_text =
|
||||
"\n"
|
||||
"Ogg Vorbis - (C) 2005, Xiph.Org Foundation\n"
|
||||
"JPEG - Independent JPEG Group, (C) 1991-1998, Thomas G. Lane\n"
|
||||
"\n\n"
|
||||
"\n\n";
|
||||
"libpng - Copyright (C) 1998-2010 Glenn Randers-Pehrson\n"
|
||||
"liblua - Copyright (C) 1994–2008 Lua.org, PUC-Rio\n"
|
||||
"zlib - Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n";
|
||||
|
||||
char *unmodified_credits = "ORIGINAL VOLITION STAFF:\n\n\n";
|
||||
char *mod_check = "Design:";
|
||||
|
||||
@@ -50,11 +50,7 @@ static char *Demo_title_bitmap_filename = NOX("DemoTitle1");
|
||||
// PLAYER SELECT defines
|
||||
//
|
||||
|
||||
//#define MAX_PLAYER_SELECT_LINES 8 // max # of pilots displayed at once
|
||||
int Player_select_max_lines[GR_NUM_RESOLUTIONS] = { // max # of pilots displayed at once
|
||||
8, // GR_640
|
||||
15 // GR_1024
|
||||
};
|
||||
int Max_lines; //Max number of pilots displayed in Window. Gets set in player_select_draw_list()
|
||||
|
||||
// button control defines
|
||||
#define NUM_PLAYER_SELECT_BUTTONS 8 // button control defines
|
||||
@@ -918,7 +914,7 @@ void player_select_scroll_list_down()
|
||||
gamesnd_play_iface(SND_GENERAL_FAIL);
|
||||
}
|
||||
|
||||
if (Player_select_pilot >= (Player_select_list_start + Player_select_max_lines[gr_screen.res])){
|
||||
if (Player_select_pilot >= (Player_select_list_start + Max_lines)){
|
||||
Player_select_list_start++;
|
||||
}
|
||||
}
|
||||
@@ -1064,7 +1060,12 @@ void player_select_draw_list()
|
||||
{
|
||||
int idx;
|
||||
|
||||
for (idx=0; idx<Player_select_max_lines[gr_screen.res]; idx++) {
|
||||
if (gr_screen.res == 1)
|
||||
Max_lines = 145/gr_get_font_height(); //Make the max number of lines dependent on the font height. 145 and 85 are magic numbers, based on the window size in retail.
|
||||
else
|
||||
Max_lines = 85/gr_get_font_height();
|
||||
|
||||
for (idx=0; idx<Max_lines; idx++) {
|
||||
// only draw as many pilots as we have
|
||||
if ((idx + Player_select_list_start) == Player_select_num_pilots)
|
||||
break;
|
||||
|
||||
@@ -244,7 +244,6 @@ static int Techroom_ship_modelnum;
|
||||
static float Techroom_ship_rot;
|
||||
static UI_BUTTON List_buttons[LIST_BUTTONS_MAX]; // buttons for each line of text in list
|
||||
//static int Anim_playing_id = -1;
|
||||
//static int anim_done = 0;
|
||||
static int Palette_bmp;
|
||||
//static int ShipWin01;
|
||||
//static int ShipWin02;
|
||||
@@ -393,12 +392,14 @@ void techroom_select_new_entry()
|
||||
Techroom_ship_modelnum = -1;
|
||||
Trackball_mode = 0;
|
||||
|
||||
//load animation here, we now only have one loaded
|
||||
generic_anim_init(&Current_list[Cur_entry].animation, Current_list[Cur_entry].tech_anim_filename);
|
||||
Current_list[Cur_entry].animation.ani.bg_type = bm_get_type(Tech_background_bitmap);
|
||||
if(generic_anim_stream(&Current_list[Cur_entry].animation) != -1){
|
||||
// load animation here, we now only have one loaded
|
||||
int stream_result = generic_anim_init_and_stream(&Current_list[Cur_entry].animation, Current_list[Cur_entry].tech_anim_filename, bm_get_type(Tech_background_bitmap), true);
|
||||
|
||||
if (stream_result >= 0) {
|
||||
Current_list[Cur_entry].has_anim = 1;
|
||||
} else {
|
||||
// we've failed to load any animation
|
||||
// load an image and treat it like a 1 frame animation
|
||||
Current_list[Cur_entry].bitmap = bm_load(Current_list[Cur_entry].tech_anim_filename);
|
||||
}
|
||||
}
|
||||
@@ -728,7 +729,7 @@ void tech_ship_scroll_capture()
|
||||
techroom_unload_animation();
|
||||
|
||||
techroom_select_new_entry();
|
||||
}
|
||||
}
|
||||
|
||||
void techroom_anim_render(float frametime)
|
||||
{
|
||||
@@ -808,7 +809,7 @@ void techroom_change_tab(int num)
|
||||
Ship_list[Ship_list_size].index = i;
|
||||
Ship_list[Ship_list_size].animation.num_frames = 0; // no anim for ships
|
||||
Ship_list[Ship_list_size].has_anim = 0; // no anim for ships
|
||||
Ship_list[Ship_list_size].name = (Ship_info[i].alt_name[0]) ? Ship_info[i].alt_name : Ship_info[i].name;
|
||||
Ship_list[Ship_list_size].name = *Ship_info[i].tech_title ? Ship_info[i].tech_title : (*Ship_info[i].alt_name ? Ship_info[i].alt_name : Ship_info[i].name);
|
||||
Ship_list[Ship_list_size].desc = Ship_info[i].tech_desc;
|
||||
Ship_list[Ship_list_size].model_num = -1;
|
||||
Ship_list[Ship_list_size].textures_loaded = 0;
|
||||
@@ -871,14 +872,11 @@ void techroom_change_tab(int num)
|
||||
Weapon_list[Weapon_list_size].index = i;
|
||||
Weapon_list[Weapon_list_size].desc = Weapon_info[i].tech_desc;
|
||||
Weapon_list[Weapon_list_size].has_anim = 1;
|
||||
Weapon_list[Weapon_list_size].name = Weapon_info[i].tech_title;
|
||||
Weapon_list[Weapon_list_size].name = *Weapon_info[i].tech_title ? Weapon_info[i].tech_title : Weapon_info[i].name;
|
||||
Weapon_list[Weapon_list_size].bitmap = -1;
|
||||
Weapon_list[Weapon_list_size].animation.num_frames = 0;
|
||||
Weapon_list[Weapon_list_size].model_num = -1;
|
||||
Weapon_list[Weapon_list_size].textures_loaded = 0;
|
||||
if (Weapon_list[Weapon_list_size].name[0] == 0) {
|
||||
Weapon_list[Weapon_list_size].name = Weapon_info[i].name;
|
||||
}
|
||||
// copy the weapon animation filename
|
||||
strncpy(Weapon_list[Weapon_list_size].tech_anim_filename, Weapon_info[i].tech_anim_filename, MAX_FILENAME_LEN - 1);
|
||||
|
||||
|
||||
@@ -181,6 +181,11 @@ char *Persona_type_names[MAX_PERSONA_TYPES] =
|
||||
|
||||
int Default_command_persona;
|
||||
|
||||
|
||||
// Goober5000
|
||||
// NOTE - these are truncated filenames, i.e. without extensions
|
||||
SCP_vector<SCP_string> generic_message_filenames;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// used to distort incoming messages when comms are damaged
|
||||
///////////////////////////////////////////////////////////////////
|
||||
@@ -419,7 +424,6 @@ void message_parse(bool importing_from_fsm)
|
||||
|
||||
void parse_msgtbl()
|
||||
{
|
||||
char *p1, *p2, *p3;
|
||||
int i, j;
|
||||
|
||||
// open localization
|
||||
@@ -435,27 +439,19 @@ void parse_msgtbl()
|
||||
Num_messages = 0;
|
||||
Num_personas = 0;
|
||||
|
||||
// Goober5000 - ugh, nasty nasty hack to fix the FS2 retail tables
|
||||
p1 = strstr(Mp, "#End");
|
||||
*(p1+4)=0;
|
||||
p1 = strstr(Mp, "2926");
|
||||
if (p1)
|
||||
// Goober5000 - ugh, ugly hack to fix the FS2 retail tables
|
||||
char *pVawacs25 = strstr(Mp, "Vawacs25.wav");
|
||||
if (pVawacs25)
|
||||
{
|
||||
p2 = strstr(p1, "Vawacs25.wav");
|
||||
p3 = strstr(p1, "$Name");
|
||||
if (p2 && p3 && (p2 < p3))
|
||||
char *pAwacs75 = strstr(pVawacs25, "Awacs75.wav");
|
||||
if (pAwacs75)
|
||||
{
|
||||
replace_one(p2, "Vawacs25.wav", "Awacs25.wav", 500);
|
||||
}
|
||||
}
|
||||
p1 = strstr(Mp, "2927");
|
||||
if (p1)
|
||||
{
|
||||
p2 = strstr(p1, "Awacs75.wav");
|
||||
p3 = strstr(p1, "$Name");
|
||||
if (p2 && p3 && (p2 < p3))
|
||||
{
|
||||
replace_one(p2, "Awacs75.wav", "Vawacs75.wav", 500);
|
||||
// move the 'V' from the first filename to the second, and adjust the 'A' case
|
||||
*pVawacs25 = 'A';
|
||||
for (i = 1; i < (pAwacs75 - pVawacs25) - 1; i++)
|
||||
pVawacs25[i] = pVawacs25[i+1];
|
||||
pAwacs75[-1] = 'V';
|
||||
pAwacs75[0] = 'a';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,6 +485,50 @@ void parse_msgtbl()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// additional table part!
|
||||
generic_message_filenames.clear();
|
||||
generic_message_filenames.push_back("none");
|
||||
generic_message_filenames.push_back("cuevoice");
|
||||
generic_message_filenames.push_back("emptymsg");
|
||||
generic_message_filenames.push_back("generic");
|
||||
generic_message_filenames.push_back("msgstart");
|
||||
|
||||
if (optional_string("#Simulated Speech Overrides"))
|
||||
{
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
|
||||
while (required_string_either("#End", "$File Name:"))
|
||||
{
|
||||
required_string("$File Name:");
|
||||
stuff_string(filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
// get extension
|
||||
char *ptr = strchr(filename, '.');
|
||||
if (ptr == NULL)
|
||||
{
|
||||
Warning(LOCATION, "Simulated speech override file '%s' was provided with no extension!", filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
// test extension
|
||||
if (stricmp(ptr, ".ogg") && stricmp(ptr, ".wav"))
|
||||
{
|
||||
Warning(LOCATION, "Simulated speech override file '%s' was provided with an extension other than .wav or .ogg!", filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
// truncate extension
|
||||
*ptr = '\0';
|
||||
|
||||
// add truncated file name
|
||||
generic_message_filenames.push_back(filename);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
|
||||
|
||||
// close localization
|
||||
lcl_ext_close();
|
||||
}
|
||||
@@ -859,10 +899,26 @@ void message_load_wave(int index, const char *filename)
|
||||
// Goober5000
|
||||
bool message_filename_is_generic(char *filename)
|
||||
{
|
||||
if (!strnicmp(filename, "cuevoice.wav", 8)) return true;
|
||||
if (!strnicmp(filename, "emptymsg.wav", 8)) return true;
|
||||
if (!strnicmp(filename, "generic.wav", 7)) return true;
|
||||
if (!strnicmp(filename, "msgstart.wav", 8)) return true;
|
||||
int i;
|
||||
char truncated_filename[MAX_FILENAME_LEN];
|
||||
|
||||
// truncate any file extension
|
||||
strcpy(truncated_filename, filename);
|
||||
char *ptr = strchr(truncated_filename, '.');
|
||||
|
||||
// extension must be a recognized sound file
|
||||
if ((ptr == NULL) || (stricmp(ptr, ".ogg") && stricmp(ptr, ".wav")))
|
||||
return false;
|
||||
|
||||
// truncate it
|
||||
*ptr = '\0';
|
||||
|
||||
// test against the list
|
||||
for (i = 0; i < generic_message_filenames.size(); i++)
|
||||
{
|
||||
if (!stricmp(generic_message_filenames[i].c_str(), truncated_filename))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1970,7 +2026,7 @@ void message_maybe_distort()
|
||||
snd_set_volume(Playing_messages[i].wave, 0.0f);
|
||||
} else {
|
||||
if ( was_muted )
|
||||
snd_set_volume(Playing_messages[i].wave, Master_sound_volume);
|
||||
snd_set_volume(Playing_messages[i].wave, (Master_sound_volume * aav_voice_volume));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ typedef struct {
|
||||
char Training_buf[TRAINING_MESSAGE_LENGTH];
|
||||
char *Training_lines[MAX_TRAINING_MESSAGE_LINES]; // Training message split into lines
|
||||
char Training_voice_filename[NAME_LENGTH];
|
||||
int Max_directives = TRAINING_OBJ_DISPLAY_LINES;
|
||||
int Training_message_timestamp;
|
||||
int Training_line_sizes[MAX_TRAINING_MESSAGE_LINES];
|
||||
int Training_message_method = 1;
|
||||
@@ -173,8 +174,8 @@ void training_obj_display()
|
||||
|
||||
offset = 0;
|
||||
end = Training_obj_num_lines;
|
||||
if (end > TRAINING_OBJ_DISPLAY_LINES) {
|
||||
end = TRAINING_OBJ_DISPLAY_LINES;
|
||||
if (end > Max_directives) {
|
||||
end = Max_directives;
|
||||
offset = Training_obj_num_lines - end;
|
||||
}
|
||||
|
||||
@@ -302,6 +303,9 @@ void training_mission_init()
|
||||
Training_obj_num_lines = 0;
|
||||
Training_message_queue_count = 0;
|
||||
Training_failure = 0;
|
||||
if (Max_directives > TRAINING_OBJ_LINES) {
|
||||
Max_directives = TRAINING_OBJ_LINES;
|
||||
}
|
||||
for (i=0; i<TRAINING_OBJ_LINES; i++)
|
||||
Training_obj_lines[i] = -1;
|
||||
|
||||
@@ -361,7 +365,7 @@ void sort_training_objectives()
|
||||
|
||||
// get the index of the first directive that will be displayed
|
||||
// if less than 0, display all lines
|
||||
offset = Training_obj_num_lines - TRAINING_OBJ_DISPLAY_LINES;
|
||||
offset = Training_obj_num_lines - Max_directives;
|
||||
|
||||
if (offset <= 0) {
|
||||
return;
|
||||
@@ -447,7 +451,7 @@ void sort_training_objectives()
|
||||
|
||||
// find first slot that can be bumped
|
||||
// look at the last (N-4 to N) positions
|
||||
for (slot_idx=0; slot_idx<TRAINING_OBJ_DISPLAY_LINES; slot_idx++) {
|
||||
for (slot_idx=0; slot_idx<Max_directives; slot_idx++) {
|
||||
if ( Training_obj_lines[i+offset] & TRAINING_OBJ_STATUS_KNOWN ) {
|
||||
break;
|
||||
}
|
||||
@@ -726,7 +730,7 @@ int message_play_training_voice(int index)
|
||||
|
||||
Training_voice_type = 1;
|
||||
if (Training_voice_handle >= 0)
|
||||
audiostream_play(Training_voice_handle, Master_voice_volume, 0);
|
||||
audiostream_play(Training_voice_handle, (Master_voice_volume * aav_voice_volume), 0);
|
||||
|
||||
Training_voice = index;
|
||||
return Training_voice;
|
||||
@@ -914,7 +918,11 @@ void message_training_display()
|
||||
|
||||
Training_message_visible = 0;
|
||||
message_training_queue_check();
|
||||
training_obj_display();
|
||||
|
||||
if ( !hud_disabled_except_messages() ) {
|
||||
training_obj_display();
|
||||
}
|
||||
|
||||
|
||||
if (Training_failure){
|
||||
return;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
|
||||
|
||||
extern int Max_directives;
|
||||
extern int Training_message_method;
|
||||
extern int Training_num_lines;
|
||||
extern int Training_message_visible;
|
||||
|
||||
@@ -193,7 +193,6 @@ static int Voice_ended_time;
|
||||
//static anim_instance *Cur_anim_instance = NULL;
|
||||
static generic_anim Cur_Anim;
|
||||
static char *Cur_anim_filename = "~~~~";
|
||||
static int anim_done = 0;
|
||||
|
||||
static int Cmd_brief_last_voice;
|
||||
static int Cmd_brief_paused = 0;
|
||||
@@ -320,9 +319,6 @@ void cmd_brief_stop_anim(int id)
|
||||
|
||||
void cmd_brief_new_stage(int stage)
|
||||
{
|
||||
char *p;
|
||||
char filename[NAME_LENGTH];
|
||||
|
||||
if (stage < 0) {
|
||||
cmd_brief_stop_anim(-1);
|
||||
Cur_stage = -1;
|
||||
@@ -338,11 +334,6 @@ void cmd_brief_new_stage(int stage)
|
||||
|
||||
// load a new animation if it's different to what's already playing
|
||||
if (strcmp(Cur_anim_filename, Cur_cmd_brief->stage[stage].ani_filename) != 0) {
|
||||
// set stuff up
|
||||
int stream_result = -1;
|
||||
ubyte bg_type = bm_get_type(Cmd_brief_background_bitmap);
|
||||
anim_done = 0;
|
||||
|
||||
// unload the previous anim
|
||||
if(Cur_Anim.num_frames > 0) {
|
||||
generic_anim_unload(&Cur_Anim);
|
||||
@@ -351,40 +342,8 @@ void cmd_brief_new_stage(int stage)
|
||||
// save new filename
|
||||
Cur_anim_filename = Cur_cmd_brief->stage[stage].ani_filename;
|
||||
|
||||
// hi-res support
|
||||
if (gr_screen.res == GR_1024) {
|
||||
// attempt to load a hi-res animation
|
||||
memset(filename, 0, NAME_LENGTH);
|
||||
strcpy_s(filename, "2_");
|
||||
strncat(filename, Cur_anim_filename, NAME_LENGTH - 3);
|
||||
|
||||
// remove extension
|
||||
p = strchr(filename, '.');
|
||||
if(p) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
// attempt to stream the hi-res ani
|
||||
generic_anim_init(&Cur_Anim, filename);
|
||||
Cur_Anim.ani.bg_type = bg_type;
|
||||
stream_result = generic_anim_stream(&Cur_Anim);
|
||||
}
|
||||
|
||||
// we failed to stream hi-res, or we aren't running in hi-res, so try low-res
|
||||
if (stream_result < 0) {
|
||||
strcpy_s(filename, Cur_anim_filename);
|
||||
|
||||
// remove extension
|
||||
p = strchr(filename, '.');
|
||||
if(p) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
// attempt to stream the low-res ani
|
||||
generic_anim_init(&Cur_Anim, filename);
|
||||
Cur_Anim.ani.bg_type = bg_type;
|
||||
stream_result = generic_anim_stream(&Cur_Anim);
|
||||
}
|
||||
// try to load the new anim in either high or low res
|
||||
int stream_result = generic_anim_init_and_stream(&Cur_Anim, Cur_anim_filename, bm_get_type(Cmd_brief_background_bitmap), true);
|
||||
|
||||
// we've failed to load any animation
|
||||
if (stream_result < 0) {
|
||||
|
||||
@@ -2728,11 +2728,11 @@ void ss_load_icons(int ship_class)
|
||||
{
|
||||
int first_frame, num_frames, i;
|
||||
first_frame = bm_load_animation(sip->icon_filename, &num_frames);
|
||||
if ( first_frame == -1 ) {
|
||||
Int3(); // Could not load in icon frames.. get Alan
|
||||
|
||||
Assertion(first_frame != -1, "Failed to load icon %s\n", sip->icon_filename); // Could not load in icon frames.. get Alan
|
||||
if (first_frame == -1)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for ( i = 0; i < num_frames; i++ ) {
|
||||
icon->icon_bmaps[i] = first_frame+i;
|
||||
}
|
||||
|
||||
@@ -601,10 +601,10 @@ void red_alert_store_subsys_status(red_alert_ship_status *ras, ship *shipp)
|
||||
ss = GET_FIRST(&shipp->subsys_list);
|
||||
while ( ss != END_OF_LIST( &shipp->subsys_list ) ) {
|
||||
|
||||
if ( count >= MAX_RED_ALERT_SUBSYSTEMS ) {
|
||||
Int3(); // ran out of subsystems
|
||||
break;
|
||||
}
|
||||
Assertion((count < MAX_RED_ALERT_SUBSYSTEMS), "Too many subsystems in ship %s with red-alert-carry status. Tried to store %d, maximum is %d\n", shipp->ship_name, count, MAX_RED_ALERT_SUBSYSTEMS);
|
||||
|
||||
if ( count >= MAX_RED_ALERT_SUBSYSTEMS )
|
||||
break; //Ran out of systems, better bail
|
||||
|
||||
ras->subsys_current_hits[count] = ss->current_hits;
|
||||
|
||||
|
||||
+3
-2
@@ -107,6 +107,7 @@ typedef struct submodel_instance_info {
|
||||
#define MSS_FLAG_TURRET_ALT_MATH (1 << 18) // tells the game to use additional calculations should turret have a defined y fov
|
||||
#define MSS_FLAG_DUM_ROTATES (1 << 19) // Bobboau
|
||||
#define MSS_FLAG_CARRY_SHOCKWAVE (1 << 20) // subsystem - even with 'carry no damage' flag - will carry shockwave damage to the hull
|
||||
#define MSS_FLAG_ALLOW_LANDING (1 << 21) // This subsystem can be landed on
|
||||
|
||||
// definition of stepped rotation struct
|
||||
typedef struct stepped_rotation {
|
||||
@@ -398,8 +399,8 @@ typedef struct model_path {
|
||||
} model_path;
|
||||
|
||||
typedef struct model_tmap_vert {
|
||||
short vertnum;
|
||||
short normnum;
|
||||
ushort vertnum;
|
||||
ushort normnum;
|
||||
float u,v;
|
||||
} model_tmap_vert;
|
||||
|
||||
|
||||
@@ -1593,6 +1593,9 @@ void standalone_main_init()
|
||||
|
||||
// if this is a tracker game then we have some extra tasks to perform
|
||||
if (MULTI_IS_TRACKER_GAME) {
|
||||
// disconnect and prepare for reset if we are already connected
|
||||
fs2netd_disconnect();
|
||||
|
||||
// login (duh!)
|
||||
if ( fs2netd_login() ) {
|
||||
// validate missions
|
||||
@@ -1659,7 +1662,7 @@ void multi_standalone_reset_all()
|
||||
delete_player( idx );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// make sure we go to the proper state.
|
||||
if(gameseq_get_state() == GS_STATE_STANDALONE_MAIN){
|
||||
standalone_main_init();
|
||||
|
||||
@@ -1901,7 +1901,7 @@ void multi_join_send_join_request(int as_observer)
|
||||
return;
|
||||
}
|
||||
|
||||
nprintf(("Password : %s\n",Multi_join_request.passwd));
|
||||
nprintf(("Network", "Password : %s\n", Multi_join_request.passwd));
|
||||
}
|
||||
|
||||
// fill out the join request struct
|
||||
|
||||
@@ -61,7 +61,7 @@ int collide_debris_ship( obj_pair * pair )
|
||||
vec3d hitpos;
|
||||
// create and initialize ship_ship_hit_info struct
|
||||
collision_info_struct debris_hit_info;
|
||||
memset( &debris_hit_info, -1, sizeof(collision_info_struct) );
|
||||
init_collision_info_struct(&debris_hit_info);
|
||||
|
||||
if ( pdebris->phys_info.mass > pship->phys_info.mass ) {
|
||||
debris_hit_info.heavy = pdebris;
|
||||
@@ -218,7 +218,7 @@ int collide_asteroid_ship( obj_pair * pair )
|
||||
vec3d hitpos;
|
||||
// create and initialize ship_ship_hit_info struct
|
||||
collision_info_struct asteroid_hit_info;
|
||||
memset( &asteroid_hit_info, -1, sizeof(collision_info_struct) );
|
||||
init_collision_info_struct(&asteroid_hit_info);
|
||||
|
||||
if ( pasteroid->phys_info.mass > pship->phys_info.mass ) {
|
||||
asteroid_hit_info.heavy = pasteroid;
|
||||
|
||||
+173
-54
@@ -22,20 +22,16 @@
|
||||
#include "io/joy_ff.h"
|
||||
#include "io/timer.h"
|
||||
#include "asteroid/asteroid.h"
|
||||
#include "debris/debris.h"
|
||||
#include "playerman/player.h"
|
||||
#include "object/objectdock.h"
|
||||
#include "object/objectshield.h"
|
||||
#include "parse/scripting.h"
|
||||
|
||||
|
||||
|
||||
//#pragma optimize("", off)
|
||||
//#pragma auto_inline(off)
|
||||
|
||||
#define COLLISION_FRICTION_FACTOR 0.0
|
||||
#define COLLISION_ROTATION_FACTOR 0.2
|
||||
#define SEP_VEL 5.0f // separation velocity between two ships that collide on same team.
|
||||
|
||||
#define COLLIDE_DEBUG
|
||||
#undef COLLIDE_DEBUG
|
||||
|
||||
@@ -124,6 +120,9 @@ int ship_ship_check_collision(collision_info_struct *ship_ship_hit_info, vec3d *
|
||||
ship *heavy_shipp = &Ships[heavy_obj->instance];
|
||||
ship *light_shipp = &Ships[light_obj->instance];
|
||||
|
||||
ship_info *heavy_sip = &Ship_info[heavy_shipp->ship_info_index];
|
||||
ship_info *light_sip = &Ship_info[light_shipp->ship_info_index];
|
||||
|
||||
// AL 12-4-97: we use the player_involved flag to ensure collisions are always
|
||||
// done with the player, regardless of team.
|
||||
if ( heavy_obj == Player_obj || light_obj == Player_obj ) {
|
||||
@@ -181,11 +180,11 @@ int ship_ship_check_collision(collision_info_struct *ship_ship_hit_info, vec3d *
|
||||
}
|
||||
|
||||
// If either of these objects doesn't get collision checks, abort.
|
||||
if (Ship_info[heavy_shipp->ship_info_index].flags & SIF_NO_COLLIDE) {
|
||||
if (heavy_sip->flags & SIF_NO_COLLIDE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Ship_info[light_shipp->ship_info_index].flags & SIF_NO_COLLIDE) {
|
||||
if (light_sip->flags & SIF_NO_COLLIDE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -196,7 +195,7 @@ int ship_ship_check_collision(collision_info_struct *ship_ship_hit_info, vec3d *
|
||||
// vec3d submodel_hit;
|
||||
|
||||
// Do in heavy object RF
|
||||
mc.model_num = Ship_info[heavy_shipp->ship_info_index].model_num; // Fill in the model to check
|
||||
mc.model_num = heavy_sip->model_num; // Fill in the model to check
|
||||
mc.orient = &heavy_obj->orient; // The object's orient
|
||||
|
||||
vec3d zero, p0, p1;
|
||||
@@ -228,7 +227,7 @@ int ship_ship_check_collision(collision_info_struct *ship_ship_hit_info, vec3d *
|
||||
// Set up collision info
|
||||
mc.pos = &zero; // The object's position
|
||||
mc.p1 = &p1; // Point 2 of ray to check
|
||||
mc.radius = model_get_core_radius(Ship_info[light_shipp->ship_info_index].model_num);
|
||||
mc.radius = model_get_core_radius(light_sip->model_num);
|
||||
mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE); // flags
|
||||
|
||||
// Only check invisible face polygons for ship:ship of different teams.
|
||||
@@ -475,7 +474,7 @@ int ship_ship_check_collision(collision_info_struct *ship_ship_hit_info, vec3d *
|
||||
if (heavy_shipp->team == light_shipp->team) {
|
||||
// If a couple of small ships, just move them apart.
|
||||
|
||||
if ((Ship_info[heavy_shipp->ship_info_index].flags & SIF_SMALL_SHIP) && (Ship_info[light_shipp->ship_info_index].flags & SIF_SMALL_SHIP)) {
|
||||
if ((heavy_sip->flags & SIF_SMALL_SHIP) && (light_sip->flags & SIF_SMALL_SHIP)) {
|
||||
if ((heavy_obj->flags & OF_PLAYER_SHIP) || (light_obj->flags & OF_PLAYER_SHIP)) {
|
||||
/*
|
||||
vec3d h2l_vec;
|
||||
@@ -527,8 +526,10 @@ int ship_ship_check_collision(collision_info_struct *ship_ship_hit_info, vec3d *
|
||||
vm_vec_scale_add(&perp_rel_vel, &rel_vel_h, &h_to_l_vec, -mag);
|
||||
vm_vec_normalize(&perp_rel_vel);
|
||||
|
||||
vm_vec_scale_add2(&heavy_obj->phys_info.vel, &perp_rel_vel, SEP_VEL * light_obj->phys_info.mass / mass_sum);
|
||||
vm_vec_scale_add2(&light_obj->phys_info.vel, &perp_rel_vel, -SEP_VEL * heavy_obj->phys_info.mass / mass_sum);
|
||||
vm_vec_scale_add2(&heavy_obj->phys_info.vel, &perp_rel_vel,
|
||||
heavy_sip->collision_physics.both_small_bounce * light_obj->phys_info.mass / mass_sum);
|
||||
vm_vec_scale_add2(&light_obj->phys_info.vel, &perp_rel_vel,
|
||||
-(light_sip->collision_physics.both_small_bounce) * heavy_obj->phys_info.mass / mass_sum);
|
||||
|
||||
vm_vec_rotate( &heavy_obj->phys_info.prev_ramp_vel, &heavy_obj->phys_info.vel, &heavy_obj->orient );
|
||||
vm_vec_rotate( &light_obj->phys_info.prev_ramp_vel, &light_obj->phys_info.vel, &light_obj->orient );
|
||||
@@ -541,9 +542,11 @@ int ship_ship_check_collision(collision_info_struct *ship_ship_hit_info, vec3d *
|
||||
rel_vel = 1.0f;
|
||||
}
|
||||
float mass_sum = heavy_obj->phys_info.mass + light_obj->phys_info.mass;
|
||||
vm_vec_scale_add2( &heavy_obj->phys_info.vel, &ship_ship_hit_info->light_rel_vel, SEP_VEL*light_obj->phys_info.mass/(mass_sum*rel_vel) );
|
||||
vm_vec_scale_add2( &heavy_obj->phys_info.vel, &ship_ship_hit_info->light_rel_vel,
|
||||
heavy_sip->collision_physics.bounce*light_obj->phys_info.mass/(mass_sum*rel_vel) );
|
||||
vm_vec_rotate( &heavy_obj->phys_info.prev_ramp_vel, &heavy_obj->phys_info.vel, &heavy_obj->orient );
|
||||
vm_vec_scale_add2( &light_obj->phys_info.vel, &ship_ship_hit_info->light_rel_vel, -SEP_VEL*heavy_obj->phys_info.mass/(mass_sum*rel_vel) );
|
||||
vm_vec_scale_add2( &light_obj->phys_info.vel, &ship_ship_hit_info->light_rel_vel,
|
||||
-(light_sip->collision_physics.bounce)*heavy_obj->phys_info.mass/(mass_sum*rel_vel) );
|
||||
vm_vec_rotate( &light_obj->phys_info.prev_ramp_vel, &light_obj->phys_info.vel, &light_obj->orient );
|
||||
}
|
||||
}
|
||||
@@ -602,6 +605,21 @@ int check_special_cruiser_asteroid_collision(object *heavy, object *light, float
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Find the subobject corresponding to the submodel hit
|
||||
bool check_subsystem_landing_allowed(ship_info *heavy_sip, collision_info_struct *ship_ship_hit_info) {
|
||||
if (!(heavy_sip->flags2 & SIF2_ALLOW_LANDINGS))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < heavy_sip->n_subsystems; i++) {
|
||||
if (heavy_sip->subsystems[i].flags & MSS_FLAG_ALLOW_LANDING &&
|
||||
heavy_sip->subsystems[i].subobj_num == ship_ship_hit_info->submodel_num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// input: ship_ship_hit => structure containing ship_ship hit info
|
||||
// (includes) A, B => objects colliding
|
||||
@@ -625,6 +643,13 @@ void calculate_ship_ship_collision_physics(collision_info_struct *ship_ship_hit_
|
||||
object *heavy = ship_ship_hit_info->heavy;
|
||||
object *light = ship_ship_hit_info->light;
|
||||
|
||||
// gurgh... this includes asteroids and debris too
|
||||
Assert(heavy->type == OBJ_SHIP || heavy->type == OBJ_ASTEROID || heavy->type == OBJ_DEBRIS);
|
||||
Assert(light->type == OBJ_SHIP || light->type == OBJ_ASTEROID || light->type == OBJ_DEBRIS);
|
||||
|
||||
ship_info *light_sip = (light->type == OBJ_SHIP) ? &Ship_info[Ships[light->instance].ship_info_index] : NULL;
|
||||
ship_info *heavy_sip = (heavy->type == OBJ_SHIP) ? &Ship_info[Ships[heavy->instance].ship_info_index] : NULL;
|
||||
|
||||
// make cruiser/asteroid collision softer on cruisers.
|
||||
int special_cruiser_asteroid_collision;
|
||||
int cruiser_light = 0;
|
||||
@@ -669,7 +694,18 @@ void calculate_ship_ship_collision_physics(collision_info_struct *ship_ship_hit_
|
||||
if (ship_ship_hit_info->submodel_rot_hit == 1) {
|
||||
bool set_model = false;
|
||||
|
||||
polymodel *pm = model_get(Ship_info[Ships[heavy->instance].ship_info_index].model_num);
|
||||
polymodel *pm;
|
||||
if (heavy->type == OBJ_SHIP) {
|
||||
pm = model_get(heavy_sip->model_num);
|
||||
} else if (heavy->type == OBJ_ASTEROID) {
|
||||
pm = Asteroid_info[Asteroids[heavy->instance].asteroid_type].modelp[Asteroids[heavy->instance].asteroid_subtype];
|
||||
} else if (heavy->type == OBJ_DEBRIS) {
|
||||
pm = model_get(Debris[heavy->instance].model_num);
|
||||
} else {
|
||||
// we should have caught this already
|
||||
Int3();
|
||||
pm = NULL;
|
||||
}
|
||||
|
||||
// be sure model is set
|
||||
if (pm->submodel[ship_ship_hit_info->submodel_num].sii == NULL) {
|
||||
@@ -745,6 +781,31 @@ void calculate_ship_ship_collision_physics(collision_info_struct *ship_ship_hit_
|
||||
v_rel_normal_m = -v_rel_normal_m;
|
||||
}
|
||||
|
||||
//Maybe treat the current collision as a landing
|
||||
vec3d light_local_vel;
|
||||
float light_uvec_dot_norm;
|
||||
float light_fvec_dot_norm;
|
||||
float light_rvec_dot_norm;
|
||||
bool subsys_landing_allowed = light->type == OBJ_SHIP && heavy->type == OBJ_SHIP && check_subsystem_landing_allowed(heavy_sip, ship_ship_hit_info);
|
||||
if (subsys_landing_allowed) {
|
||||
vm_vec_rotate(&light_local_vel, &ship_ship_hit_info->light_rel_vel, &light->orient);
|
||||
light_uvec_dot_norm = vm_vec_dot(&ship_ship_hit_info->collision_normal, &light->orient.vec.uvec);
|
||||
light_fvec_dot_norm = vm_vec_dot(&ship_ship_hit_info->collision_normal, &light->orient.vec.fvec);
|
||||
light_rvec_dot_norm = vm_vec_dot(&ship_ship_hit_info->collision_normal, &light->orient.vec.rvec);
|
||||
}
|
||||
if (subsys_landing_allowed &&
|
||||
light_local_vel.xyz.z < light_sip->collision_physics.landing_max_z &&
|
||||
light_local_vel.xyz.z > light_sip->collision_physics.landing_min_z &&
|
||||
light_local_vel.xyz.y > light_sip->collision_physics.landing_min_y &&
|
||||
abs(light_local_vel.xyz.x) < light_sip->collision_physics.landing_max_x &&
|
||||
light_uvec_dot_norm > 0 &&
|
||||
light_fvec_dot_norm < light_sip->collision_physics.landing_max_angle &&
|
||||
light_fvec_dot_norm > light_sip->collision_physics.landing_min_angle &&
|
||||
abs(light_rvec_dot_norm) < light_sip->collision_physics.landing_max_rot_angle)
|
||||
{
|
||||
ship_ship_hit_info->is_landing = true;
|
||||
}
|
||||
|
||||
vec3d rotational_impulse_heavy, rotational_impulse_light, delta_rotvel_heavy, delta_rotvel_light;
|
||||
vec3d delta_vel_from_delta_rotvel_heavy, delta_vel_from_delta_rotvel_light, impulse;
|
||||
float impulse_mag, heavy_denom, light_denom;
|
||||
@@ -758,7 +819,8 @@ void calculate_ship_ship_collision_physics(collision_info_struct *ship_ship_hit_
|
||||
impulse = ship_ship_hit_info->collision_normal;
|
||||
vm_vec_projection_onto_plane(&v_rel_parallel_m, &v_rel_m, &ship_ship_hit_info->collision_normal);
|
||||
collision_speed_parallel = vm_vec_normalize_safe(&v_rel_parallel_m);
|
||||
parallel_mag = float(-COLLISION_FRICTION_FACTOR) * collision_speed_parallel / vm_vec_mag(&v_rel_m);
|
||||
float friction = (light->type == OBJ_SHIP) ? light_sip->collision_physics.friction : COLLISION_FRICTION_FACTOR;
|
||||
parallel_mag = float(-friction) * collision_speed_parallel / vm_vec_mag(&v_rel_m);
|
||||
vm_vec_scale_add2(&impulse, &v_rel_parallel_m, parallel_mag);
|
||||
|
||||
// calculate the effect on the velocity of the collison point per unit impulse
|
||||
@@ -771,7 +833,8 @@ void calculate_ship_ship_collision_physics(collision_info_struct *ship_ship_hit_
|
||||
vm_vec_crossprod(&rotational_impulse_heavy, &ship_ship_hit_info->r_heavy, &impulse);
|
||||
get_I_inv(&heavy_I_inv, &heavy->phys_info.I_body_inv, &heavy->orient);
|
||||
vm_vec_rotate(&delta_rotvel_heavy, &rotational_impulse_heavy, &heavy_I_inv);
|
||||
vm_vec_scale(&delta_rotvel_heavy, float(COLLISION_ROTATION_FACTOR)); // hack decrease rotation (delta_rotvel)
|
||||
float rotation_factor = (heavy->type == OBJ_SHIP) ? heavy_sip->collision_physics.rotation_factor : COLLISION_ROTATION_FACTOR;
|
||||
vm_vec_scale(&delta_rotvel_heavy, rotation_factor); // hack decrease rotation (delta_rotvel)
|
||||
vm_vec_crossprod(&delta_vel_from_delta_rotvel_heavy, &delta_rotvel_heavy , &ship_ship_hit_info->r_heavy);
|
||||
heavy_denom = vm_vec_dotprod(&delta_vel_from_delta_rotvel_heavy, &ship_ship_hit_info->collision_normal);
|
||||
if (heavy_denom < 0) {
|
||||
@@ -791,7 +854,8 @@ void calculate_ship_ship_collision_physics(collision_info_struct *ship_ship_hit_
|
||||
vm_vec_crossprod(&rotational_impulse_light, &ship_ship_hit_info->r_light, &impulse);
|
||||
get_I_inv(&light_I_inv, &light->phys_info.I_body_inv, &light->orient);
|
||||
vm_vec_rotate(&delta_rotvel_light, &rotational_impulse_light, &light_I_inv);
|
||||
vm_vec_scale(&delta_rotvel_light, float(COLLISION_ROTATION_FACTOR)); // hack decrease rotation (delta_rotvel)
|
||||
float rotation_factor = (light->type == OBJ_SHIP) ? light_sip->collision_physics.rotation_factor : COLLISION_ROTATION_FACTOR;
|
||||
vm_vec_scale(&delta_rotvel_light, rotation_factor); // hack decrease rotation (delta_rotvel)
|
||||
vm_vec_crossprod(&delta_vel_from_delta_rotvel_light, &delta_rotvel_light, &ship_ship_hit_info->r_light);
|
||||
light_denom = vm_vec_dotprod(&delta_vel_from_delta_rotvel_light, &ship_ship_hit_info->collision_normal);
|
||||
if (light_denom < 0) {
|
||||
@@ -809,17 +873,43 @@ void calculate_ship_ship_collision_physics(collision_info_struct *ship_ship_hit_
|
||||
nprintf(("Physics", "negative impulse mag -- Get Dave A if not Descent Physics\n"));
|
||||
impulse_mag = -impulse_mag;
|
||||
}
|
||||
|
||||
|
||||
// update the physics info structs for heavy and light objects
|
||||
// since we have already calculated delta rotvel for heavy and light in world coords
|
||||
// physics should not have to recalculate this, just change into body coords (done in collide_whack)
|
||||
vm_vec_scale(&impulse, impulse_mag);
|
||||
//Assert(impulse_mag < 20e6);
|
||||
vm_vec_scale(&delta_rotvel_light, impulse_mag);
|
||||
physics_collide_whack(&impulse, &delta_rotvel_light, &light->phys_info, &light->orient);
|
||||
physics_collide_whack(&impulse, &delta_rotvel_light, &light->phys_info, &light->orient, ship_ship_hit_info->is_landing);
|
||||
vm_vec_negate(&impulse);
|
||||
vm_vec_scale(&delta_rotvel_heavy, -impulse_mag);
|
||||
physics_collide_whack(&impulse, &delta_rotvel_heavy, &heavy->phys_info, &heavy->orient);
|
||||
physics_collide_whack(&impulse, &delta_rotvel_heavy, &heavy->phys_info, &heavy->orient, true);
|
||||
|
||||
// If within certain bounds, we want to add some more rotation towards the "resting orientation" of the ship
|
||||
// These bounds are defined separately from normal "landing" bounds so that they can be more generous:
|
||||
// we can have crash landings that still re-orient the ship.
|
||||
if (subsys_landing_allowed &
|
||||
light_local_vel.xyz.z < light_sip->collision_physics.reorient_max_z &&
|
||||
light_local_vel.xyz.z > light_sip->collision_physics.reorient_min_z &&
|
||||
light_local_vel.xyz.y > light_sip->collision_physics.reorient_min_y &&
|
||||
abs(light_local_vel.xyz.x) < light_sip->collision_physics.reorient_max_x &&
|
||||
light_uvec_dot_norm > 0 &&
|
||||
light_fvec_dot_norm < light_sip->collision_physics.reorient_max_angle &&
|
||||
light_fvec_dot_norm > light_sip->collision_physics.reorient_min_angle &&
|
||||
abs(light_rvec_dot_norm) < light_sip->collision_physics.reorient_max_rot_angle)
|
||||
{
|
||||
vec3d landing_delta_rotvel;
|
||||
landing_delta_rotvel.xyz.x = (light_fvec_dot_norm * light_sip->collision_physics.reorient_mult)
|
||||
- light_sip->collision_physics.landing_rest_angle;
|
||||
// For yaw, use the dot product between vel vector (normalized) and orientation on the xz plane
|
||||
// This reduces to the following math
|
||||
// We also clamp to reduce huge nose swings at low speeds
|
||||
float xzVelMag = sqrt(light_local_vel.xyz.x * light_local_vel.xyz.x + light_local_vel.xyz.z * light_local_vel.xyz.z);
|
||||
float xzVelDotOrient = MIN(MAX((xzVelMag > 0 ? (light_local_vel.xyz.x / xzVelMag) : 0), -0.5f), 0.5f);
|
||||
landing_delta_rotvel.xyz.y = (xzVelMag > 2) ? (xzVelDotOrient * light_sip->collision_physics.reorient_mult) : 0;
|
||||
landing_delta_rotvel.xyz.z = light_rvec_dot_norm * light_sip->collision_physics.reorient_mult * -1;
|
||||
vm_vec_add2( &light->phys_info.rotvel, &landing_delta_rotvel );
|
||||
}
|
||||
|
||||
// Find final positions
|
||||
// We will try not to worry about the left over time in the frame
|
||||
@@ -835,11 +925,18 @@ void calculate_ship_ship_collision_physics(collision_info_struct *ship_ship_hit_
|
||||
|
||||
Assert( !vm_is_vec_nan(&direction_light) );
|
||||
vm_vec_scale_add2(&heavy->pos, &direction_light, 0.2f * light->phys_info.mass / (heavy->phys_info.mass + light->phys_info.mass));
|
||||
vm_vec_scale_add2(&light->pos, &direction_light, -0.2f * heavy->phys_info.mass / (heavy->phys_info.mass + light->phys_info.mass));
|
||||
vm_vec_scale_add2(&heavy->pos, &ship_ship_hit_info->collision_normal, -0.1f * light->phys_info.mass / (heavy->phys_info.mass + light->phys_info.mass));
|
||||
vm_vec_scale_add2(&light->pos, &ship_ship_hit_info->collision_normal, 0.1f * heavy->phys_info.mass / (heavy->phys_info.mass + light->phys_info.mass));
|
||||
//For landings, we want minimal movement on the light ship (just enough to keep the collision detection honest)
|
||||
//TODO: Solution that works reliably landing on a moving ship
|
||||
if (ship_ship_hit_info->is_landing) {
|
||||
vm_vec_scale_add2(&light->pos, &ship_ship_hit_info->collision_normal, LANDING_POS_OFFSET);
|
||||
}
|
||||
else {
|
||||
vm_vec_scale_add2(&light->pos, &direction_light, -0.2f * heavy->phys_info.mass / (heavy->phys_info.mass + light->phys_info.mass));
|
||||
vm_vec_scale_add2(&light->pos, &ship_ship_hit_info->collision_normal, 0.1f * heavy->phys_info.mass / (heavy->phys_info.mass + light->phys_info.mass));
|
||||
}
|
||||
|
||||
// restore mass in case of special cruuiser / asteroid collision
|
||||
// restore mass in case of special cruiser / asteroid collision
|
||||
if (special_cruiser_asteroid_collision) {
|
||||
if (cruiser_light) {
|
||||
light->phys_info.mass = copy_mass;
|
||||
@@ -1123,11 +1220,13 @@ int collide_ship_ship( obj_pair * pair )
|
||||
}
|
||||
}
|
||||
|
||||
ship_info *light_sip = &Ship_info[Ships[LightOne->instance].ship_info_index];
|
||||
|
||||
// create ship_ship_or_debris_hit
|
||||
// inputs obj A, obj B
|
||||
// outputs hitpos, impulse (for damage), shield hit tri (for quadrant)
|
||||
collision_info_struct ship_ship_hit_info;
|
||||
memset(&ship_ship_hit_info, -1, sizeof(collision_info_struct));
|
||||
init_collision_info_struct(&ship_ship_hit_info);
|
||||
|
||||
ship_ship_hit_info.heavy = HeavyOne; // heavy object, generally slower moving
|
||||
ship_ship_hit_info.light = LightOne; // light object, generally faster moving
|
||||
@@ -1214,7 +1313,8 @@ int collide_ship_ship( obj_pair * pair )
|
||||
// }
|
||||
// }
|
||||
#endif
|
||||
if ( player_involved ) {
|
||||
//Only flash the "Collision" text if not landing
|
||||
if ( player_involved && !ship_ship_hit_info.is_landing) {
|
||||
hud_start_text_flash(XSTR("Collision", 1431), 2000);
|
||||
}
|
||||
}
|
||||
@@ -1223,7 +1323,23 @@ int collide_ship_ship( obj_pair * pair )
|
||||
|
||||
// vm_vec_add(&world_hit_pos, &ship_ship_hit_info.heavy->pos, &ship_ship_hit_info.hit_pos);
|
||||
|
||||
collide_ship_ship_do_sound(&world_hit_pos, A, B, player_involved);
|
||||
//If this is a landing, play a different sound
|
||||
if (ship_ship_hit_info.is_landing) {
|
||||
if (vm_vec_mag(&ship_ship_hit_info.light_rel_vel) > MIN_LANDING_SOUND_VEL) {
|
||||
if ( player_involved ) {
|
||||
if ( !snd_is_playing(Player_collide_sound) ) {
|
||||
Player_collide_sound = snd_play_3d( &Snds[light_sip->collision_physics.landing_sound_idx], &world_hit_pos, &View_position );
|
||||
}
|
||||
} else {
|
||||
if ( !snd_is_playing(AI_collide_sound) ) {
|
||||
AI_collide_sound = snd_play_3d( &Snds[light_sip->collision_physics.landing_sound_idx], &world_hit_pos, &View_position );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
collide_ship_ship_do_sound(&world_hit_pos, A, B, player_involved);
|
||||
}
|
||||
|
||||
// check if we should do force feedback stuff
|
||||
if (player_involved && (ship_ship_hit_info.impulse > 0)) {
|
||||
@@ -1258,35 +1374,38 @@ int collide_ship_ship( obj_pair * pair )
|
||||
|
||||
// nprintf(("AI", "Ship:ship collision: %s and %s.\n", Ships[A->instance].ship_name, Ships[B->instance].ship_name));
|
||||
|
||||
// Scale damage based on skill level for player.
|
||||
if ((LightOne->flags & OF_PLAYER_SHIP) || (HeavyOne->flags & OF_PLAYER_SHIP)) {
|
||||
damage *= (float) (Game_skill_level*Game_skill_level+1)/(NUM_SKILL_LEVELS+1);
|
||||
} else if (Ships[LightOne->instance].team == Ships[HeavyOne->instance].team) {
|
||||
// Decrease damage if non-player ships and not large.
|
||||
// Looks dumb when fighters are taking damage from bumping into each other.
|
||||
if ((LightOne->radius < 50.0f) && (HeavyOne->radius <50.0f)) {
|
||||
damage /= 4.0f;
|
||||
//Only do damage if not a landing
|
||||
if (!ship_ship_hit_info.is_landing) {
|
||||
// Scale damage based on skill level for player.
|
||||
if ((LightOne->flags & OF_PLAYER_SHIP) || (HeavyOne->flags & OF_PLAYER_SHIP)) {
|
||||
damage *= (float) (Game_skill_level*Game_skill_level+1)/(NUM_SKILL_LEVELS+1);
|
||||
} else if (Ships[LightOne->instance].team == Ships[HeavyOne->instance].team) {
|
||||
// Decrease damage if non-player ships and not large.
|
||||
// Looks dumb when fighters are taking damage from bumping into each other.
|
||||
if ((LightOne->radius < 50.0f) && (HeavyOne->radius <50.0f)) {
|
||||
damage /= 4.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float dam2 = (100.0f * damage/LightOne->phys_info.mass);
|
||||
|
||||
int quadrant_num = get_ship_quadrant_from_global(&world_hit_pos, ship_ship_hit_info.heavy);
|
||||
//nprintf(("AI", "Ship %s hit in quad #%i\n", Ships[ship_ship_hit_info.heavy->instance].ship_name, quadrant_num));
|
||||
if ((ship_ship_hit_info.heavy->flags & OF_NO_SHIELDS) || !ship_is_shield_up(ship_ship_hit_info.heavy, quadrant_num) ) {
|
||||
quadrant_num = -1;
|
||||
}
|
||||
|
||||
ship_apply_local_damage(ship_ship_hit_info.heavy, ship_ship_hit_info.light, &world_hit_pos, 100.0f * damage/HeavyOne->phys_info.mass, quadrant_num, CREATE_SPARKS, ship_ship_hit_info.submodel_num, &ship_ship_hit_info.collision_normal);
|
||||
hud_shield_quadrant_hit(ship_ship_hit_info.heavy, quadrant_num);
|
||||
|
||||
//nprintf(("AI", "Ship %s hit in quad #%i\n", Ships[ship_ship_hit_info.light->instance].ship_name, quadrant_num));
|
||||
// don't draw sparks (using sphere hitpos)
|
||||
ship_apply_local_damage(ship_ship_hit_info.light, ship_ship_hit_info.heavy, &world_hit_pos, dam2, MISS_SHIELDS, NO_SPARKS, -1, &ship_ship_hit_info.collision_normal);
|
||||
hud_shield_quadrant_hit(ship_ship_hit_info.light, quadrant_num);
|
||||
|
||||
maybe_push_little_ship_from_fast_big_ship(ship_ship_hit_info.heavy, ship_ship_hit_info.light, ship_ship_hit_info.impulse, &ship_ship_hit_info.collision_normal);
|
||||
//nprintf(("AI", "Damage to %s = %7.3f\n", Ships[LightOne->instance].ship_name, dam2));
|
||||
}
|
||||
|
||||
float dam2 = (100.0f * damage/LightOne->phys_info.mass);
|
||||
|
||||
int quadrant_num = get_ship_quadrant_from_global(&world_hit_pos, ship_ship_hit_info.heavy);
|
||||
//nprintf(("AI", "Ship %s hit in quad #%i\n", Ships[ship_ship_hit_info.heavy->instance].ship_name, quadrant_num));
|
||||
if ((ship_ship_hit_info.heavy->flags & OF_NO_SHIELDS) || !ship_is_shield_up(ship_ship_hit_info.heavy, quadrant_num) ) {
|
||||
quadrant_num = -1;
|
||||
}
|
||||
|
||||
ship_apply_local_damage(ship_ship_hit_info.heavy, ship_ship_hit_info.light, &world_hit_pos, 100.0f * damage/HeavyOne->phys_info.mass, quadrant_num, CREATE_SPARKS, ship_ship_hit_info.submodel_num, &ship_ship_hit_info.collision_normal);
|
||||
hud_shield_quadrant_hit(ship_ship_hit_info.heavy, quadrant_num);
|
||||
|
||||
//nprintf(("AI", "Ship %s hit in quad #%i\n", Ships[ship_ship_hit_info.light->instance].ship_name, quadrant_num));
|
||||
// don't draw sparks (using sphere hitpos)
|
||||
ship_apply_local_damage(ship_ship_hit_info.light, ship_ship_hit_info.heavy, &world_hit_pos, dam2, MISS_SHIELDS, NO_SPARKS, -1, &ship_ship_hit_info.collision_normal);
|
||||
hud_shield_quadrant_hit(ship_ship_hit_info.light, quadrant_num);
|
||||
|
||||
maybe_push_little_ship_from_fast_big_ship(ship_ship_hit_info.heavy, ship_ship_hit_info.light, ship_ship_hit_info.impulse, &ship_ship_hit_info.collision_normal);
|
||||
//nprintf(("AI", "Damage to %s = %7.3f\n", Ships[LightOne->instance].ship_name, dam2));
|
||||
}
|
||||
|
||||
if(!(b_override && !a_override))
|
||||
|
||||
@@ -1071,3 +1071,12 @@ void set_hit_struct_info(collision_info_struct *hit, mc_info *mc, int submodel_r
|
||||
|
||||
hit->submodel_rot_hit = submodel_rot_hit;
|
||||
}
|
||||
|
||||
//Previously, this was done with
|
||||
//memset(&ship_ship_hit_info, -1, sizeof(collision_info_struct));
|
||||
//All those -1s are to replicate that logic
|
||||
void init_collision_info_struct(collision_info_struct *cis)
|
||||
{
|
||||
memset(cis, -1, sizeof(collision_info_struct));
|
||||
cis->is_landing = false;
|
||||
}
|
||||
@@ -35,8 +35,14 @@ typedef struct collision_info_struct {
|
||||
int submodel_num; // submodel of heavy object that is hit
|
||||
int edge_hit; // if edge is hit, need to change collision normal
|
||||
int submodel_rot_hit; // if collision is against rotating submodel
|
||||
bool is_landing; //SUSHI: Maybe treat current collision as a landing
|
||||
} collision_info_struct;
|
||||
|
||||
//Collision physics constants
|
||||
#define COLLISION_FRICTION_FACTOR 0.0f //Default value if not set in ships.tbl
|
||||
#define COLLISION_ROTATION_FACTOR 0.2f //Default value if not set in ships.tbl
|
||||
#define MIN_LANDING_SOUND_VEL 2.0f
|
||||
#define LANDING_POS_OFFSET 0.05f
|
||||
|
||||
//===============================================================================
|
||||
// GENERAL COLLISION DETECTION HELPER FUNCTIONS
|
||||
@@ -138,4 +144,5 @@ int get_ship_quadrant_from_global(vec3d *global_pos, object *objp);
|
||||
|
||||
int reject_due_collision_groups(object *A, object *B);
|
||||
|
||||
void init_collision_info_struct(collision_info_struct *cis);
|
||||
#endif
|
||||
@@ -779,8 +779,8 @@ void obj_move_call_physics(object *objp, float frametime)
|
||||
|
||||
if (shipp->weapons.num_secondary_banks > 0) {
|
||||
polymodel *pm = model_get(Ship_info[shipp->ship_info_index].model_num);
|
||||
Assert( pm != NULL );
|
||||
Assert( pm->missile_banks != NULL );
|
||||
Assertion( pm != NULL, "No polymodel found for ship %s", Ship_info[shipp->ship_info_index].name );
|
||||
Assertion( pm->missile_banks != NULL, "Ship %s has %d secondary banks, but no missile banks could be found.\n", Ship_info[shipp->ship_info_index].name, shipp->weapons.num_secondary_banks );
|
||||
|
||||
for (int i = 0; i < shipp->weapons.num_secondary_banks; i++) {
|
||||
//if there are no missles left don't bother
|
||||
|
||||
@@ -673,6 +673,10 @@ int obj_snd_assign(int objnum, int sndnum, vec3d *pos, int main, int flags, ship
|
||||
if ( Obj_snd_enabled == FALSE )
|
||||
return -1;
|
||||
|
||||
//Initialize object sound list, if not initialized
|
||||
if (!Obj_snd_level_inited)
|
||||
obj_snd_level_init();
|
||||
|
||||
obj_snd *snd = NULL;
|
||||
object *objp = &Objects[objnum];
|
||||
int idx, sound_index;
|
||||
|
||||
+123
-4
@@ -3248,6 +3248,17 @@ ADE_FUNC(getScreenCoords, l_Vector, NULL, "Gets screen cordinates of a world vec
|
||||
return ade_set_args(L, "ff", vtx.sx, vtx.sy);
|
||||
}
|
||||
|
||||
ADE_FUNC(getNormalized, l_Vector, NULL, "Returns a normalized version of the vector", "vector", "Normalized Vector, or NIL if invalid")
|
||||
{
|
||||
vec3d v3;
|
||||
if(!ade_get_args(L, "o", l_Vector.Get(&v3)))
|
||||
return ADE_RETURN_NIL;
|
||||
|
||||
vm_vec_normalize(&v3);
|
||||
|
||||
return ade_set_args(L, "o", l_Vector.Set(v3));
|
||||
}
|
||||
|
||||
//**********HANDLE: material
|
||||
static const int THT_INDEPENDENT = 0;
|
||||
static const int THT_OBJECT = 1;
|
||||
@@ -4091,6 +4102,69 @@ ADE_VIRTVAR(CollisionGroups, l_Object, "number", "Collision group data", "number
|
||||
return ade_set_args(L, "i", objh->objp->collision_group_id);
|
||||
}
|
||||
|
||||
ADE_FUNC(getfvec, l_Object, "[boolean normalize]", "Returns the objects' current fvec.", "vector", "Objects' forward vector, or nil if invalid. If called with a true argument, vector will be normalized.")
|
||||
{
|
||||
object_h *objh = NULL;
|
||||
object *obj = NULL;
|
||||
bool normalize = false;
|
||||
|
||||
if (!ade_get_args(L, "o|b", l_Object.GetPtr(&objh), &normalize)) {
|
||||
return ADE_RETURN_NIL;
|
||||
}
|
||||
|
||||
if(!objh->IsValid())
|
||||
return ADE_RETURN_NIL;
|
||||
|
||||
obj = objh->objp;
|
||||
vec3d v1 = obj->orient.vec.fvec;
|
||||
if (normalize)
|
||||
vm_vec_normalize(&v1);
|
||||
|
||||
return ade_set_args(L, "o", l_Vector.Set(v1));
|
||||
}
|
||||
|
||||
ADE_FUNC(getuvec, l_Object, "[boolean normalize]", "Returns the objects' current uvec.", "vector", "Objects' up vector, or nil if invalid. If called with a true argument, vector will be normalized.")
|
||||
{
|
||||
object_h *objh = NULL;
|
||||
object *obj = NULL;
|
||||
bool normalize = false;
|
||||
|
||||
if (!ade_get_args(L, "o|b", l_Object.GetPtr(&objh), &normalize)) {
|
||||
return ADE_RETURN_NIL;
|
||||
}
|
||||
|
||||
if(!objh->IsValid())
|
||||
return ADE_RETURN_NIL;
|
||||
|
||||
obj = objh->objp;
|
||||
vec3d v1 = obj->orient.vec.uvec;
|
||||
if (normalize)
|
||||
vm_vec_normalize(&v1);
|
||||
|
||||
return ade_set_args(L, "o", l_Vector.Set(v1));
|
||||
}
|
||||
|
||||
ADE_FUNC(getrvec, l_Object, "[boolean normalize]", "Returns the objects' current rvec.", "vector", "Objects' rvec, or nil if invalid. If called with a true argument, vector will be normalized.")
|
||||
{
|
||||
object_h *objh = NULL;
|
||||
object *obj = NULL;
|
||||
bool normalize = false;
|
||||
|
||||
if (!ade_get_args(L, "o|b", l_Object.GetPtr(&objh), &normalize)) {
|
||||
return ADE_RETURN_NIL;
|
||||
}
|
||||
|
||||
if(!objh->IsValid())
|
||||
return ADE_RETURN_NIL;
|
||||
|
||||
obj = objh->objp;
|
||||
vec3d v1 = obj->orient.vec.fvec;
|
||||
if (normalize)
|
||||
vm_vec_normalize(&v1);
|
||||
|
||||
return ade_set_args(L, "o", l_Vector.Set(v1));
|
||||
}
|
||||
|
||||
ADE_FUNC(checkRayCollision, l_Object, "vector Start Point, vector End Point, [boolean Local]", "Checks the collisions between the polygons of the current object and a ray", "vector Position", "World collision point (local if boolean is set to true), nil if no collisions")
|
||||
{
|
||||
object_h *objh = NULL;
|
||||
@@ -4105,20 +4179,27 @@ ADE_FUNC(checkRayCollision, l_Object, "vector Start Point, vector End Point, [bo
|
||||
return ADE_RETURN_NIL;
|
||||
|
||||
obj = objh->objp;
|
||||
int flags = 0;
|
||||
int submodel = -1;
|
||||
|
||||
switch(obj->type) {
|
||||
case OBJ_SHIP:
|
||||
model_num = Ship_info[Ships[obj->instance].ship_info_index].model_num;
|
||||
flags = (MC_CHECK_MODEL | MC_CHECK_RAY);
|
||||
break;
|
||||
case OBJ_WEAPON:
|
||||
model_num = Weapon_info[Weapons[obj->instance].weapon_info_index].model_num;
|
||||
flags = (MC_CHECK_MODEL | MC_CHECK_RAY);
|
||||
break;
|
||||
case OBJ_DEBRIS:
|
||||
model_num = Debris[obj->instance].model_num;
|
||||
flags = (MC_CHECK_MODEL | MC_CHECK_RAY | MC_SUBMODEL);
|
||||
submodel = Debris[obj->instance].submodel_num;
|
||||
break;
|
||||
case OBJ_ASTEROID:
|
||||
temp = Asteroids[obj->instance].asteroid_subtype;
|
||||
model_num = Asteroid_info[Asteroids[obj->instance].asteroid_type].model_num[temp];
|
||||
flags = (MC_CHECK_MODEL | MC_CHECK_RAY);
|
||||
break;
|
||||
default:
|
||||
return ADE_RETURN_NIL;
|
||||
@@ -4130,11 +4211,12 @@ ADE_FUNC(checkRayCollision, l_Object, "vector Start Point, vector End Point, [bo
|
||||
mc_info hull_check;
|
||||
|
||||
hull_check.model_num = model_num;
|
||||
hull_check.submodel_num = submodel;
|
||||
hull_check.orient = &obj->orient;
|
||||
hull_check.pos = &obj->pos;
|
||||
hull_check.p0 = v3a;
|
||||
hull_check.p1 = v3b;
|
||||
hull_check.flags = MC_CHECK_MODEL | MC_CHECK_RAY;
|
||||
hull_check.flags = flags;
|
||||
|
||||
if ( !model_collide(&hull_check) ) {
|
||||
return ADE_RETURN_NIL;
|
||||
@@ -5521,7 +5603,7 @@ ADE_VIRTVAR(SecondaryBanks, l_Subsystem, "weaponbanktype", "Array of secondary w
|
||||
}
|
||||
|
||||
|
||||
ADE_VIRTVAR(Target, l_Subsystem, "object", "Object targetted by this subsystem", "object", "Targeted object, or invalid object handle if subsystem handle is invalid")
|
||||
ADE_VIRTVAR(Target, l_Subsystem, "object", "Object targetted by this subsystem. If used to set a new target, AI targeting will be switched off.", "object", "Targeted object, or invalid object handle if subsystem handle is invalid")
|
||||
{
|
||||
ship_subsys_h *sso;
|
||||
object_h *objh;
|
||||
@@ -5538,11 +5620,28 @@ ADE_VIRTVAR(Target, l_Subsystem, "object", "Object targetted by this subsystem",
|
||||
ss->turret_enemy_objnum = OBJ_INDEX(objh->objp);
|
||||
ss->turret_enemy_sig = objh->sig;
|
||||
ss->targeted_subsys = NULL;
|
||||
ss->scripting_target_override = true;
|
||||
}
|
||||
|
||||
return ade_set_object_with_breed(L, ss->turret_enemy_objnum);
|
||||
}
|
||||
|
||||
ADE_FUNC(targetingOverride, l_Subsystem, "boolean", "If set to true, AI targeting for this turret is switched off. If set to false, the AI will take over again.", "boolean", "Returns true if successful, false otherwise")
|
||||
{
|
||||
bool targetOverride = false;
|
||||
ship_subsys_h *sso;
|
||||
if(!ade_get_args(L, "ob", l_Subsystem.GetPtr(&sso), &targetOverride))
|
||||
return ADE_RETURN_FALSE;
|
||||
|
||||
if(!sso->IsValid())
|
||||
return ADE_RETURN_FALSE;
|
||||
|
||||
ship_subsys *ss = sso->ss;
|
||||
|
||||
ss->scripting_target_override = targetOverride;
|
||||
return ADE_RETURN_TRUE;
|
||||
}
|
||||
|
||||
ADE_FUNC(hasFired, l_Subsystem, NULL, "Determine if a subsystem has fired", "boolean", "true if if fired, false if not fired, or nil if invalid. resets fired flag when called.")
|
||||
{
|
||||
ship_subsys_h *sso;
|
||||
@@ -6247,6 +6346,7 @@ ADE_FUNC(hasShipExploded, l_Ship, NULL, "Checks if the ship explosion event has
|
||||
if (shipp->pre_death_explosion_happened == 1) {
|
||||
return ade_set_args(L, "i", 1);
|
||||
}
|
||||
return ade_set_args(L, "i", 3);
|
||||
}
|
||||
|
||||
return ade_set_args(L, "i", 0);
|
||||
@@ -6706,6 +6806,25 @@ ADE_FUNC(isWarpingIn, l_Ship, NULL, "Checks if ship is warping in", "boolean", "
|
||||
return ADE_RETURN_FALSE;
|
||||
}
|
||||
|
||||
ADE_FUNC(getEMP, l_Ship, NULL, "Returns the current emp effect strength acting on the object", "number", "Current EMP effect strength or NIL if object is invalid")
|
||||
{
|
||||
object_h *objh = NULL;
|
||||
object *obj = NULL;
|
||||
|
||||
if (!ade_get_args(L, "o", l_Ship.GetPtr(&objh))) {
|
||||
return ADE_RETURN_NIL;
|
||||
}
|
||||
|
||||
if(!objh->IsValid())
|
||||
return ADE_RETURN_NIL;
|
||||
|
||||
obj = objh->objp;
|
||||
|
||||
ship *shipp = &Ships[obj->instance];
|
||||
|
||||
return ade_set_args(L, "f", shipp->emp_intensity);
|
||||
}
|
||||
|
||||
//**********HANDLE: Weapon
|
||||
ade_obj<object_h> l_Weapon("weapon", "Weapon handle", &l_Object);
|
||||
|
||||
@@ -8140,7 +8259,7 @@ ADE_FUNC(playGameSound, l_Audio, "Sound index, [Panning (-1.0 left to 1.0 right)
|
||||
if(vol > 100.0f)
|
||||
vol = 100.0f;
|
||||
|
||||
idx = snd_play(&Snds[idx], pan, vol*0.01f, pri, voice_msg);
|
||||
idx = snd_play(&Snds[gamesnd_get_by_tbl_index(idx)], pan, vol*0.01f, pri, voice_msg);
|
||||
|
||||
return ade_set_args(L, "b", idx > -1);
|
||||
}
|
||||
@@ -8151,7 +8270,7 @@ ADE_FUNC(playInterfaceSound, l_Audio, "Sound index", "Plays a sound from #Interf
|
||||
if(!ade_get_args(L, "i", &idx))
|
||||
return ade_set_error(L, "b", false);
|
||||
|
||||
gamesnd_play_iface(idx);
|
||||
gamesnd_play_iface(gamesnd_get_by_iface_tbl_index(idx));
|
||||
|
||||
return ade_set_args(L, "b", idx > -1);
|
||||
}
|
||||
|
||||
@@ -2365,7 +2365,9 @@ int stuff_loadout_list (int *ilp, int max_ints, int lookup_type)
|
||||
}
|
||||
else if ((lookup_type == MISSION_LOADOUT_WEAPON_LIST) && (!(Weapon_info[index].wi_flags & WIF_PLAYER_ALLOWED)) ) {
|
||||
clean_loadout_list_entry();
|
||||
Warning(LOCATION, "Weapon type \"%s\" found in loadout of mission file. This class is not marked as a player allowed weapon...skipping", str);
|
||||
nprintf(("Warning", "Warning: Weapon type %s found in loadout of mission file. This class is not marked as a player allowed weapon...skipping\n", str));
|
||||
if ( !Is_standalone )
|
||||
Warning(LOCATION, "Weapon type \"%s\" found in loadout of mission file. This class is not marked as a player allowed weapon...skipping", str);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+814
-121
File diff suppressed because it is too large.
Load diff
+25
-6
@@ -117,6 +117,9 @@ struct ship;
|
||||
#define OPF_HUD_ELEMENT 71 // A magic name of a specific HUD element
|
||||
#define OPF_SOUND_ENVIRONMENT 72 // Goober5000 - one of EFX_presets, per Taylor
|
||||
#define OPF_SOUND_ENVIRONMENT_OPTION 73 // Goober5000 - one of Taylor's options
|
||||
#define OPF_EXPLOSION_OPTION 74 // Goober5000
|
||||
#define OPF_AUDIO_VOLUME_OPTION 75 // The E
|
||||
#define OPF_WEAPON_BANK_NUMBER 76 // Karajomra - The number of a primary/secondary/tertiary weapon bank or all of them
|
||||
|
||||
// Operand return types
|
||||
#define OPR_NUMBER 1 // returns number
|
||||
@@ -338,6 +341,8 @@ struct ship;
|
||||
#define OP_GET_THROTTLE_SPEED (0x003a | OP_CATEGORY_STATUS | OP_NONCAMPAIGN_FLAG) // Karajorma
|
||||
#define OP_HITS_LEFT_SUBSYSTEM_GENERIC (0x003b | OP_CATEGORY_STATUS | OP_NONCAMPAIGN_FLAG) // Goober5000
|
||||
#define OP_HITS_LEFT_SUBSYSTEM_SPECIFIC (0x003c | OP_CATEGORY_STATUS | OP_NONCAMPAIGN_FLAG) // Goober5000
|
||||
#define OP_HAS_PRIMARY_WEAPON (0x003d | OP_CATEGORY_STATUS | OP_NONCAMPAIGN_FLAG) // Karajorma
|
||||
#define OP_HAS_SECONDARY_WEAPON (0x003e | OP_CATEGORY_STATUS | OP_NONCAMPAIGN_FLAG) // Karajorma
|
||||
|
||||
|
||||
// conditional sexpressions
|
||||
@@ -468,7 +473,7 @@ struct ship;
|
||||
#define OP_CLOSE_SOUND_FROM_FILE (0x0064 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // Goober5000
|
||||
#define OP_HUD_DISABLE (0x0065 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // Goober5000
|
||||
#define OP_KAMIKAZE (0x0066 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) //-Sesquipedalian
|
||||
#define OP_NOT_KAMIKAZE (0x0067 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) //-Sesquipedalian
|
||||
#define OP_MISSION_SET_SUBSPACE (0x0067 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG)
|
||||
#define OP_TURRET_TAGGED_SPECIFIC (0x0068 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) //phreak
|
||||
#define OP_TURRET_TAGGED_CLEAR_SPECIFIC (0x0069 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) //phreak
|
||||
#define OP_LOCK_ROTATING_SUBSYSTEM (0x006a | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // Goober5000
|
||||
@@ -584,10 +589,13 @@ struct ship;
|
||||
#define OP_SET_ARMOR_TYPE (0x00d2 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // FUBAR
|
||||
#define OP_CUTSCENES_SHOW_SUBTITLE_TEXT (0x00d3 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // Goober5000
|
||||
#define OP_CUTSCENES_SHOW_SUBTITLE_IMAGE (0x00d4 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // Goober5000
|
||||
#define OP_MISSION_SET_SUBSPACE (0x00d5 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG)
|
||||
#define OP_HUD_DISPLAY_GAUGE (0x00d6 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG)
|
||||
#define OP_SET_SOUND_ENVIRONMENT (0x00d7 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // Taylor
|
||||
#define OP_UPDATE_SOUND_ENVIRONMENT (0x00d8 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // Taylor
|
||||
#define OP_HUD_DISPLAY_GAUGE (0x00d5 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG)
|
||||
#define OP_SET_SOUND_ENVIRONMENT (0x00d6 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // Taylor
|
||||
#define OP_UPDATE_SOUND_ENVIRONMENT (0x00d7 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // Taylor
|
||||
#define OP_SET_EXPLOSION_OPTION (0x00d8 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // Goober5000
|
||||
#define OP_ADJUST_AUDIO_VOLUME (0x00d9 | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // The E
|
||||
#define OP_SHIP_CHANGE_CALLSIGN (0x00da | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // FUBAR
|
||||
#define OP_IS_FACING (0x00db | OP_CATEGORY_CHANGE | OP_NONCAMPAIGN_FLAG) // The E
|
||||
|
||||
/* made obsolete by Goober5000
|
||||
// debugging sexpressions
|
||||
@@ -687,11 +695,13 @@ struct ship;
|
||||
// defines for string constants
|
||||
#define SEXP_HULL_STRING "Hull"
|
||||
#define SEXP_SIM_HULL_STRING "Simulated Hull"
|
||||
#define SEXP_SHIELD_STRING "Shields"
|
||||
#define SEXP_ALL_ENGINES_STRING "<all engines>"
|
||||
#define SEXP_ALL_TURRETS_STRING "<all turrets>"
|
||||
#define SEXP_ARGUMENT_STRING "<argument>"
|
||||
#define SEXP_NONE_STRING "<none>"
|
||||
#define SEXP_SHIELD_STRING "Shields"
|
||||
#define SEXP_ANY_STRING "<any string>"
|
||||
#define SEXP_ALL_BANKS_STRING "<all weapon banks>"
|
||||
|
||||
// macros for accessing sexpression atoms
|
||||
#define CAR(n) ((n < 0) ? -1 : Sexp_nodes[n].first)
|
||||
@@ -856,6 +866,7 @@ char *CTEXT(int n);
|
||||
#define SEXP_CHECK_INVALID_HUD_ELEMENT -143
|
||||
#define SEXP_CHECK_INVALID_SOUND_ENVIRONMENT -144
|
||||
#define SEXP_CHECK_INVALID_SOUND_ENVIRONMENT_OPTION -145
|
||||
#define SEXP_CHECK_INVALID_EXPLOSION_OPTION -146
|
||||
|
||||
#define TRAINING_CONTEXT_SPEED (1<<0)
|
||||
#define TRAINING_CONTEXT_FLY_PATH (1<<1)
|
||||
@@ -1061,6 +1072,14 @@ void multi_sexp_eval();
|
||||
extern int Num_sound_environment_options;
|
||||
extern char *Sound_environment_option[];
|
||||
|
||||
// Goober5000
|
||||
extern int Num_explosion_options;
|
||||
extern char *Explosion_option[];
|
||||
|
||||
//The E
|
||||
extern int Num_adjust_audio_options;
|
||||
extern char *Adjust_audio_options[];
|
||||
|
||||
/** Global state variables for the hud-display-gauge sexp.
|
||||
They all should be named Sexp_hud_display_*;
|
||||
They all should follow the following symantics for the value of the
|
||||
|
||||
@@ -1074,7 +1074,7 @@ void physics_apply_shock(vec3d *direction_vec, float pressure, physics_info *pi,
|
||||
// Warning: Do not change ROTVEL_COLLIDE_WHACK_CONST. This will mess up collision physics.
|
||||
// If you need to change the rotation, change COLLISION_ROTATION_FACTOR in collide_ship_ship.
|
||||
#define ROTVEL_COLLIDE_WHACK_CONST 1.0
|
||||
void physics_collide_whack( vec3d *impulse, vec3d *world_delta_rotvel, physics_info *pi, matrix *orient )
|
||||
void physics_collide_whack( vec3d *impulse, vec3d *world_delta_rotvel, physics_info *pi, matrix *orient, bool is_landing )
|
||||
{
|
||||
vec3d body_delta_rotvel;
|
||||
|
||||
@@ -1095,9 +1095,11 @@ void physics_collide_whack( vec3d *impulse, vec3d *world_delta_rotvel, physics_i
|
||||
update_reduced_damp_timestamp( pi, vm_vec_mag(impulse) );
|
||||
|
||||
// find time for shake from weapon to end
|
||||
int dtime = timestamp_until(pi->afterburner_decay);
|
||||
if (dtime < WEAPON_SHAKE_TIME) {
|
||||
pi->afterburner_decay = timestamp( WEAPON_SHAKE_TIME );
|
||||
if (!is_landing) {
|
||||
int dtime = timestamp_until(pi->afterburner_decay);
|
||||
if (dtime < WEAPON_SHAKE_TIME) {
|
||||
pi->afterburner_decay = timestamp( WEAPON_SHAKE_TIME );
|
||||
}
|
||||
}
|
||||
|
||||
pi->flags |= PF_REDUCED_DAMP;
|
||||
|
||||
@@ -132,7 +132,7 @@ extern void physics_sim_vel(vec3d * position, physics_info * pi, float sim_time,
|
||||
extern void physics_sim_rot(matrix * orient, physics_info * pi, float sim_time );
|
||||
extern void physics_apply_whack(vec3d *force, vec3d *pos, physics_info *pi, matrix *orient, float mass);
|
||||
extern void physics_apply_shock(vec3d *direction_vec, float pressure, physics_info *pi, matrix *orient, vec3d *min, vec3d *max, float radius);
|
||||
extern void physics_collide_whack(vec3d *impulse, vec3d *delta_rotvel, physics_info *pi, matrix *orient);
|
||||
extern void physics_collide_whack(vec3d *impulse, vec3d *delta_rotvel, physics_info *pi, matrix *orient, bool is_landing);
|
||||
int check_rotvel_limit( physics_info *pi );
|
||||
|
||||
|
||||
|
||||
@@ -1498,7 +1498,7 @@ int player_inspect_cargo(float frametime, char *outstr)
|
||||
Assert ( cargo_sip->flags & (SIF_CARGO|SIF_TRANSPORT) );
|
||||
|
||||
if ( cargo_name[0] == '#' )
|
||||
sprintf(outstr, XSTR( "passengers:\n %s", 83), cargo_name+1 );
|
||||
sprintf(outstr, XSTR( "passengers: %s", 83), cargo_name+1 );
|
||||
else
|
||||
sprintf(outstr,XSTR( "cargo: %s", 84), cargo_name );
|
||||
} else {
|
||||
|
||||
@@ -100,7 +100,7 @@ int png_read_header(char *real_filename, CFILE *img_cfp, int *w, int *h, int *bp
|
||||
{
|
||||
mprintf(("png_read_header: error creating info struct\n"));
|
||||
cfclose(png_file);
|
||||
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
return PNG_ERROR_READING;
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ int png_read_header(char *real_filename, CFILE *img_cfp, int *w, int *h, int *bp
|
||||
{
|
||||
mprintf(("png_read_header: something went wrong\n"));
|
||||
/* Free all of the memory associated with the png_ptr and info_ptr */
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
cfclose(png_file);
|
||||
/* If we get here, we had a problem reading the file */
|
||||
return PNG_ERROR_READING;
|
||||
@@ -128,7 +128,7 @@ int png_read_header(char *real_filename, CFILE *img_cfp, int *w, int *h, int *bp
|
||||
png_file = NULL;
|
||||
}
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
|
||||
return PNG_ERROR_NONE;
|
||||
}
|
||||
@@ -183,7 +183,7 @@ int png_read_bitmap(char *real_filename, ubyte *image_data, ubyte *bpp, int dest
|
||||
{
|
||||
mprintf(("png_read_bitmap: info_ptr went wrong\n"));
|
||||
cfclose(png_file);
|
||||
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
return PNG_ERROR_READING;
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ int png_read_bitmap(char *real_filename, ubyte *image_data, ubyte *bpp, int dest
|
||||
{
|
||||
mprintf(("png_read_bitmap: something went wrong\n"));
|
||||
/* Free all of the memory associated with the png_ptr and info_ptr */
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
cfclose(png_file);
|
||||
/* If we get here, we had a problem reading the file */
|
||||
return PNG_ERROR_READING;
|
||||
@@ -199,7 +199,7 @@ int png_read_bitmap(char *real_filename, ubyte *image_data, ubyte *bpp, int dest
|
||||
|
||||
png_set_read_fn(png_ptr, &png_file, png_scp_read_data);
|
||||
|
||||
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_EXPAND, png_voidp_NULL);
|
||||
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_EXPAND, NULL);
|
||||
len = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
row_pointers = png_get_rows(png_ptr, info_ptr);
|
||||
@@ -212,7 +212,7 @@ int png_read_bitmap(char *real_filename, ubyte *image_data, ubyte *bpp, int dest
|
||||
memcpy(&image_data[i * len], row_pointers[i], len);
|
||||
}
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
cfclose(png_file);
|
||||
|
||||
return PNG_ERROR_NONE;
|
||||
|
||||
@@ -312,7 +312,11 @@ void radar_plot_object_orb( object *objp )
|
||||
return;
|
||||
}
|
||||
|
||||
vm_vec_normalize(&pos);
|
||||
if (IS_VEC_NULL_SQ_SAFE(&pos)) {
|
||||
vm_vec_make(&pos, 1.0f, 0.0f, 0.0f);
|
||||
} else {
|
||||
vm_vec_normalize(&pos);
|
||||
}
|
||||
|
||||
float scale = dist / Radar_bright_range;
|
||||
if (scale > 1.25f) scale = 1.25f;
|
||||
|
||||
@@ -112,7 +112,7 @@ void load_shield_hit_bitmap()
|
||||
if ( Shield_ani[i].first_frame < 0 )
|
||||
Int3();
|
||||
*/
|
||||
Assert(Species_info[i].shield_anim.first_frame >= 0);
|
||||
Assertion((Species_info[i].shield_anim.first_frame >= 0), "Error while loading shield hit ani: %s for species: %s\n", Species_info[i].shield_anim.filename, Species_info[i].species_name);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+247
-57
@@ -72,7 +72,9 @@
|
||||
#include "iff_defs/iff_defs.h"
|
||||
#include "network/multiutil.h"
|
||||
#include "network/multimsgs.h"
|
||||
|
||||
#include "autopilot/autopilot.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "object/objcollide.h"
|
||||
|
||||
|
||||
|
||||
@@ -105,8 +107,6 @@ extern void fs2netd_add_table_validation(char *tblname);
|
||||
|
||||
//#define MIN_COLLISION_MOVE_DIST 5.0
|
||||
//#define COLLISION_VEL_CONST 0.1
|
||||
#define COLLISION_FRICTION_FACTOR 0.0 // ratio of maximum friction impulse to repulsion impulse
|
||||
#define COLLISION_ROTATION_FACTOR 1.0 // increase in rotation from collision
|
||||
#define SHIP_REPAIR_SUBSYSTEM_RATE 0.01f
|
||||
|
||||
int Ai_render_debug_flag=0;
|
||||
@@ -235,7 +235,8 @@ flag_def_list Subsystem_flags[] = {
|
||||
{ "no subsystem targeting", MSS_FLAG_NO_SS_TARGETING, 0 },
|
||||
{ "fire on target", MSS_FLAG_FIRE_ON_TARGET, 0 },
|
||||
{ "reset when idle", MSS_FLAG_TURRET_RESET_IDLE, 0 },
|
||||
{ "carry shockwave", MSS_FLAG_CARRY_SHOCKWAVE, 0 }
|
||||
{ "carry shockwave", MSS_FLAG_CARRY_SHOCKWAVE, 0 },
|
||||
{ "allow landing", MSS_FLAG_ALLOW_LANDING, 0 }
|
||||
};
|
||||
|
||||
int Num_subsystem_flags = sizeof(Subsystem_flags)/sizeof(flag_def_list);
|
||||
@@ -283,6 +284,7 @@ flag_def_list Ship_flags[] = {
|
||||
{ "no thruster geometry noise", SIF2_NO_THRUSTER_GEO_NOISE, 1 },
|
||||
{ "intrinsic no shields", SIF2_INTRINSIC_NO_SHIELDS, 1 },
|
||||
{ "no primary linking", SIF2_NO_PRIMARY_LINKING, 1 },
|
||||
{ "no pain flash", SIF2_NO_PAIN_FLASH, 1 },
|
||||
|
||||
// to keep things clean, obsolete options go last
|
||||
{ "ballistic primaries", -1, 255 }
|
||||
@@ -565,6 +567,8 @@ void parse_engine_wash(bool replace)
|
||||
|
||||
char *Warp_types[] = {
|
||||
"Default",
|
||||
"Knossos",
|
||||
"Babylon5",
|
||||
"Galactica",
|
||||
"Homeworld",
|
||||
"Hyperspace",
|
||||
@@ -625,6 +629,7 @@ void init_ship_entry(ship_info *sip)
|
||||
|
||||
sip->type_str = sip->maneuverability_str = sip->armor_str = sip->manufacturer_str = NULL;
|
||||
sip->desc = NULL;
|
||||
sip->tech_title[0] = 0;
|
||||
sip->tech_desc = NULL;
|
||||
sip->ship_length = NULL;
|
||||
sip->gun_mounts = NULL;
|
||||
@@ -698,6 +703,30 @@ void init_ship_entry(ship_info *sip)
|
||||
strcpy_s(sip->shockwave_name,"");*/
|
||||
|
||||
sip->collision_damage_type_idx = -1;
|
||||
sip->collision_physics.both_small_bounce = 5.0; //Retail default collision physics
|
||||
sip->collision_physics.bounce = 5.0;
|
||||
sip->collision_physics.friction = COLLISION_FRICTION_FACTOR;
|
||||
sip->collision_physics.rotation_factor = COLLISION_ROTATION_FACTOR;
|
||||
|
||||
// Default landing parameters
|
||||
sip->collision_physics.landing_max_z = 0.0f;
|
||||
sip->collision_physics.landing_min_z = 0.0f;
|
||||
sip->collision_physics.landing_min_y = 0.0f;
|
||||
sip->collision_physics.landing_max_x = 0.0f;
|
||||
sip->collision_physics.landing_max_angle = 0.0f;
|
||||
sip->collision_physics.landing_min_angle = 0.0f;
|
||||
sip->collision_physics.landing_max_rot_angle = 0.0f;
|
||||
sip->collision_physics.reorient_max_z = 0.0f;
|
||||
sip->collision_physics.reorient_min_z = 0.0f;
|
||||
sip->collision_physics.reorient_min_y = 0.0f;
|
||||
sip->collision_physics.reorient_max_x = 0.0f;
|
||||
sip->collision_physics.reorient_max_angle = 0.0f;
|
||||
sip->collision_physics.reorient_min_angle = 0.0f;
|
||||
sip->collision_physics.reorient_max_rot_angle = 0.0f;
|
||||
sip->collision_physics.reorient_mult = 1.0f;
|
||||
sip->collision_physics.landing_rest_angle = 0.0f;
|
||||
sip->collision_physics.landing_sound_idx = -1;
|
||||
|
||||
sip->debris_min_lifetime = -1.0f;
|
||||
sip->debris_max_lifetime = -1.0f;
|
||||
sip->debris_min_speed = -1.0f;
|
||||
@@ -1134,6 +1163,10 @@ int parse_ship_values(ship_info* sip, bool isTemplate, bool first_time, bool rep
|
||||
}
|
||||
|
||||
|
||||
if (optional_string("+Tech Title:")) {
|
||||
stuff_string(sip->tech_title, F_NAME, NAME_LENGTH);
|
||||
}
|
||||
|
||||
if (optional_string("+Tech Description:")) {
|
||||
stuff_malloc_string(&sip->tech_desc, F_MULTITEXT, NULL, SHIP_MULTITEXT_LENGTH);
|
||||
}
|
||||
@@ -1329,6 +1362,88 @@ int parse_ship_values(ship_info* sip, bool isTemplate, bool first_time, bool rep
|
||||
}
|
||||
}
|
||||
|
||||
if(optional_string("$Collision Physics:"))
|
||||
{
|
||||
if(optional_string("+Bounce:")) {
|
||||
stuff_float(&sip->collision_physics.bounce);
|
||||
}
|
||||
if(optional_string("+Both Small Bounce:")) {
|
||||
stuff_float(&sip->collision_physics.both_small_bounce);
|
||||
}
|
||||
if(optional_string("+Friction:")) {
|
||||
stuff_float(&sip->collision_physics.friction);
|
||||
}
|
||||
if(optional_string("+Rotation Factor:")) {
|
||||
stuff_float(&sip->collision_physics.friction);
|
||||
}
|
||||
if(optional_string("+Landing Max Forward Vel:")) {
|
||||
stuff_float(&sip->collision_physics.landing_max_z);
|
||||
}
|
||||
if(optional_string("+Landing Min Forward Vel:")) {
|
||||
stuff_float(&sip->collision_physics.landing_min_z);
|
||||
}
|
||||
if(optional_string("+Landing Max Descent Vel:")) {
|
||||
stuff_float(&sip->collision_physics.landing_min_y);
|
||||
sip->collision_physics.landing_min_y *= -1;
|
||||
}
|
||||
if(optional_string("+Landing Max Horizontal Vel:")) {
|
||||
stuff_float(&sip->collision_physics.landing_max_x);
|
||||
}
|
||||
if(optional_string("+Landing Max Angle:")) {
|
||||
float degrees;
|
||||
stuff_float(°rees);
|
||||
sip->collision_physics.landing_max_angle = cos(ANG_TO_RAD(90 - degrees));
|
||||
}
|
||||
if(optional_string("+Landing Min Angle:")) {
|
||||
float degrees;
|
||||
stuff_float(°rees);
|
||||
sip->collision_physics.landing_min_angle = cos(ANG_TO_RAD(90 - degrees));
|
||||
}
|
||||
if(optional_string("+Landing Max Rotate Angle:")) {
|
||||
float degrees;
|
||||
stuff_float(°rees);
|
||||
sip->collision_physics.landing_max_rot_angle = cos(ANG_TO_RAD(90 - degrees));
|
||||
}
|
||||
if(optional_string("+Reorient Max Forward Vel:")) {
|
||||
stuff_float(&sip->collision_physics.reorient_max_z);
|
||||
}
|
||||
if(optional_string("+Reorient Min Forward Vel:")) {
|
||||
stuff_float(&sip->collision_physics.reorient_min_z);
|
||||
}
|
||||
if(optional_string("+Reorient Max Descent Vel:")) {
|
||||
stuff_float(&sip->collision_physics.reorient_min_y);
|
||||
sip->collision_physics.reorient_min_y *= -1;
|
||||
}
|
||||
if(optional_string("+Reorient Max Horizontal Vel:")) {
|
||||
stuff_float(&sip->collision_physics.reorient_max_x);
|
||||
}
|
||||
if(optional_string("+Reorient Max Angle:")) {
|
||||
float degrees;
|
||||
stuff_float(°rees);
|
||||
sip->collision_physics.reorient_max_angle = cos(ANG_TO_RAD(90 - degrees));
|
||||
}
|
||||
if(optional_string("+Reorient Min Angle:")) {
|
||||
float degrees;
|
||||
stuff_float(°rees);
|
||||
sip->collision_physics.reorient_min_angle = cos(ANG_TO_RAD(90 - degrees));
|
||||
}
|
||||
if(optional_string("+Reorient Max Rotate Angle:")) {
|
||||
float degrees;
|
||||
stuff_float(°rees);
|
||||
sip->collision_physics.reorient_max_rot_angle = cos(ANG_TO_RAD(90 - degrees));
|
||||
}
|
||||
if(optional_string("+Reorient Speed Mult:")) {
|
||||
stuff_float(&sip->collision_physics.reorient_mult);
|
||||
}
|
||||
if(optional_string("+Landing Rest Angle:")) {
|
||||
float degrees;
|
||||
stuff_float(°rees);
|
||||
sip->collision_physics.landing_rest_angle = cos(ANG_TO_RAD(90 - degrees));
|
||||
}
|
||||
parse_sound("+Landing Sound:", &sip->collision_physics.landing_sound_idx, sip->name);
|
||||
}
|
||||
|
||||
|
||||
if(optional_string("$Debris:"))
|
||||
{
|
||||
if(optional_string("+Min Lifetime:")) {
|
||||
@@ -2827,7 +2942,7 @@ strcpy_s(parse_error_text, temp_error);
|
||||
sp->engine_wash_pointer = get_engine_wash_pointer(name_tmp);
|
||||
|
||||
if(sp->engine_wash_pointer == NULL)
|
||||
Warning(LOCATION,"Invalid engine wash name %s specified for subsystem %s in ship class %s", name_tmp, sp->subobj_name, sip->name);
|
||||
WarningEx(LOCATION,"Invalid engine wash name %s specified for subsystem %s in ship class %s", name_tmp, sp->subobj_name, sip->name);
|
||||
}
|
||||
|
||||
parse_sound("$AliveSnd:", &sp->alive_snd, sp->subobj_name);
|
||||
@@ -2911,6 +3026,10 @@ strcpy_s(parse_error_text, temp_error);
|
||||
|
||||
if (optional_string("$Flags:")) {
|
||||
parse_string_flag_list((int*)&sp->flags, Subsystem_flags, Num_subsystem_flags);
|
||||
|
||||
//If we've set any subsystem as landable, set a ship-info flag as a shortcut for later
|
||||
if (sp->flags & MSS_FLAG_ALLOW_LANDING)
|
||||
sip->flags2 |= SIF2_ALLOW_LANDINGS;
|
||||
}
|
||||
|
||||
if (optional_string("+non-targetable")) {
|
||||
@@ -3661,7 +3780,7 @@ void ship_parse_post_cleanup()
|
||||
// ultra stupid compatbility handling for the once broken "generate hud" flag.
|
||||
// it was previously testing the afterburner flag, so that's what we check for that
|
||||
if ( (sip->shield_icon_index == 255) && (sip->flags & SIF_AFTERBURNER)
|
||||
&& !(sip->flags2 & SIF2_GENERATE_HUD_ICON) )
|
||||
&& !(sip->flags2 & SIF2_GENERATE_HUD_ICON) && (sip->flags & SIF_PLAYER_SHIP) )
|
||||
{
|
||||
Warning(LOCATION, "Compatibility warning:\nNo shield icon specified for '%s' but the \"generate icon\" flag is not specified.\nEnabling flag by default.\n", sip->name);
|
||||
sip->flags2 |= SIF2_GENERATE_HUD_ICON;
|
||||
@@ -4130,6 +4249,8 @@ void ship_set_warp_effects(object *objp, ship_info *sip)
|
||||
switch(sip->warpin_type)
|
||||
{
|
||||
case WT_DEFAULT:
|
||||
case WT_KNOSSOS:
|
||||
case WT_DEFAULT_THEN_KNOSSOS:
|
||||
shipp->warpin_effect = new WE_Default(objp, WD_WARP_IN);
|
||||
break;
|
||||
case WT_IN_PLACE_ANIM:
|
||||
@@ -4151,6 +4272,8 @@ void ship_set_warp_effects(object *objp, ship_info *sip)
|
||||
switch(sip->warpout_type)
|
||||
{
|
||||
case WT_DEFAULT:
|
||||
case WT_KNOSSOS:
|
||||
case WT_DEFAULT_THEN_KNOSSOS:
|
||||
shipp->warpout_effect = new WE_Default(objp, WD_WARP_OUT);
|
||||
break;
|
||||
case WT_IN_PLACE_ANIM:
|
||||
@@ -4850,6 +4973,7 @@ int subsys_set(int objnum, int ignore_subsys_info)
|
||||
ship_system->turret_time_enemy_in_range = 0.0f;
|
||||
ship_system->disruption_timestamp=timestamp(0);
|
||||
ship_system->turret_pick_big_attack_point_timestamp = timestamp(0);
|
||||
ship_system->scripting_target_override = false;
|
||||
vm_vec_zero(&ship_system->turret_big_attack_point);
|
||||
for(j = 0; j < NUM_TURRET_ORDER_TYPES; j++)
|
||||
{
|
||||
@@ -5404,13 +5528,14 @@ void ship_render(object * obj)
|
||||
//it is specified
|
||||
//it isn't assigned already
|
||||
//start sound doesn't exist or has finished
|
||||
if(mtp->loop_snd >= 0
|
||||
&& shipp->thrusters_sounds[i] < 0
|
||||
&& (mtp->start_snd < 0 || (snd_get_duration(mtp->start_snd) < timestamp() - shipp->thrusters_start[i]))
|
||||
)
|
||||
{
|
||||
shipp->thrusters_sounds[i] = obj_snd_assign(OBJ_INDEX(obj), mtp->loop_snd, &mtp->pos, 1);
|
||||
}
|
||||
if (!Cmdline_freespace_no_sound)
|
||||
if(mtp->loop_snd >= 0
|
||||
&& shipp->thrusters_sounds[i] < 0
|
||||
&& (mtp->start_snd < 0 || (snd_get_duration(mtp->start_snd) < timestamp() - shipp->thrusters_start[i]))
|
||||
)
|
||||
{
|
||||
shipp->thrusters_sounds[i] = obj_snd_assign(OBJ_INDEX(obj), mtp->loop_snd, &mtp->pos, 1);
|
||||
}
|
||||
|
||||
//Draw graphics
|
||||
//Skip invalid ones
|
||||
@@ -7671,9 +7796,9 @@ void ship_set_default_weapons(ship *shipp, ship_info *sip)
|
||||
for ( i = sip->num_primary_banks; i < pm->n_guns; i++ ) {
|
||||
// Make unspecified weapon for bank be a laser
|
||||
for ( j = 0; j < Num_player_weapon_precedence; j++ ) {
|
||||
Assert(Player_weapon_precedence[j] > 0);
|
||||
Assertion((Player_weapon_precedence[j] > 0), "Error reading player weapon precedence list. Check weapons.tbl for $Player Weapon Precedence entry, and correct as necessary.\n");
|
||||
int weapon_id = Player_weapon_precedence[j];
|
||||
if (Weapon_info[weapon_id].subtype & (WP_LASER || WP_BEAM)) {
|
||||
if ( (Weapon_info[weapon_id].subtype == WP_LASER) || (Weapon_info[weapon_id].subtype == WP_BEAM) ) {
|
||||
swp->primary_bank_weapons[i] = weapon_id;
|
||||
break;
|
||||
}
|
||||
@@ -7696,7 +7821,7 @@ void ship_set_default_weapons(ship *shipp, ship_info *sip)
|
||||
for ( j = 0; j < Num_player_weapon_precedence; j++ ) {
|
||||
Assert(Player_weapon_precedence[j] > 0);
|
||||
int weapon_id = Player_weapon_precedence[j];
|
||||
if (Weapon_info[weapon_id].subtype & WP_MISSILE) {
|
||||
if (Weapon_info[weapon_id].subtype == WP_MISSILE) {
|
||||
swp->secondary_bank_weapons[i] = weapon_id;
|
||||
break;
|
||||
}
|
||||
@@ -8229,6 +8354,7 @@ void change_ship_type(int n, int ship_type, int by_sexp)
|
||||
ship_info *sip_orig;
|
||||
ship *sp;
|
||||
ship_weapon *swp;
|
||||
ship_subsys *ss;
|
||||
object *objp;
|
||||
p_object *p_objp;
|
||||
float hull_pct, shield_pct;
|
||||
@@ -8240,37 +8366,71 @@ void change_ship_type(int n, int ship_type, int by_sexp)
|
||||
swp = &sp->weapons;
|
||||
sip_orig = &Ship_info[sp->ship_info_index];
|
||||
objp = &Objects[sp->objnum];
|
||||
ph_inf = objp->phys_info;
|
||||
|
||||
// Goober5000 - maintain the original hull and shield percentages when called by sexp
|
||||
if (by_sexp)
|
||||
|
||||
// Goober5000 - maintain the original hull, shield, and subsystem percentages... gah
|
||||
|
||||
// hull
|
||||
if (sp->special_hitpoints) {
|
||||
hull_pct = objp->hull_strength / sp->ship_max_hull_strength;
|
||||
} else {
|
||||
Assert( Ship_info[sp->ship_info_index].max_hull_strength > 0.0f );
|
||||
hull_pct = objp->hull_strength / Ship_info[sp->ship_info_index].max_hull_strength;
|
||||
}
|
||||
|
||||
// extra check
|
||||
Assert(hull_pct > 0.0f && hull_pct <= 1.0f);
|
||||
if (hull_pct <= 0.0f) hull_pct = 0.1f;
|
||||
if (hull_pct > 1.0f) hull_pct = 1.0f;
|
||||
|
||||
// shield
|
||||
if (sp->special_shield > 0) {
|
||||
shield_pct = shield_get_strength(objp) / sp->ship_max_shield_strength;
|
||||
} else if (Ship_info[sp->ship_info_index].max_shield_strength > 0.0f) {
|
||||
shield_pct = shield_get_strength(objp) / Ship_info[sp->ship_info_index].max_shield_strength;
|
||||
} else {
|
||||
shield_pct = 0.0f;
|
||||
}
|
||||
|
||||
// extra check
|
||||
Assert(shield_pct >= 0.0f && shield_pct <= 1.0f);
|
||||
if (shield_pct < 0.0f) shield_pct = 0.0f;
|
||||
if (shield_pct > 1.0f) shield_pct = 1.0f;
|
||||
|
||||
// subsystems
|
||||
int num_saved_subsystems = 0;
|
||||
char **subsys_names = new char *[sip_orig->n_subsystems];
|
||||
float *subsys_pcts = new float[sip_orig->n_subsystems];
|
||||
|
||||
ss = GET_FIRST(&sp->subsys_list);
|
||||
while ( ss != END_OF_LIST(&sp->subsys_list) )
|
||||
{
|
||||
// hull
|
||||
if (sp->special_hitpoints) {
|
||||
hull_pct = objp->hull_strength / sp->ship_max_hull_strength;
|
||||
} else {
|
||||
Assert( Ship_info[sp->ship_info_index].max_hull_strength > 0.0f );
|
||||
hull_pct = objp->hull_strength / Ship_info[sp->ship_info_index].max_hull_strength;
|
||||
if (num_saved_subsystems == sip_orig->n_subsystems)
|
||||
{
|
||||
Error(LOCATION, "Subsystem mismatch while changing ship class from '%s' to '%s'!", sip_orig->name, sip->name);
|
||||
break;
|
||||
}
|
||||
|
||||
// shield
|
||||
if (sp->special_shield > 0) {
|
||||
shield_pct = shield_get_strength(objp) / sp->ship_max_shield_strength;
|
||||
} else if (Ship_info[sp->ship_info_index].max_shield_strength > 0.0f) {
|
||||
shield_pct = shield_get_strength(objp) / Ship_info[sp->ship_info_index].max_shield_strength;
|
||||
} else {
|
||||
shield_pct = 0.0f;
|
||||
}
|
||||
// save subsys information
|
||||
subsys_names[num_saved_subsystems] = new char[NAME_LENGTH];
|
||||
strcpy(subsys_names[num_saved_subsystems], ss->system_info->subobj_name);
|
||||
|
||||
// physics
|
||||
ph_inf = objp->phys_info;
|
||||
if (ss->max_hits > 0.0f)
|
||||
subsys_pcts[num_saved_subsystems] = ss->current_hits / ss->max_hits;
|
||||
else
|
||||
subsys_pcts[num_saved_subsystems] = ss->max_hits;
|
||||
|
||||
// extra check
|
||||
Assert(subsys_pcts[num_saved_subsystems] >= 0.0f && subsys_pcts[num_saved_subsystems] <= 1.0f);
|
||||
if (subsys_pcts[num_saved_subsystems] < 0.0f) subsys_pcts[num_saved_subsystems] = 0.0f;
|
||||
if (subsys_pcts[num_saved_subsystems] > 1.0f) subsys_pcts[num_saved_subsystems] = 1.0f;
|
||||
|
||||
num_saved_subsystems++;
|
||||
ss = GET_NEXT(ss);
|
||||
}
|
||||
// set to 100% otherwise
|
||||
else
|
||||
{
|
||||
hull_pct = 1.0f;
|
||||
shield_pct = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// make sure that shields are disabled/enabled if they need to be - Chief1983
|
||||
if (!Fred_running) {
|
||||
p_objp = mission_parse_get_parse_object(sp->ship_name);
|
||||
@@ -8286,15 +8446,6 @@ void change_ship_type(int n, int ship_type, int by_sexp)
|
||||
}
|
||||
}
|
||||
|
||||
// Goober5000 - extra checks
|
||||
Assert(hull_pct > 0.0f && hull_pct <= 1.0f);
|
||||
Assert(shield_pct >= 0.0f && shield_pct <= 1.0f);
|
||||
if (hull_pct <= 0.0f) hull_pct = 0.1f;
|
||||
if (hull_pct > 1.0f) hull_pct = 1.0f;
|
||||
if (shield_pct < 0.0f) shield_pct = 0.0f;
|
||||
if (shield_pct > 1.0f) shield_pct = 1.0f;
|
||||
|
||||
|
||||
// point to new ship data
|
||||
ship_model_change(n, ship_type);
|
||||
sp->ship_info_index = ship_type;
|
||||
@@ -8346,8 +8497,36 @@ void change_ship_type(int n, int ship_type, int by_sexp)
|
||||
// fix up the subsystems
|
||||
subsys_set( sp->objnum );
|
||||
|
||||
sp->afterburner_fuel = MAX(0, sip->afterburner_fuel_capacity - (sip_orig->afterburner_fuel_capacity - sp->afterburner_fuel));
|
||||
|
||||
// Goober5000 - restore the subsystem percentages
|
||||
|
||||
ss = GET_FIRST(&sp->subsys_list);
|
||||
while ( ss != END_OF_LIST(&sp->subsys_list) )
|
||||
{
|
||||
for (i = 0; i < num_saved_subsystems; i++)
|
||||
{
|
||||
if (!subsystem_stricmp(ss->system_info->subobj_name, subsys_names[i]))
|
||||
{
|
||||
ss->current_hits = ss->max_hits * subsys_pcts[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ss = GET_NEXT(ss);
|
||||
}
|
||||
ship_recalc_subsys_strength(sp);
|
||||
|
||||
// now free the memory
|
||||
for (i = 0; i < sip_orig->n_subsystems; i++)
|
||||
delete[] subsys_names[i];
|
||||
delete [] subsys_names;
|
||||
delete [] subsys_pcts;
|
||||
|
||||
|
||||
// DONE WITH PERCENTAGE STUFF
|
||||
|
||||
|
||||
sp->afterburner_fuel = MAX(0, sip->afterburner_fuel_capacity - (sip_orig->afterburner_fuel_capacity - sp->afterburner_fuel));
|
||||
sp->cmeasure_count = MAX(0, sip->cmeasure_max - (sip_orig->cmeasure_max - sp->cmeasure_count));
|
||||
|
||||
// avoid cases where either of these are 0
|
||||
@@ -10925,7 +11104,7 @@ void ship_model_start(object *objp)
|
||||
case SUBSYSTEM_ACTIVATION:
|
||||
break;
|
||||
case SUBSYSTEM_TURRET:
|
||||
Assert( !(psub->flags & MSS_FLAG_ROTATES) ); // Turrets can't rotate!!! See John!
|
||||
Assertion( !(psub->flags & MSS_FLAG_ROTATES), "Turret %s on ship %s has the $rotate or $triggered subobject property defined. Please fix the model.\n", psub->name, Ship_info[shipp->ship_info_index].name ); // Turrets can't rotate!!! See John!
|
||||
break;
|
||||
default:
|
||||
Error(LOCATION, "Illegal subsystem type.\n");
|
||||
@@ -11867,6 +12046,7 @@ int ship_do_rearm_frame( object *objp, float frametime )
|
||||
|
||||
// function which is used to find a repair ship to repair requester_obj. the way repair ships will work
|
||||
// is:
|
||||
// if repair ship present and ordered to depart, return NULL.
|
||||
// if repair ship present and available, return pointer to that object.
|
||||
// If repair ship present and busy, possibly return that object if he can satisfy the request soon enough.
|
||||
// If repair ship present and busy and cannot satisfy request, return NULL to warp a new one in if below max number
|
||||
@@ -11915,6 +12095,14 @@ object *ship_find_repair_ship( object *requester_obj )
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ship has been ordered to warpout but has not had a chance to
|
||||
process the order.*/
|
||||
Assert( Ships[objp->instance].ai_index != -1 );
|
||||
ai_info* aip = &(Ai_info[Ships[objp->instance].ai_index]);
|
||||
if ( ai_find_goal_index( aip->goals, AI_GOAL_WARP ) != -1 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dist = vm_vec_dist_quick(&objp->pos, &requester_obj->pos);
|
||||
|
||||
if (!(Ai_info[shipp->ai_index].ai_flags & AIF_REPAIRING))
|
||||
@@ -12854,12 +13042,10 @@ int ship_return_subsys_path_normal(ship *shipp, ship_subsys *ss, vec3d *gsubpos,
|
||||
pm = model_get(Ship_info[shipp->ship_info_index].model_num);
|
||||
Assert( pm != NULL );
|
||||
|
||||
if (ss->system_info->path_num > pm->n_paths) {
|
||||
// possibly a bad model?
|
||||
mprintf(("WARNING: Too many paths in '%s'! Max is %i and the requested path was %i for subsystem '%s'!\n", pm->filename, pm->n_paths, ss->system_info->path_num, ss->system_info->subobj_name));
|
||||
// Int3();
|
||||
// possibly a bad model?
|
||||
Assertion(ss->system_info->path_num <= pm->n_paths, "Too many paths in '%s'! Max is %i and the requested path was %i for subsystem '%s'!\n", pm->filename, pm->n_paths, ss->system_info->path_num, ss->system_info->subobj_name);
|
||||
if (ss->system_info->path_num > pm->n_paths)
|
||||
return 1;
|
||||
}
|
||||
|
||||
mp = &pm->paths[ss->system_info->path_num];
|
||||
if ( mp->nverts >= 2 ) {
|
||||
@@ -14731,6 +14917,10 @@ int is_support_allowed(object *objp)
|
||||
{
|
||||
// check updated mission conditions to allow support
|
||||
|
||||
// If running under autopilot support is not allowed
|
||||
if ( AutoPilotEngaged )
|
||||
return 0;
|
||||
|
||||
// none allowed
|
||||
if (The_mission.support_ships.max_support_ships == 0)
|
||||
return 0;
|
||||
|
||||
+53
-7
@@ -259,6 +259,7 @@ typedef struct ship_subsys {
|
||||
float optimum_range;
|
||||
float favor_current_facing;
|
||||
ship_subsys *targeted_subsys; // subsystem this turret is attacking
|
||||
bool scripting_target_override;
|
||||
|
||||
int turret_pick_big_attack_point_timestamp; // Next time to pick an attack point for this turret
|
||||
vec3d turret_big_attack_point; // local coordinate of point for this turret to attack on enemy
|
||||
@@ -815,8 +816,10 @@ extern int ship_find_exited_ship_by_signature( int signature);
|
||||
#define SIF2_NO_THRUSTER_GEO_NOISE (1 << 8) // Echelon9 - No thruster geometry noise.
|
||||
#define SIF2_INTRINSIC_NO_SHIELDS (1 << 9) // Chief - disables shields for this ship even without No Shields in mission.
|
||||
#define SIF2_NO_PRIMARY_LINKING (1 << 10) // Chief - slated for 3.7 originally, but this looks pretty simple to implement.
|
||||
|
||||
#define MAX_SHIP_FLAGS 11 // Number of distinct flags for flags field in ship_info struct
|
||||
#define SIF2_NO_PAIN_FLASH (1 << 11) // The E - disable red pain flash
|
||||
#define SIF2_ALLOW_LANDINGS (1 << 12) // SUSHI: Automatically set if any subsystems allow landings (as a shortcut)
|
||||
// !!! IF YOU ADD A FLAG HERE BUMP MAX_SHIP_FLAGS !!!
|
||||
#define MAX_SHIP_FLAGS 13 // Number of distinct flags for flags field in ship_info struct
|
||||
#define SIF_DEFAULT_VALUE 0
|
||||
#define SIF2_DEFAULT_VALUE 0
|
||||
|
||||
@@ -979,10 +982,51 @@ typedef struct man_thruster {
|
||||
} man_thruster;
|
||||
|
||||
//Warp type defines
|
||||
#define WT_DEFAULT 0
|
||||
#define WT_IN_PLACE_ANIM 1
|
||||
#define WT_SWEEPER 2
|
||||
#define WT_HYPERSPACE 3
|
||||
#define WT_DEFAULT 0
|
||||
#define WT_KNOSSOS 1
|
||||
#define WT_DEFAULT_THEN_KNOSSOS 2
|
||||
#define WT_IN_PLACE_ANIM 3
|
||||
#define WT_SWEEPER 4
|
||||
#define WT_HYPERSPACE 5
|
||||
|
||||
// Holds variables for collision physics (Gets its own struct purely for clarity purposes)
|
||||
// Most of this only really applies properly to small ships
|
||||
typedef struct ship_collision_physics {
|
||||
// Collision physics definitions: how a ship responds to collisions
|
||||
float both_small_bounce; // Bounce factor when both ships are small
|
||||
// This currently only comes into play if one ship is the player...
|
||||
// blame retail for that.
|
||||
float bounce; // Bounce factor for all other cases
|
||||
float friction; // Controls lateral velocity lost when colliding with a large ship
|
||||
float rotation_factor; // Affects the rotational energy of collisions... TBH not sure how.
|
||||
|
||||
// Speed & angle constraints for a smooth landing
|
||||
// Note that all angles are stored as a dotproduct between normalized vectors instead. This saves us from having
|
||||
// to do a lot of dot product calculations later.
|
||||
float landing_max_z;
|
||||
float landing_min_z;
|
||||
float landing_min_y;
|
||||
float landing_max_x;
|
||||
float landing_max_angle;
|
||||
float landing_min_angle;
|
||||
float landing_max_rot_angle;
|
||||
|
||||
// Speed & angle constraints for a "rough" landing (one with normal collision consequences, but where
|
||||
// the ship is still reoriented towards its resting orientation)
|
||||
float reorient_max_z;
|
||||
float reorient_min_z;
|
||||
float reorient_min_y;
|
||||
float reorient_max_x;
|
||||
float reorient_max_angle;
|
||||
float reorient_min_angle;
|
||||
float reorient_max_rot_angle;
|
||||
|
||||
// Landing response parameters
|
||||
float reorient_mult; // How quickly the ship will reorient towards it's resting position
|
||||
float landing_rest_angle; // The vertical angle where the ship's orientation comes to rest
|
||||
int landing_sound_idx; //Sound to play on successful landing collisions
|
||||
|
||||
} ship_collision_physics;
|
||||
|
||||
// The real FreeSpace ship_info struct.
|
||||
typedef struct ship_info {
|
||||
@@ -998,6 +1042,7 @@ typedef struct ship_info {
|
||||
char *manufacturer_str; // string used by tooltips
|
||||
char *desc; // string used by tooltips
|
||||
char *tech_desc; // string used by tech database
|
||||
char tech_title[NAME_LENGTH]; // ship's name (in tech database)
|
||||
|
||||
char *ship_length; // string used by multiplayer ship desc
|
||||
char *gun_mounts; // string used by multiplayer ship desc
|
||||
@@ -1053,7 +1098,8 @@ typedef struct ship_info {
|
||||
float max_speed, min_speed, max_accel;
|
||||
|
||||
//Collision
|
||||
int collision_damage_type_idx;
|
||||
int collision_damage_type_idx;
|
||||
ship_collision_physics collision_physics;
|
||||
|
||||
// ship explosion info
|
||||
shockwave_create_info shockwave;
|
||||
|
||||
+13
-13
@@ -3853,18 +3853,14 @@ int WE_Default::warpStart()
|
||||
HUD_printf(NOX("Subspace drive engaged"));
|
||||
}
|
||||
|
||||
int portal_objnum;
|
||||
if (direction == WD_WARP_IN)
|
||||
portal_objnum = shipp->special_warpin_objnum;
|
||||
else if (direction == WD_WARP_OUT)
|
||||
portal_objnum = shipp->special_warpout_objnum;
|
||||
else
|
||||
portal_objnum = -1;
|
||||
|
||||
portal_objp = NULL;
|
||||
if(portal_objnum >= 0 && shipfx_special_warp_objnum_valid(portal_objnum))
|
||||
if ((direction == WD_WARP_IN) && shipfx_special_warp_objnum_valid(shipp->special_warpin_objnum))
|
||||
{
|
||||
portal_objp = &Objects[portal_objnum];
|
||||
portal_objp = &Objects[shipp->special_warpin_objnum];
|
||||
}
|
||||
else if ((direction == WD_WARP_OUT) && shipfx_special_warp_objnum_valid(shipp->special_warpout_objnum))
|
||||
{
|
||||
portal_objp = &Objects[shipp->special_warpout_objnum];
|
||||
}
|
||||
|
||||
float warpout_speed = 0.0f;
|
||||
@@ -3896,7 +3892,7 @@ int WE_Default::warpStart()
|
||||
if (direction == WD_WARP_OUT)
|
||||
{
|
||||
// maybe special warpout
|
||||
int fireball_type = ((portal_objp != NULL) || Cmdline_tbp) ? FIREBALL_KNOSSOS : FIREBALL_WARP;
|
||||
int fireball_type = ((portal_objp != NULL) || (sip->warpout_type == WT_KNOSSOS) || (sip->warpout_type == WT_DEFAULT_THEN_KNOSSOS)) ? FIREBALL_KNOSSOS : FIREBALL_WARP;
|
||||
|
||||
// create fireball
|
||||
warp_objnum = fireball_create(&pos, fireball_type, FIREBALL_WARP_EFFECT, OBJ_INDEX(objp), radius, 1, NULL, warp_time, shipp->ship_info_index, NULL, 0, 0, sip->warpout_snd_start, sip->warpout_snd_end);
|
||||
@@ -3904,7 +3900,7 @@ int WE_Default::warpStart()
|
||||
else if (direction == WD_WARP_IN)
|
||||
{
|
||||
// maybe special warpin
|
||||
int fireball_type = (portal_objp != NULL) ? FIREBALL_KNOSSOS : FIREBALL_WARP;
|
||||
int fireball_type = ((portal_objp != NULL) || (sip->warpin_type == WT_KNOSSOS)) ? FIREBALL_KNOSSOS : FIREBALL_WARP;
|
||||
|
||||
// create fireball
|
||||
warp_objnum = fireball_create(&pos, fireball_type, FIREBALL_WARP_EFFECT, OBJ_INDEX(objp), radius, 0, NULL, warp_time, shipp->ship_info_index, NULL, 0, 0, sip->warpin_snd_start, sip->warpin_snd_end);
|
||||
@@ -3922,8 +3918,11 @@ int WE_Default::warpStart()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// maybe negate if special warp effect
|
||||
fvec = Objects[warp_objnum].orient.vec.fvec;
|
||||
|
||||
// G5K 6/26/2010 this should no longer be needed
|
||||
/*
|
||||
// maybe negate if special warp effect
|
||||
if (portal_objp != NULL)
|
||||
{
|
||||
float dot = vm_vec_dotprod(&fvec, &objp->orient.vec.fvec);
|
||||
@@ -3934,6 +3933,7 @@ int WE_Default::warpStart()
|
||||
vm_vec_negate(&fvec);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
stage_time_start = total_time_start = timestamp();
|
||||
if(direction == WD_WARP_IN)
|
||||
|
||||
@@ -1910,7 +1910,7 @@ static void ship_do_damage(object *ship_obj, object *other_obj, vec3d *hitpos, f
|
||||
// apply pain to me
|
||||
|
||||
// Goober5000: make sure other_obj doesn't cause a read violation!
|
||||
if (other_obj)
|
||||
if (other_obj && !(Ship_info[Ships[Player_obj->instance].ship_info_index].flags2 & SIF2_NO_PAIN_FLASH))
|
||||
{
|
||||
// For the record, ship_hit_pain seems to simply be the red flash that appears
|
||||
// on the screen when you're hit.
|
||||
|
||||
+110
-9
@@ -14,6 +14,7 @@
|
||||
#include "sound/audiostr.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "osapi/osapi.h"
|
||||
#include "globalincs/vmallocator.h"
|
||||
|
||||
#include "gamesnd/gamesnd.h"
|
||||
#include "globalincs/alphacolors.h"
|
||||
@@ -55,6 +56,20 @@ float Master_voice_volume = 0.7f; // range is 0 -> 1, used for all voice playbac
|
||||
|
||||
unsigned int SND_ENV_DEFAULT = 0;
|
||||
|
||||
//For the adjust-audio-volume sexp
|
||||
float aav_voice_volume = 1.0f;
|
||||
float aav_music_volume = 1.0f;
|
||||
float aav_effect_volume = 1.0f;
|
||||
|
||||
struct aav {
|
||||
float start_volume;
|
||||
float delta;
|
||||
float start_time;
|
||||
int delta_time;
|
||||
};
|
||||
|
||||
aav aav_data[3];
|
||||
|
||||
// min volume to play a sound after all volume processing (range is 0.0 -> 1.0)
|
||||
#define MIN_SOUND_VOLUME 0.05f
|
||||
|
||||
@@ -122,6 +137,8 @@ int snd_init()
|
||||
mprintf(("Could not initialize the OGG vorbis converter.\n"));
|
||||
}
|
||||
|
||||
snd_aav_init();
|
||||
|
||||
// Init the audio streaming stuff
|
||||
audiostream_init();
|
||||
|
||||
@@ -180,7 +197,7 @@ void snd_spew_debug_info()
|
||||
int message_sounds = 0;
|
||||
int interface_sounds = 0;
|
||||
int done = 0;
|
||||
int s_idx;
|
||||
size_t s_idx;
|
||||
|
||||
if(!Sound_spew){
|
||||
return;
|
||||
@@ -195,7 +212,7 @@ void snd_spew_debug_info()
|
||||
done = 0;
|
||||
|
||||
// what kind of sound is this
|
||||
for(s_idx=0; s_idx<Num_game_sounds; s_idx++){
|
||||
for(s_idx=0; s_idx < Snds.size(); s_idx++){
|
||||
if(!stricmp(Snds[s_idx].filename, Sounds[idx].filename)){
|
||||
game_sounds++;
|
||||
done = 1;
|
||||
@@ -203,7 +220,7 @@ void snd_spew_debug_info()
|
||||
}
|
||||
|
||||
if(!done){
|
||||
for(s_idx=0; s_idx<Num_game_sounds; s_idx++){
|
||||
for(s_idx=0; s_idx < Snds.size(); s_idx++){
|
||||
if(!stricmp(Snds_iface[s_idx].filename, Sounds[idx].filename)){
|
||||
interface_sounds++;
|
||||
done = 1;
|
||||
@@ -495,9 +512,9 @@ int snd_play( game_snd *gs, float pan, float vol_scale, int priority, bool is_vo
|
||||
|
||||
volume = gs->default_volume * vol_scale;
|
||||
if ( gs->flags&GAME_SND_VOICE ) {
|
||||
volume *= Master_voice_volume;
|
||||
volume *= (Master_voice_volume * aav_voice_volume);
|
||||
} else {
|
||||
volume *= Master_sound_volume;
|
||||
volume *= (Master_sound_volume * aav_effect_volume);
|
||||
}
|
||||
if ( volume > 1.0f )
|
||||
volume = 1.0f;
|
||||
@@ -617,7 +634,7 @@ int snd_play_3d(game_snd *gs, vec3d *source_pos, vec3d *listen_pos, float radius
|
||||
}
|
||||
}
|
||||
|
||||
volume *= Master_sound_volume;
|
||||
volume *= (Master_sound_volume * aav_effect_volume);
|
||||
if ( (volume < MIN_SOUND_VOLUME) && !force) {
|
||||
return -1;
|
||||
}
|
||||
@@ -635,7 +652,7 @@ int snd_play_3d(game_snd *gs, vec3d *source_pos, vec3d *listen_pos, float radius
|
||||
|
||||
handle = ds_play(snd->sid, gs->id_sig, ds_priority(priority), volume / gs->default_volume, pan, looping);
|
||||
} else {
|
||||
handle = ds3d_play(snd->sid, gs->id_sig, source_pos, source_vel, min_range, max_range, looping, (max_volume*Master_sound_volume), volume, ds_priority(priority));
|
||||
handle = ds3d_play(snd->sid, gs->id_sig, source_pos, source_vel, min_range, max_range, looping, (max_volume*Master_sound_volume*aav_effect_volume), volume, ds_priority(priority));
|
||||
}
|
||||
|
||||
return handle;
|
||||
@@ -784,7 +801,7 @@ int snd_play_looping( game_snd *gs, float pan, int start_loop, int stop_loop, fl
|
||||
return -1;
|
||||
|
||||
volume = gs->default_volume * vol_scale;
|
||||
volume *= Master_sound_volume;
|
||||
volume *= (Master_sound_volume * aav_effect_volume);
|
||||
if ( volume > 1.0f )
|
||||
volume = 1.0f;
|
||||
|
||||
@@ -841,7 +858,7 @@ void snd_set_volume( int sig, float volume )
|
||||
return;
|
||||
}
|
||||
|
||||
new_volume = volume * Master_sound_volume;
|
||||
new_volume = volume * (Master_sound_volume * aav_effect_volume);
|
||||
ds_set_volume( channel, new_volume );
|
||||
}
|
||||
|
||||
@@ -1020,6 +1037,11 @@ int snd_get_duration(int snd_id)
|
||||
if ( snd_id < 0 )
|
||||
return 0;
|
||||
|
||||
Assert( !Sounds.empty() );
|
||||
|
||||
if ( Sounds.empty() )
|
||||
return 0;
|
||||
|
||||
return Sounds[snd_id].duration;
|
||||
}
|
||||
|
||||
@@ -1324,8 +1346,13 @@ int sound_env_supported()
|
||||
|
||||
// Called once per game frame
|
||||
//
|
||||
|
||||
void adjust_volume_on_frame(float* volume_now, aav* data);
|
||||
void snd_do_frame()
|
||||
{
|
||||
adjust_volume_on_frame(&aav_music_volume, &aav_data[AAV_MUSIC]);
|
||||
adjust_volume_on_frame(&aav_voice_volume, &aav_data[AAV_VOICE]);
|
||||
adjust_volume_on_frame(&aav_effect_volume, &aav_data[AAV_EFFECTS]);
|
||||
ds_do_frame();
|
||||
}
|
||||
|
||||
@@ -1366,3 +1393,77 @@ int snd_get_samples_per_measure(char *filename, float num_measures)
|
||||
// ok, now return the samples per measure (which is half of bytes_per_measure)
|
||||
return (bytes_per_measure / 2);
|
||||
}
|
||||
|
||||
void snd_adjust_audio_volume(int type, float percent, int time)
|
||||
{
|
||||
Assert( type >= 0 && type < 4 );
|
||||
|
||||
switch (type) {
|
||||
case AAV_MUSIC:
|
||||
aav_data[type].start_volume = aav_music_volume;
|
||||
if (percent < aav_music_volume)
|
||||
aav_data[type].delta = (aav_music_volume - percent) * -1.0f;
|
||||
else
|
||||
aav_data[type].delta = percent - aav_music_volume;
|
||||
break;
|
||||
case AAV_VOICE:
|
||||
aav_data[type].start_volume = aav_voice_volume;
|
||||
if (percent < aav_voice_volume)
|
||||
aav_data[type].delta = (aav_voice_volume - percent) * -1.0f;
|
||||
else
|
||||
aav_data[type].delta = percent - aav_voice_volume;
|
||||
break;
|
||||
case AAV_EFFECTS:
|
||||
aav_data[type].start_volume = aav_effect_volume;
|
||||
if (percent < aav_effect_volume)
|
||||
aav_data[type].delta = (aav_effect_volume - percent) * -1.0f;
|
||||
else
|
||||
aav_data[type].delta = percent - aav_effect_volume;
|
||||
break;
|
||||
}
|
||||
|
||||
aav_data[type].delta_time = time;
|
||||
aav_data[type].start_time = (f2fl(Missiontime) * 1000);
|
||||
}
|
||||
|
||||
void adjust_volume_on_frame(float* volume_now, aav* data)
|
||||
{
|
||||
if (Missiontime == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
if (*volume_now == (data->start_volume + data->delta))
|
||||
return;
|
||||
|
||||
float msMissiontime = (f2fl(Missiontime) * 1000);
|
||||
|
||||
if ( msMissiontime > ( data->start_time + data->delta_time) ) {
|
||||
*volume_now = data->start_volume + data->delta;
|
||||
return;
|
||||
}
|
||||
|
||||
float done = 0.0f;
|
||||
//How much change do we need?
|
||||
if (data->delta_time == 0)
|
||||
done = 1.0f;
|
||||
else
|
||||
done =(float) (msMissiontime - data->start_time)/data->delta_time;
|
||||
|
||||
//apply change
|
||||
*volume_now = data->start_volume + (data->delta * done);
|
||||
CLAMP(*volume_now, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void snd_aav_init()
|
||||
{
|
||||
aav_music_volume = 1.0f;
|
||||
aav_voice_volume = 1.0f;
|
||||
aav_effect_volume = 1.0f;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
aav_data[i].delta = 0.0f;
|
||||
aav_data[i].start_volume = 1.0f;
|
||||
aav_data[i].delta_time = 0;
|
||||
aav_data[i].start_time = 0.0f;
|
||||
}
|
||||
}
|
||||
+14
-2
@@ -28,9 +28,14 @@
|
||||
#define SND_PRIORITY_DOUBLE_INSTANCE 2
|
||||
#define SND_PRIORITY_TRIPLE_INSTANCE 3
|
||||
|
||||
//For the adjust-audio-volume sexp
|
||||
#define AAV_MUSIC 0
|
||||
#define AAV_VOICE 1
|
||||
#define AAV_EFFECTS 2
|
||||
|
||||
typedef struct game_snd
|
||||
{
|
||||
int sig; // number of sound in sounds.tbl (not used)
|
||||
int sig; // index number of sound in as specified in sounds.tbl
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
float default_volume; // range: 0.0 -> 1.0
|
||||
int min, max; // min: distance at which sound will stop getting louder max: distance at which sound is inaudible
|
||||
@@ -62,6 +67,9 @@ 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
|
||||
extern int Snd_hram; // Soundcard memory consumed by sound data
|
||||
extern float aav_voice_volume;
|
||||
extern float aav_music_volume;
|
||||
extern float aav_effect_volume;
|
||||
|
||||
//int snd_load( char *filename, int hardware=0, int three_d=0, int *sig=NULL );
|
||||
int snd_load( game_snd *gs, int allow_hardware_load = 0);
|
||||
@@ -137,6 +145,7 @@ int snd_num_playing();
|
||||
int snd_get_data(int handle, char *data);
|
||||
int snd_size(int handle, int *size);
|
||||
void snd_do_frame();
|
||||
void snd_adjust_audio_volume(int type, float percent, int time);
|
||||
|
||||
// repositioning of the sound buffer pointer
|
||||
void snd_rewind(int snd_handle, game_snd *sg, float seconds); // rewind N seconds from the current position
|
||||
@@ -160,4 +169,7 @@ int sound_env_get(sound_env *se, int preset = -1);
|
||||
int sound_env_disable();
|
||||
int sound_env_supported();
|
||||
|
||||
#endif
|
||||
// adjust-audio-volume
|
||||
void snd_aav_init();
|
||||
|
||||
#endif
|
||||
@@ -424,9 +424,9 @@ int targa_read_header(char *real_filename, CFILE *img_cfp, int *w, int *h, int *
|
||||
cfclose(targa_file);
|
||||
targa_file = NULL;
|
||||
}
|
||||
|
||||
|
||||
if ( (header.pixel_depth != 16) && (header.pixel_depth != 24) && (header.pixel_depth != 32) ) {
|
||||
Int3();
|
||||
Assertion( (header.pixel_depth != 16) && (header.pixel_depth != 24) && (header.pixel_depth != 32), "Invalid colour depth (%d) in header of tga file %s\n", header.pixel_depth, real_filename );
|
||||
return TARGA_ERROR_READING;
|
||||
}
|
||||
|
||||
|
||||
@@ -2763,7 +2763,7 @@ void beam_handle_collisions(beam *b)
|
||||
}
|
||||
|
||||
if (wi->wi_flags & WIF_HUGE) {
|
||||
if (Objects[target].type & OBJ_SHIP) {
|
||||
if (Objects[target].type == OBJ_SHIP) {
|
||||
ship_type_info *sti;
|
||||
sti = ship_get_type_info(&Objects[target]);
|
||||
if (sti->weapon_bools & STI_WEAP_NO_HUGE_IMPACT_EFF)
|
||||
|
||||
@@ -184,8 +184,8 @@ void mflash_page_in(bool load_all)
|
||||
|
||||
// blobs
|
||||
for ( idx = 0; idx < Mflash_info[i].blobs.size(); idx++) {
|
||||
Mflash_info[i].blobs[idx].anim_id = bm_load_animation(Mflash_info[i].blobs[idx].name, &num_frames, &fps, NULL, 1);
|
||||
Assert( Mflash_info[i].blobs[idx].anim_id >= 0 );
|
||||
Mflash_info[i].blobs[idx].anim_id = bm_load_either(Mflash_info[i].blobs[idx].name, &num_frames, &fps, NULL, 1);
|
||||
Assertion( (Mflash_info[i].blobs[idx].anim_id >= 0), "Failed to load muzzle flash animation %s\n", Mflash_info[i].blobs[idx].name );
|
||||
bm_page_in_xparent_texture( Mflash_info[i].blobs[idx].anim_id );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,10 +350,19 @@ void shockwave_move(object *shockwave_objp, float frametime)
|
||||
}
|
||||
|
||||
// blast ships and asteroids
|
||||
// And (some) weapons
|
||||
for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
|
||||
if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_ASTEROID) ) {
|
||||
if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_ASTEROID) && (objp->type != OBJ_WEAPON)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( objp->type == OBJ_WEAPON ) {
|
||||
// only apply to missiles with hitpoints
|
||||
weapon_info* wip = &Weapon_info[Weapons[objp->instance].weapon_info_index];
|
||||
if (wip->weapon_hitpoints <= 0 || !(wip->wi_flags2 & WIF2_TAKES_SHOCKWAVE_DAMAGE))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if ( objp->type == OBJ_SHIP ) {
|
||||
// don't blast navbuoys
|
||||
@@ -392,6 +401,13 @@ void shockwave_move(object *shockwave_objp, float frametime)
|
||||
case OBJ_ASTEROID:
|
||||
asteroid_hit(objp, NULL, NULL, damage);
|
||||
break;
|
||||
case OBJ_WEAPON:
|
||||
objp->hull_strength -= damage;
|
||||
if (objp->hull_strength < 0.0f) {
|
||||
Weapons[objp->instance].lifeleft = 0.01f;
|
||||
Weapons[objp->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Int3();
|
||||
break;
|
||||
|
||||
@@ -104,6 +104,8 @@ extern int Num_weapon_subtypes;
|
||||
#define WIF2_CAPITAL_PLUS (1 << 23) // AI will not use this weapon on fighters or bombers
|
||||
#define WIF2_EXTERNAL_WEAPON_FP (1 << 24) // will try to use external models FPs if possible
|
||||
#define WIF2_EXTERNAL_WEAPON_LNCH (1 << 25) // render external secondary as a launcher
|
||||
#define WIF2_TAKES_BLAST_DAMAGE (1 << 26) // This weapon can take blast damage
|
||||
#define WIF2_TAKES_SHOCKWAVE_DAMAGE (1 << 27) // This weapon can take shockwave damage
|
||||
|
||||
#define WIF_HOMING (WIF_HOMING_HEAT | WIF_HOMING_ASPECT | WIF_HOMING_JAVELIN)
|
||||
#define WIF_LOCKED_HOMING (WIF_HOMING_ASPECT | WIF_HOMING_JAVELIN)
|
||||
|
||||
+21
-7
@@ -632,6 +632,10 @@ void parse_wi_flags(weapon_info *weaponp, int wi_flags, int wi_flags2)
|
||||
weaponp->wi_flags2 |= WIF2_EXTERNAL_WEAPON_FP;
|
||||
else if (!stricmp(NOX("external model launcher"), weapon_strings[i]))
|
||||
weaponp->wi_flags2 |= WIF2_EXTERNAL_WEAPON_LNCH;
|
||||
else if (!stricmp(NOX("takes blast damage"), weapon_strings[i]))
|
||||
weaponp->wi_flags2 |= WIF2_TAKES_BLAST_DAMAGE;
|
||||
else if (!stricmp(NOX("takes shockwave damage"), weapon_strings[i]))
|
||||
weaponp->wi_flags2 |= WIF2_TAKES_SHOCKWAVE_DAMAGE;
|
||||
else
|
||||
Warning(LOCATION, "Bogus string in weapon flags: %s\n", weapon_strings[i]);
|
||||
}
|
||||
@@ -5379,11 +5383,6 @@ int weapon_area_calc_damage(object *objp, vec3d *pos, float inner_rad, float out
|
||||
{
|
||||
float dist, max_dist, min_dist;
|
||||
|
||||
// only blast ships and asteroids
|
||||
if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_ASTEROID)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
max_dist = objp->radius + outer_rad;
|
||||
dist = vm_vec_dist_quick(&objp->pos, pos);
|
||||
if ( (dist > max_dist) || (dist > (limit+objp->radius)) ) {
|
||||
@@ -5477,11 +5476,19 @@ void weapon_do_area_effect(object *wobjp, shockwave_create_info *sci, vec3d *pos
|
||||
Assert(sci->inner_rad != 0);
|
||||
|
||||
// only blast ships and asteroids
|
||||
// And (some) weapons
|
||||
for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
|
||||
if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_ASTEROID) ) {
|
||||
if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_ASTEROID) && (objp->type != OBJ_WEAPON) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( objp->type == OBJ_WEAPON ) {
|
||||
// only apply to missiles with hitpoints
|
||||
weapon_info* wip = &Weapon_info[Weapons[objp->instance].weapon_info_index];
|
||||
if (wip->weapon_hitpoints <= 0 || !(wip->wi_flags2 & WIF2_TAKES_BLAST_DAMAGE))
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( objp->type == OBJ_SHIP ) {
|
||||
// don't blast navbuoys
|
||||
if ( ship_get_SIF(objp->instance) & SIF_NAVBUOY ) {
|
||||
@@ -5504,6 +5511,13 @@ void weapon_do_area_effect(object *wobjp, shockwave_create_info *sci, vec3d *pos
|
||||
case OBJ_ASTEROID:
|
||||
asteroid_hit(objp, NULL, NULL, damage);
|
||||
break;
|
||||
case OBJ_WEAPON:
|
||||
objp->hull_strength -= damage;
|
||||
if (objp->hull_strength < 0.0f) {
|
||||
Weapons[objp->instance].lifeleft = 0.01f;
|
||||
Weapons[objp->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Int3();
|
||||
break;
|
||||
@@ -5883,7 +5897,7 @@ void weapons_page_in()
|
||||
}
|
||||
|
||||
default:
|
||||
Int3(); // Invalid weapon rendering type.
|
||||
Assertion(wip->render_type != WRT_POF && wip->render_type != WRT_LASER, "Weapon %s does not have a valid rendering type. Type passed: %d\n", wip->name, wip->render_type); // Invalid weapon rendering type.
|
||||
}
|
||||
|
||||
wip->external_model_num = -1;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
// Goober5000 - now these warnings will only be disabled when compiling with MSVC :)
|
||||
#if defined _MSC_VER
|
||||
|
||||
// 4002 is too many actual parameters for macro 'Assertion'
|
||||
// 4100 is unreferenced formal parameters,
|
||||
// 4127 is constant conditional (assert)
|
||||
// 4201 nonstandard extension used: nameless struct/union (happens a lot in Windows include headers)
|
||||
@@ -28,7 +29,7 @@
|
||||
// So to disable this, I add in a stub function at the top of each module that does nothing.
|
||||
// 4786 is identifier truncated to 255 characters (happens all the time in Microsoft #includes) -- Goober5000
|
||||
// 4996 deprecated strcpy, strcat, sprintf, etc. (from MSVC 2005) - taylor
|
||||
#pragma warning(disable: 4100 4127 4201 4390 4410 4511 4512 4514 4611 4663 4710 4711 4725 4786 4996)
|
||||
#pragma warning(disable: 4002 4100 4127 4201 4390 4410 4511 4512 4514 4611 4663 4710 4711 4725 4786 4996)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+23257
-4034
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,86 @@
|
||||
## libjpeg/Makefile.am for fs2_open
|
||||
##
|
||||
## $Id: Makefile.am,v 1.4 2005-07-07 16:36:58 taylor Exp $
|
||||
|
||||
|
||||
EXTRA_DIST = README
|
||||
|
||||
|
||||
# D_ variants are defaults and should always be used
|
||||
AM_CFLAGS = @D_CFLAGS@ -Wno-main
|
||||
AM_LDFLAGS = @D_LDFLAGS@
|
||||
|
||||
noinst_LIBRARIES = libjpeg.a
|
||||
|
||||
###############################################################################
|
||||
##
|
||||
## Begin JPEG library
|
||||
##
|
||||
|
||||
libjpeg_a_SOURCES = \
|
||||
cderror.h \
|
||||
cdjpeg.h \
|
||||
jcapimin.c \
|
||||
jcapistd.c \
|
||||
jccoefct.c \
|
||||
jccolor.c \
|
||||
jcdctmgr.c \
|
||||
jchuff.c \
|
||||
jchuff.h \
|
||||
jcinit.c \
|
||||
jcmainct.c \
|
||||
jcmarker.c \
|
||||
jcmaster.c \
|
||||
jconfig_lnx.h \
|
||||
jconfig_vc.h \
|
||||
jcomapi.c \
|
||||
jcparam.c \
|
||||
jcphuff.c \
|
||||
jcprepct.c \
|
||||
jcsample.c \
|
||||
jctrans.c \
|
||||
jdapimin.c \
|
||||
jdapistd.c \
|
||||
jdatadst.c \
|
||||
jdatasrc.c \
|
||||
jdcoefct.c \
|
||||
jdcolor.c \
|
||||
jdct.h \
|
||||
jddctmgr.c \
|
||||
jdhuff.c \
|
||||
jdhuff.h \
|
||||
jdinput.c \
|
||||
jdmainct.c \
|
||||
jdmarker.c \
|
||||
jdmaster.c \
|
||||
jdmerge.c \
|
||||
jdphuff.c \
|
||||
jdpostct.c \
|
||||
jdsample.c \
|
||||
jdtrans.c \
|
||||
jerror.c \
|
||||
jerror.h \
|
||||
jfdctflt.c \
|
||||
jfdctfst.c \
|
||||
jfdctint.c \
|
||||
jidctflt.c \
|
||||
jidctfst.c \
|
||||
jidctint.c \
|
||||
jidctred.c \
|
||||
jinclude.h \
|
||||
jmemansi.c \
|
||||
jmemmgr.c \
|
||||
jmemsys.h \
|
||||
jmorecfg.h \
|
||||
jpegint.h \
|
||||
jpeglib.h \
|
||||
jquant1.c \
|
||||
jquant2.c \
|
||||
jutils.c \
|
||||
jversion.h \
|
||||
transupp.h
|
||||
|
||||
##
|
||||
## End JPEG library
|
||||
##
|
||||
###############################################################################
|
||||
@@ -0,0 +1,77 @@
|
||||
## lua/Makefile.am for fs2_open
|
||||
##
|
||||
## $Id: Makefile.am,v 1.2 2007-01-07 12:39:30 taylor Exp $
|
||||
|
||||
|
||||
# D_ variants are defaults and should always be used
|
||||
AM_CFLAGS = @D_CFLAGS@
|
||||
AM_LDFLAGS = @D_LDFLAGS@
|
||||
|
||||
noinst_LIBRARIES = liblua.a
|
||||
|
||||
###############################################################################
|
||||
##
|
||||
## Begin Lua library
|
||||
##
|
||||
|
||||
liblua_a_SOURCES = \
|
||||
lapi.c \
|
||||
lapi.h \
|
||||
lauxlib.c \
|
||||
lauxlib.h \
|
||||
lbaselib.c \
|
||||
lcode.c \
|
||||
lcode.h \
|
||||
ldblib.c \
|
||||
ldebug.c \
|
||||
ldebug.h \
|
||||
ldo.c \
|
||||
ldo.h \
|
||||
ldump.c \
|
||||
lfunc.c \
|
||||
lfunc.h \
|
||||
lgc.c \
|
||||
lgc.h \
|
||||
linit.c \
|
||||
liolib.c \
|
||||
llex.c \
|
||||
llex.h \
|
||||
llimits.h \
|
||||
lmathlib.c \
|
||||
lmem.c \
|
||||
lmem.h \
|
||||
loadlib.c \
|
||||
lobject.c \
|
||||
lobject.h \
|
||||
lopcodes.c \
|
||||
lopcodes.h \
|
||||
loslib.c \
|
||||
lparser.c \
|
||||
lparser.h \
|
||||
lstate.c \
|
||||
lstate.h \
|
||||
lstring.c \
|
||||
lstring.h \
|
||||
lstrlib.c \
|
||||
ltable.c \
|
||||
ltable.h \
|
||||
ltablib.c \
|
||||
ltests.c \
|
||||
ltm.c \
|
||||
ltm.h \
|
||||
luaconf.h \
|
||||
lua.h \
|
||||
lua.c \
|
||||
lualib.h \
|
||||
lundump.c \
|
||||
lundump.h \
|
||||
lvm.c \
|
||||
lvm.h \
|
||||
lzio.c \
|
||||
lzio.h \
|
||||
print.c
|
||||
|
||||
##
|
||||
## End Lua library
|
||||
##
|
||||
###############################################################################
|
||||
+15
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $
|
||||
** $Id: lcode.c,v 2.25.1.4 2009/06/15 14:12:25 roberto Exp $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -544,15 +544,18 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
|
||||
pc = NO_JUMP; /* always true; do nothing */
|
||||
break;
|
||||
}
|
||||
case VFALSE: {
|
||||
pc = luaK_jump(fs); /* always jump */
|
||||
break;
|
||||
}
|
||||
case VJMP: {
|
||||
invertjump(fs, e);
|
||||
pc = e->u.s.info;
|
||||
break;
|
||||
}
|
||||
case VFALSE: {
|
||||
if (!hasjumps(e)) {
|
||||
pc = luaK_jump(fs); /* always jump */
|
||||
break;
|
||||
}
|
||||
/* else go through */
|
||||
}
|
||||
default: {
|
||||
pc = jumponcond(fs, e, 0);
|
||||
break;
|
||||
@@ -572,14 +575,17 @@ static void luaK_goiffalse (FuncState *fs, expdesc *e) {
|
||||
pc = NO_JUMP; /* always false; do nothing */
|
||||
break;
|
||||
}
|
||||
case VTRUE: {
|
||||
pc = luaK_jump(fs); /* always jump */
|
||||
break;
|
||||
}
|
||||
case VJMP: {
|
||||
pc = e->u.s.info;
|
||||
break;
|
||||
}
|
||||
case VTRUE: {
|
||||
if (!hasjumps(e)) {
|
||||
pc = luaK_jump(fs); /* always jump */
|
||||
break;
|
||||
}
|
||||
/* else go through */
|
||||
}
|
||||
default: {
|
||||
pc = jumponcond(fs, e, 1);
|
||||
break;
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $
|
||||
** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $
|
||||
** Interface from Lua to its debug API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -45,6 +45,7 @@ static int db_setmetatable (lua_State *L) {
|
||||
|
||||
|
||||
static int db_getfenv (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
lua_getfenv(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $
|
||||
** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $
|
||||
** Standard I/O (and system) library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -276,7 +276,10 @@ static int read_number (lua_State *L, FILE *f) {
|
||||
lua_pushnumber(L, d);
|
||||
return 1;
|
||||
}
|
||||
else return 0; /* read fails */
|
||||
else {
|
||||
lua_pushnil(L); /* "result" to be removed */
|
||||
return 0; /* read fails */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loaded 100 of 124 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user