From 543dfd9f88b3191f79f9556c45d08f26200bcff8 Mon Sep 17 00:00:00 2001
From: zicodxx <>
Date: Sat, 17 Feb 2007 22:52:23 +0000
Subject: [PATCH] added Alex' patch to add FPS independent and physics homing
missiles - also implemented command-line to switch back to legacy homers
---
d2x.ini | 1 +
dxx-changelog.txt | 8 ++
main/inferno.c | 5 ++
main/laser.c | 200 ++++++++++++++++++++++++++++++----------------
4 files changed, 147 insertions(+), 67 deletions(-)
diff --git a/d2x.ini b/d2x.ini
index 393676e05..234c2312e 100755
--- a/d2x.ini
+++ b/d2x.ini
@@ -7,6 +7,7 @@
;-userdir
set user dir to instead of $HOME/.d2x-rebirth
;-macdata Read (and, for editor, write) mac data files (swap colors)
;-lowmem Lowers animation detail for better performance with low memory
+;-legacyhomers Activate original homing missiles (FPS and physics independent)
Controls:
diff --git a/dxx-changelog.txt b/dxx-changelog.txt
index 9029fc946..2dcb7898f 100755
--- a/dxx-changelog.txt
+++ b/dxx-changelog.txt
@@ -1,5 +1,13 @@
D2X-Rebirth Changelog
+20070217
+--------
+d2x.ini, main/inferno.c, main/laser.c: added Alex' patch to add FPS independent and physics homing missiles - also implemented command-line to switch back to legacy homers
+
+20070214
+--------
+Makefile, SConstruct, arch/sdl/mixdigi.c, arch/sdl/mixmusic.c, include/hmp2mid.h, misc/hmp2mid.c: Going back to PHYSFS_file type (lower-case 'f') for compatibility; Turning off sound debug flags; Optional micro versions (see SConstruct); Makefile emulation for SCons
+
20070211
--------
d2x.ini, main/collide.c, main/collide.h, main/fireball.c, main/inferno.c, main/object.c: improved debris random stuff, added -persistentdebris feature
diff --git a/main/inferno.c b/main/inferno.c
index 044b97c48..27a5131f4 100755
--- a/main/inferno.c
+++ b/main/inferno.c
@@ -165,6 +165,7 @@ extern int Config_vr_type;
extern int Config_vr_resolution;
extern int Config_vr_tracking;
extern int mouselook;
+extern int newhomers;
#ifndef RELEASE
extern int invulnerability;
#endif
@@ -190,6 +191,7 @@ void print_commandline_help()
printf( " -macdata %s\n","Read (and, for editor, write) mac data files (swap colors)");
#endif // defined(EDITOR) || !defined(MACDATA)
printf( " -lowmem %s\n", "Lowers animation detail for better performance with low memory");
+ printf( " -legacyhomers %s\n", "Activate original homing missiles (FPS and physics independent)");
printf( "\n Controls:\n\n");
printf( " -NoJoystick %s\n", "Disables joystick support");
@@ -555,6 +557,9 @@ int main(int argc, char *argv[])
else
mouselook=0;
+ if (FindArg("-legacyhomers"))
+ newhomers = 0;
+
if (FindArg("-persistentdebris"))
persistent_debris=1;
diff --git a/main/laser.c b/main/laser.c
index 6c20992be..7bcff753c 100755
--- a/main/laser.c
+++ b/main/laser.c
@@ -72,6 +72,7 @@ char laser_rcsid[] = "$Id: laser.c,v 1.1.1.1 2006/03/17 19:55:16 zicodxx Exp $";
int Laser_rapid_fire = 0;
+int newhomers = 1;
object *Guided_missile[MAX_PLAYERS]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
int Guided_missile_sig[MAX_PLAYERS]={-1,-1,-1,-1,-1,-1,-1,-1};
@@ -1416,46 +1417,15 @@ void Flare_create(object *obj)
#define HOMING_MISSILE_SCALE 16
-#define LIMIT_HOMERS 1
-#define HOMER_MAX_FPS 30
-#define HOMER_MIN_DELAY (1000 / HOMER_MAX_FPS)
-
//--------------------------------------------------------------------
// Set object *objp's orientation to (or towards if I'm ambitious) its velocity.
void homing_missile_turn_towards_velocity(object *objp, vms_vector *norm_vel)
{
vms_vector new_fvec;
-#ifdef LIMIT_HOMERS
- static time_t last_time = -1;
- static int nFrames = 1;
- time_t this_time, delta_time;
- fix frame_time;
- int fps;
- if (last_time == -1) {
- last_time = clock ();
- frame_time = FrameTime;
- } else {
- nFrames++;
- this_time = clock ();
- delta_time = this_time - last_time;
- if (delta_time < HOMER_MIN_DELAY) {
- return;
- } else {
- fps = (1000 + delta_time / 2) / delta_time;
- frame_time = fps ? (f1_0 + fps / 2) / fps : f1_0;
- // frame_time /= nFrames;
- nFrames = 0;
- last_time = this_time;
- }
- }
-#else
- fix frame_time = FrameTime;
-#endif
-
new_fvec = *norm_vel;
- vm_vec_scale(&new_fvec, frame_time * HOMING_MISSILE_SCALE);
+ vm_vec_scale(&new_fvec, FrameTime * HOMING_MISSILE_SCALE);
vm_vec_add2(&new_fvec, &objp->orient.fvec);
vm_vec_normalize_quick(&new_fvec);
@@ -1465,6 +1435,58 @@ void homing_missile_turn_towards_velocity(object *objp, vms_vector *norm_vel)
vm_vector_2_matrix(&objp->orient, &new_fvec, NULL, NULL);
}
+// *a hack, because weapons must have physics; at least missiles must
+// *that this subroutine would be easy in use, here is used turn radius, and not something else
+// *give here normalized vectors; returns normalized vector too
+void Laser_TurnSpeedLimit(vms_vector* vec_forward, vms_vector* vec_to_target, fix speed, fix turn_radius)
+{
+ fixang allowed_angle;
+ fixang angle_delta;
+ fix temp;
+ fix circle_length;
+ vms_matrix view_mat;
+ vms_matrix rot_mat;
+
+ // get allowed angle
+ circle_length = (fix)(turn_radius * 2 * 3.14159);
+ // get gone distance
+ temp = fixmul(speed, FrameTime);
+ // look, which angle such distance will be on the circle
+ temp = fixdiv(temp, circle_length);
+ // however it will be, but not too much, for this one frame
+
+ allowed_angle = temp <= 0x1000 ? temp : 0x1000; // 0x1000: not more that 90 / 4 degrees
+
+ angle_delta = vm_vec_delta_ang_norm (vec_forward, vec_to_target, NULL);
+
+ if (angle_delta && angle_delta > allowed_angle)
+ {
+ vms_angvec tangles;
+ vms_matrix new_orient;
+
+ // imagine view matrix (which will not have anything common with real view matrix of weapon)
+ // matrix must be such, that we would rotate (home) at right side
+ view_mat.fvec = *vec_forward;
+ vm_vec_crossprod (&view_mat.uvec, vec_forward, vec_to_target);
+ vm_vec_normalize (&view_mat.uvec);
+ vm_vec_crossprod (&view_mat.rvec, &view_mat.uvec, vec_forward);
+ vm_vec_normalize (&view_mat.rvec);
+
+ tangles.p = 0;
+ // turn to the right, as we were arranged above
+ tangles.h = allowed_angle;
+ tangles.b = 0;
+
+ // copied from 'do_physics_sim_rot ()'
+ vm_angles_2_matrix (&rot_mat, &tangles);
+ vm_matrix_x_matrix (&new_orient, &view_mat, &rot_mat);
+ *vec_forward = new_orient.fvec;
+ }
+ else
+ // time was enough to finish homing turn till the end
+ *vec_forward = *vec_to_target;
+}
+
//-------------------------------------------------------------------------------------------
//sequence this laser object for this _frame_ (underscores added here to aid MK in his searching!)
void Laser_do_weapon_sequence(object *obj)
@@ -1565,43 +1587,87 @@ void Laser_do_weapon_sequence(object *obj)
}
if (track_goal != -1) {
- vm_vec_sub(&vector_to_object, &Objects[track_goal].pos, &obj->pos);
-
- vm_vec_normalize_quick(&vector_to_object);
- temp_vec = obj->mtype.phys_info.velocity;
- speed = vm_vec_normalize_quick(&temp_vec);
- max_speed = Weapon_info[obj->id].speed[Difficulty_level];
- if (speed+F1_0 < max_speed) {
- speed += fixmul(max_speed, FrameTime/2);
- if (speed > max_speed)
- speed = max_speed;
- }
-
- // -- dot = vm_vec_dot(&temp_vec, &vector_to_object);
-//mprintf((0, " dot=%5.2f ", f2fl(dot)));
- vm_vec_add2(&temp_vec, &vector_to_object);
- // The boss' smart children track better...
- if (Weapon_info[obj->id].render_type != WEAPON_RENDER_POLYMODEL)
- vm_vec_add2(&temp_vec, &vector_to_object);
- vm_vec_normalize_quick(&temp_vec);
- obj->mtype.phys_info.velocity = temp_vec;
- vm_vec_scale(&obj->mtype.phys_info.velocity, speed);
-
- // Subtract off life proportional to amount turned.
- // For hardest turn, it will lose 2 seconds per second.
+ if (newhomers)
{
- fix lifelost, absdot;
-
- absdot = abs(F1_0 - dot);
-
- lifelost = fixmul(absdot*32, FrameTime);
- obj->lifeleft -= lifelost;
- // -- mprintf((0, "Missile %3i, dot = %7.3f life lost = %7.3f, life left = %7.3f\n", obj-Objects, f2fl(dot), f2fl(lifelost), f2fl(obj->lifeleft)));
- }
+ fix turn_radius;
+
+ turn_radius = 0x0014 * F1_0;
+ vm_vec_sub(&vector_to_object, &Objects[track_goal].pos, &obj->pos);
+
+ // we need normalized exact vectors here
+ vm_vec_normalize (&vector_to_object);
+ temp_vec = obj->mtype.phys_info.velocity;
+ // gives magnitude
+ speed = vm_vec_normalize (&temp_vec);
+ // homing missile speeds : insane - 0x005a
+ max_speed = Weapon_info[obj->id].speed[Difficulty_level];
+
+ if (speed + F1_0 < max_speed)
+ {
+ speed += fixmul(max_speed, FrameTime/2);
+ if (speed > max_speed)
+ speed = max_speed;
+ }
+
+ dot = vm_vec_dot(&temp_vec, &vector_to_object);
+
+ Laser_TurnSpeedLimit(&temp_vec, &vector_to_object, speed, turn_radius);
+ obj->mtype.phys_info.velocity = temp_vec;
+ // orient it directly by movement vector
+ vm_vector_2_matrix (&obj->orient, &temp_vec, NULL, NULL);
+ // apply speed
+ vm_vec_scale (&temp_vec, speed);
+ obj->mtype.phys_info.velocity = temp_vec;
+
+
+ // Subtract off life proportional to amount turned.
+ // For hardest turn, it will lose 2 seconds per second.
+ {
+ fix lifelost, absdot;
+
+ absdot = abs(F1_0 - dot);
+
+ lifelost = fixmul(absdot*32, FrameTime);
+ }
+ } else {
+ vm_vec_sub(&vector_to_object, &Objects[track_goal].pos, &obj->pos);
- // Only polygon objects have visible orientation, so only they should turn.
- if (Weapon_info[obj->id].render_type == WEAPON_RENDER_POLYMODEL)
- homing_missile_turn_towards_velocity(obj, &temp_vec); // temp_vec is normalized velocity.
+ vm_vec_normalize_quick(&vector_to_object);
+ temp_vec = obj->mtype.phys_info.velocity;
+ speed = vm_vec_normalize_quick(&temp_vec);
+ max_speed = Weapon_info[obj->id].speed[Difficulty_level];
+ if (speed+F1_0 < max_speed) {
+ speed += fixmul(max_speed, FrameTime/2);
+ if (speed > max_speed)
+ speed = max_speed;
+ }
+
+ // -- dot = vm_vec_dot(&temp_vec, &vector_to_object);
+ //mprintf((0, " dot=%5.2f ", f2fl(dot)));
+ vm_vec_add2(&temp_vec, &vector_to_object);
+ // The boss' smart children track better...
+ if (Weapon_info[obj->id].render_type != WEAPON_RENDER_POLYMODEL)
+ vm_vec_add2(&temp_vec, &vector_to_object);
+ vm_vec_normalize_quick(&temp_vec);
+ obj->mtype.phys_info.velocity = temp_vec;
+ vm_vec_scale(&obj->mtype.phys_info.velocity, speed);
+
+ // Subtract off life proportional to amount turned.
+ // For hardest turn, it will lose 2 seconds per second.
+ {
+ fix lifelost, absdot;
+
+ absdot = abs(F1_0 - dot);
+
+ lifelost = fixmul(absdot*32, FrameTime);
+ obj->lifeleft -= lifelost;
+ // -- mprintf((0, "Missile %3i, dot = %7.3f life lost = %7.3f, life left = %7.3f\n", obj-Objects, f2fl(dot), f2fl(lifelost), f2fl(obj->lifeleft)));
+ }
+
+ // Only polygon objects have visible orientation, so only they should turn.
+ if (Weapon_info[obj->id].render_type == WEAPON_RENDER_POLYMODEL)
+ homing_missile_turn_towards_velocity(obj, &temp_vec); // temp_vec is normalized velocity.
+ }
}
}