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;
}
}