|
| Intro This is a two part tutorial that modifies the blaster to "auto-aim" at enemies (i.e. You aim somewhere close to your enemy, and your blaster automatically adjusts the firing direction to hit the enemy dead on). The first part shows how to install the auto-aim feature. The second part installs a "target indicator", that will show you which enemy your auto-aiming blaster has it's sights on. |
| Tutorial
Code
1. You will have to add a new vector called firevec to the declaration list at the beginning of the function So, vec3_t forward, right; vec3_t start; vec3_t offset; becomes vec3_t forward, right; vec3_t start; vec3_t offset; vec3_t firevec; /*Added: Direction to fire*/ 2. Find the call to the function fire_blaster. replace the line: fire_blaster (ent, start, forward, damage, 1000, effect); witht the lines: /*Added:Get LeadOff for nearest badguy*/ mod_GetLeadoffVec(ent, start, 5000, 1000, false, firevec); fire_blaster (ent, start, firevec, damage, 1000, effect); /*End Modification*/ 3. Now, paste the following code at the top of this "p_weapon.c" file: /*******mod_dist_point_to_line***********
* Simply calculates the distance from a point to a line
* point: the point for which we wish to calculate the distance
* linepoint: a point on the line
* linedir: the direction of the line
*****************************************/
float mod_dist_point_to_line(vec3_t point, vec3_t linepoint, vec3_t linedir)
{
vec3_t temp, temp2;
VectorSubtract(point, linepoint, temp);
CrossProduct(temp, linedir, temp2);
return VectorLength(temp2)/VectorLength(linedir);
}
/*******mod_GetLeadoffVec****************
* Author: Tim Matthews
* NOTE: This Code may be distributed and used freely as long as you give due credit to the author.
*
* Get's the direction in which to shoot at an enemy, taking into account his
* current velocity
*
*Arguments
* self: you
* fireorigin: the point from which the blast originates
* rad: the radius of the bounding sphere. Only consider monsters inside this sphere
* projspeed: the speed of the projectile being fired
* bydist: true if judging best target by distance, otherwise test by angle
* firedir: the direction we want to calculate
*************************************/
edict_t *mod_GetLeadoffVec(edict_t *self, vec3_t fireorigin, float rad, float projspeed, int bydist, vec3_t firedir)
{
edict_t *other; /*any potential target besides yourself*/
edict_t *best /*best victim so far*/;
vec3_t viewvec; /*your line of site*/
vec3_t guessdir;
vec3_t bestvec; /*the best guess for the direction of your blaster fire*/
float bestdist, dist; /*distance of the other guy and the shortest distance encountered*/
vec3_t temp, temp2, otherdir;
float d, t;
double alpha, beta, rho;
double a, b, c, t1, t2;
//gi.dprintf("Checking Targets\n");
AngleVectors (self->client->v_angle, viewvec, NULL, NULL); /*get the view direction*/
best=NULL;
other=findradius(NULL, fireorigin, rad); /*find something*/
while (other) {
if ((other->svflags & SVF_MONSTER) && other->health>0 && other!=self) { /*might have to modify these*/
if (visible(self, other) && infront(self, other)) {
/*player is in front and visible*/
/*calculate lead off*/
VectorSubtract(other->s.origin, other->s.old_origin, otherdir);
alpha=VectorNormalize(otherdir); /*alpha = speed, otherdir=direction vector*/
if (alpha>.05 && projspeed>0) { /*if speed is significant, this value may have to be changed*/
d=mod_dist_point_to_line(fireorigin, other->s.origin, otherdir); /*distance from the firepoint to the
the line on which the enemy is running*/
beta=projspeed; /*our projectile speed*/
VectorSubtract(fireorigin, other->s.origin, temp);
CrossProduct(temp, otherdir, temp2); //temp2 now holds the normal to a plane defined by fireorigin and other->s.origin
CrossProduct(temp2, otherdir, temp);
VectorNormalize(temp); /*temp holds the direction from the point to the line*/
VectorScale(temp, d, guessdir);
VectorAdd(guessdir, fireorigin, guessdir);
VectorSubtract(guessdir, other->s.origin, guessdir);
rho=VectorLength(guessdir); /*the length from other->s.origin to the point where the perpendicular vector from fireorigin intersects*/
/*now, a little quadratic equation solving...*/
a=alpha*alpha-beta*beta;
b=-2*alpha*rho;
c=rho*rho+d*d;
t1=(-b+sqrt(b*b-4*a*c))/(2*a);
t2=(-b-sqrt(b*b-4*a*c))/(2*a);
t=(t1>=0)?t1:t2; /*positive solution is the correct one*/
VectorScale(otherdir, t*alpha, guessdir);
VectorAdd(other->s.origin, guessdir, guessdir);
VectorSubtract(guessdir, fireorigin, guessdir); /*now we have our best guess*/
} else {
/*enemy is standing still, so just get a simple direction vector*/
VectorSubtract(other->s.origin, fireorigin, guessdir);
}
if (bydist) {
dist=guessdir[0]*guessdir[0]+guessdir[1]*guessdir[1]+guessdir[2]*guessdir[2];
if (!best || dist<bestdist) {
best=other;
VectorCopy(guessdir, bestvec);
bestdist=dist;
}
} else {
/*choose best as the person most in front of us*/
VectorNormalize(guessdir);
dist=DotProduct(viewvec, guessdir);
if (!best || dist>bestdist) {
best=other;
VectorCopy(guessdir, bestvec);
bestdist=dist;
}
}
}
}
other=findradius(other, self->s.origin, rad); /*find the next entity*/
}
if (!best) /*No targets aquired, so just fire forward as usual*/
AngleVectors(self->client->v_angle, firedir, NULL, NULL);
else {
//gi.dprintf("Target %s Aquired\n", best->classname);
VectorCopy(bestvec, firedir);
VectorNormalize(firedir);
}
return best;
}
/*Added*/
int i; add the following: /*Added: */ mod_CreateTargetEntity(ent);
|
|
| Ending
|
Tutorial html
coding modified by legion.
If it is created,
then it is copyrighted. Quake 2 Tutorial #6 is (c)1997-98 by Tim Matthews
and the Inside3D staff. The site is hosted by the one and only TeleFragged. Please direct any
flames, comments, or praises to the author. Any and all
information found in this tutorial may
be used in any Quake modification provided that the author and
the Inside3D staff are credited.