Well, I've got a similar setup that thought did the same thing. But it seems the way I'm adjusting the speed and trajectory is not really working. Here is some code:
This function below gets called from the G_RunMissile function if the missile impacts with another in the G_MissileImpact function (turning on it's self->strugglingAttack qboolean). If the boolean is true it runs the function from G_RunMissile basically so it gets called every frame it's struggling. 
 
This is where we try to calculate it's power (and speed) against the other missile's.
Code: Select all
void G_PowerStruggleUserWeapon(gentity_t *self, gentity_t *other, trace_t *trace) {
	int difference1,difference2,power1,power2,speed1,speed2;
	float speedScale1,speedScale2;
	speed1 = self->speed;
	speed2 = other->speed;
	power1 = self->powerLevel;
	power2 = other->powerLevel;
	difference1 = power1-power2;
	difference2 = power2-power1;
	if(difference1 > 0){
		speedScale1 = ((float)difference1 / (float)power2);
		speedScale2 = -((float)(speed1 * speedScale1) / (float)speed2);
	}
	else if(difference2 > 0){
		speedScale2 = ((float)difference2 / (float)power1);
		speedScale1 = -((float)(speed2 * speedScale2) / (float)speed1);
	}
	else{
		speedScale1 = 0;
		speedScale2 = 0;
	}
	// Don't go zipping away at light speed now!
	if(speedScale1 > 1){speedScale1 = 1;}
	if(speedScale1 < -1){speedScale1 = -1;}
	self->bounceFrac = speedScale1;
	// If both attacks are missiles and are equal in power, make them bounce off each other instead.
	if(speedScale1 == 0 && speedScale2 == 0 && self->s.eType == ET_MISSILE && other->s.eType == ET_MISSILE){
		self->bounceFrac = 1;
		self->r.ownerNum = other->s.number;
		G_BounceUserMissile(self, trace);
		self->strugglingAttack = qfalse;
	}else{
		G_StruggleUserMissile(self,other,trace);
	}
	//G_Printf("Attack Owner: %i Speed Scale %f Speed %f Power: %i Difference: %i\n", self->s.clientNum, speedScale1, self->speed, self->powerLevel, difference1);
}
And this is how we determine how to move it and stuff ... I'm sure this code could look a lot smaller and neater, but it's a mess as I try to frustratingly get it working right :P
Code: Select all
static void G_StruggleUserMissile( gentity_t *self, gentity_t *other, trace_t *trace ) {
	vec3_t	velocity;
	vec3_t	dir;
	float	dot;
	int		hitTime;
	//if(self->client->ps.bitFlags & usingBoost && self->s.eType == ET_BEAMHEAD){
	//	self->bounceFrac += 1.0 - (self->client->ps.powerLevel[plMaximum] / self->client->ps.powerLevel[plCurrent]);
	//}
	if(self->bounceFrac > other->bounceFrac){
		if(self->s.eType == ET_MISSILE){
			VectorCopy(self->s.angles,dir);
		}else{
			VectorCopy(self->client->ps.viewangles,dir);
		}
		hitTime = level.previousTime + ( level.time - level.previousTime ) * trace->fraction;
		BG_EvaluateTrajectoryDelta( &self->s, &self->s.pos, hitTime, velocity );
		dot = DotProduct( velocity, dir );
		VectorMA( velocity, -2 * dot, dir, self->s.pos.trDelta );
		VectorScale( self->s.pos.trDelta, self->bounceFrac, self->s.pos.trDelta );
		VectorAdd( self->r.currentOrigin, dir, self->r.currentOrigin);
		VectorCopy( self->r.currentOrigin, self->s.pos.trBase );
	}else if(other->s.eType == ET_MISSILE || other->s.eType == ET_BEAMHEAD){
		self->r.ownerNum = other->s.number;
		VectorCopy( other->s.pos.trDelta, self->s.pos.trDelta );
		VectorCopy( other->r.currentOrigin, self->s.pos.trBase );
	}
	self->s.pos.trTime = level.time;
	// check for stop
	if ( self->s.eType == ET_MISSILE && other->s.eType == ET_MISSILE && VectorLength( self->s.pos.trDelta ) < 40 ) {
		G_ExplodeUserWeapon ( self );
		return;
	}
}