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?)