Tremulous Forum
Mods => Modding Center => Topic started by: Redman on September 18, 2009, 09:51:43 pm
-
Hello.
I'm trying to make a little mod for my server. I started with new buildable. It's normal trapper, but it kills.
The problem is I want to remove its prediction. I really don't know how this piece of code works, so i'm asking your for help :)
//==================================================================================
#define ARET_ACCURACY 10 // lower is better
/*
================
Aret_FireOnEnemy
Used by Aret_Think to fire at enemy
================
*/
void Aret_FireOnEnemy( gentity_t *self, int firespeed, float range )
{
gentity_t *enemy = self->enemy;
vec3_t dirToTarget;
vec3_t halfAcceleration, thirdJerk;
float distanceToTarget = BG_FindRangeForBuildable( self->s.modelindex );
int lowMsec = 0;
int highMsec = (int)( (
( ( distanceToTarget * ARETM_SPEED ) +
( distanceToTarget * BG_FindSpeedForClass( enemy->client->ps.stats[ STAT_PCLASS ] ) ) ) /
( LOCKBLOB_SPEED * ARETM_SPEED ) ) * 1000.0f );
VectorScale( enemy->acceleration, 1.0f / 2.0f, halfAcceleration );
VectorScale( enemy->jerk, 1.0f / 3.0f, thirdJerk );
// highMsec and lowMsec can only move toward
// one another, so the loop must terminate
while( highMsec - lowMsec > ARET_ACCURACY )
{
int partitionMsec = ( highMsec + lowMsec ) / 2;
float time = (float)partitionMsec / 1000.0f;
float projectileDistance = ARETM_SPEED * time;
VectorMA( enemy->s.pos.trBase, time, enemy->s.pos.trDelta, dirToTarget );
VectorMA( dirToTarget, time * time, halfAcceleration, dirToTarget );
VectorMA( dirToTarget, time * time * time, thirdJerk, dirToTarget );
VectorSubtract( dirToTarget, self->s.pos.trBase, dirToTarget );
distanceToTarget = VectorLength( dirToTarget );
if( projectileDistance < distanceToTarget )
lowMsec = partitionMsec;
else if( projectileDistance > distanceToTarget )
highMsec = partitionMsec;
else if( projectileDistance == distanceToTarget )
break; // unlikely to happen
}
VectorNormalize( dirToTarget );
vectoangles( dirToTarget, self->turretAim );
//fire at target
FireWeapon( self );
G_SetBuildableAnim( self, BANIM_ATTACK1, qfalse );
self->count = level.time + firespeed;
}
(note: ARETM_* means its missile, ARET_* the buildable)
Thanks for reading.
-
The key is the loop. It tries to predict the time and position where the trapper projectile hits the enemy if it keeps moving/accelerating in the same way.
It is basically a binary search which checks how far will the enemy be from the trapper at time <time>. If this distance is larger than the distance of the trapper projectile, try a later time, if it is smaller try an earlier time. If it is equal, we found our target.
while( highMsec - lowMsec > ARET_ACCURACY )
{
// always consider the time in the middle of the interval
int partitionMsec = ( highMsec + lowMsec ) / 2;
float time = (float)partitionMsec / 1000.0f;
// the projectile moves at constant speed ARETM_SPEED, so it's distance will be ARETM_SPEED * time
float projectileDistance = ARETM_SPEED * time;
// the enemy may accelerate, so use the speed, acceleration and jerk to predict it's position in dirToTarget
VectorMA( enemy->s.pos.trBase, time, enemy->s.pos.trDelta, dirToTarget );
VectorMA( dirToTarget, time * time, halfAcceleration, dirToTarget );
VectorMA( dirToTarget, time * time * time, thirdJerk, dirToTarget );
// Compute the difference vector and calculate it's length to find the distance of the enemy
VectorSubtract( dirToTarget, self->s.pos.trBase, dirToTarget );
distanceToTarget = VectorLength( dirToTarget );
if( projectileDistance < distanceToTarget )
// the enemy is too far away, we have to find a later time
lowMsec = partitionMsec;
else if( projectileDistance > distanceToTarget )
// the enemy is too near, we have to find an earlier time
highMsec = partitionMsec;
else if( projectileDistance == distanceToTarget )
// GOTCHA!
break; // unlikely to happen
}
The rest is just starting the projectile:
// store the direction for the projectile
VectorNormalize( dirToTarget );
vectoangles( dirToTarget, self->turretAim );
//fire at target
FireWeapon( self );
// start the attack animation
G_SetBuildableAnim( self, BANIM_ATTACK1, qfalse );
// remember time for next shot
self->count = level.time + firespeed;
So if you want to change the prediction, just change the 3 VectorMA instructions. If you keep just the first, you get a simple linear prediction, or you could use VectorCopy(enemy->s.pos.trBase, dirToTarget) to have no prediction at all.
-
//VectorMA( enemy->s.pos.trBase, time, enemy->s.pos.trDelta, dirToTarget );
//VectorMA( dirToTarget, time * time, halfAcceleration, dirToTarget );
//VectorMA( dirToTarget, time * time * time, thirdJerk, dirToTarget );
VectorSubtract( dirToTarget, self->s.pos.trBase, dirToTarget );
distanceToTarget = VectorLength( dirToTarget );
VectorCopy(enemy->s.pos.trBase, dirToTarget);
I think I didn't understand you. In game when it saw me it started shooting somewhere at wall. It killed my egg :( (BTW. How to make projectiles don't damage aliens and their buildings?)