Quake Style - Quake 3 Tutorials
Weapon Mods - Homing Rockets!!
Makes your rocket launcher shoot homing missiles!

I'm sure you'll all love this one. Firstly and most importantly, credit goes out to Chris Hilton for his Quake 2 homing missile tutorial on QDevels, which this one is mainly based off.

Warning: To do this tutorial you will need to have done the FindRadius for Quake 3 and Visible for Quake 3 tutorials. Thankyou :)

Open up g_missile.c. This is the only file we will be changing!
Find the fire_rocket function, take out the old code and insert the new code:

/*
=================
fire_rocket
=================
*/
gentity_t *fire_rocket (gentity_t *self, vec3_t start, vec3_t dir) {
	gentity_t	*bolt;

	VectorNormalize (dir);

	bolt = G_Spawn();
	bolt->classname = "rocket";
	bolt->nextthink = level.time + 10000;
	bolt->think = G_ExplodeMissile;
	bolt->nextthink = level.time + 60;
	bolt->think = G_HomingMissile;
	bolt->s.eType = ET_MISSILE;
	bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
	bolt->s.weapon = WP_ROCKET_LAUNCHER;
	bolt->r.ownerNum = self->s.number;
	bolt->parent = self;
	bolt->damage = 100;
	bolt->splashDamage = 100;
	bolt->splashRadius = 120;
	bolt->methodOfDeath = MOD_ROCKET;
	bolt->splashMethodOfDeath = MOD_ROCKET_SPLASH;
	bolt->clipmask = MASK_SHOT;

	bolt->s.pos.trType = TR_LINEAR;
	bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME;		// move a bit on the very first frame
	VectorCopy( start, bolt->s.pos.trBase );
	VectorScale( dir, 900, bolt->s.pos.trDelta );
	SnapVector( bolt->s.pos.trDelta );			// save net bandwidth
	VectorCopy (start, bolt->r.currentOrigin);

	return bolt;
}

OK. Next, just above that function, insert a new one:

/*
================
G_HomingMissile

================
*/
void G_HomingMissile( gentity_t *ent )
{
	gentity_t	*target = NULL;
	gentity_t	*blip = NULL;
	vec3_t  dir, dir2, blipdir, start;
	vec_t	speed;

	while ((blip = findradius(blip, ent->r.currentOrigin, 1000)) != NULL)
	{
		if (!blip->client)
			continue;
		if (blip == ent->parent)
			continue;
		if (blip->health <= 0)
			continue;
		if (blip->client->sess.sessionTeam == TEAM_SPECTATOR)
			continue;
		if ( (g_gametype.integer == GT_TEAM || g_gametype.integer == GT_CTF) && blip->client->sess.sessionTeam == blip->parent->client->sess.sessionTeam)
			continue;
		if (!visible (ent, blip))
			continue;

		VectorSubtract(blip->r.currentOrigin, ent->r.currentOrigin, blipdir);
		blipdir[2] += 16;
		if ((target == NULL) || (VectorLength(blipdir) < VectorLength(dir)))
		{
			target = blip;
			VectorCopy(blipdir, dir);
		}
	}

	if (target != NULL)
	{
		VectorCopy( ent->r.currentOrigin, start );
		VectorCopy( ent->r.currentAngles, dir2 );

		// target acquired, nudge our direction toward it
		VectorNormalize(dir);
		VectorScale(dir, 0.4, dir);
		VectorAdd(dir, dir2, dir);
		VectorNormalize(dir);

		VectorCopy ( start, ent->s.pos.trBase );
		VectorScale ( dir, 100, ent->s.pos.trDelta );
		SnapVector ( ent->s.pos.trDelta );                      // save net bandwidth
		VectorCopy ( start, ent->r.currentOrigin );
		VectorCopy ( dir, ent->r.currentAngles );
	}

	ent->nextthink = level.time + 20;
}


Alright, that should be it. Compile, and play.

Have fun shooting homing missiles of death.

Update:
I've been having some *ahem* problems with this tutorial. Various problems have been reported. The only thing I can reccomend is to not trust this tutorial completely.
If anybody actually has definite fixes to this then feel free to e-mail me with them. Thanks.

-- Credits:
   Tutorial by (nobody)
   Return to QS Tutorials

-- Important:
   If you do use something from QuakeStyle in your mod, please give us credit.
   Our code is copyrighted, but we give permission to everyone to use it in any way they see fit, as long as we are recognized.